I am setting up a RecyclerView inside a Fragment following the Android docs example here.
I pasted my code below, there is not much. (The only difference is I'm using a Fragment instead of an Activity).
The error I'm getting is:
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
All solutions to this problem online are to add false argument in layout inflation for fragment. But I've already done this, and I still get the error.
My code:
MainActivity
...
mFragmentManager = getSupportFragmentManager();
mFragmentTransaction = mFragmentManager.beginTransaction();
mFragmentTransaction.replace(R.id.containerView,new NewsFragment()).commit();
...
NewsFragment
public class NewsFragment extends Fragment {
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.news_layout,container, false);
mRecyclerView = (RecyclerView) v.findViewById(R.id.my_recycler_view);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new NewsAdapter(new String[]{"hello","world","qwert","test","greg","peck"});
mRecyclerView.setAdapter(mAdapter);
return v;
}
}
NewsAdapter
public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder> {
private String[] mDataset;
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView mTextView;
public ViewHolder(TextView tv) {
super(tv);
mTextView = tv;
}
}
public NewsAdapter(String[] myDataset) {
mDataset = myDataset;
}
#Override
public NewsAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.news_item, parent, false);
TextView tv = (TextView)v.findViewById(R.id.textView2);
ViewHolder vh = new ViewHolder(tv);
return vh;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.mTextView.setText(mDataset[position]);
}
#Override
public int getItemCount() {
return mDataset.length;
}
}
Any help would be hugely appreciated!
The error is on this line:
TextView tv = (TextView)v.findViewById(R.id.textView2);
ViewHolder vh = new ViewHolder(tv);
Change it to:
TextView tv = (TextView)v.findViewById(R.id.textView2);
ViewHolder vh = new ViewHolder(v);
The text view is already having a parent. That's why you are getting this error.
Updated code:
public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder> {
private String[] mDataset;
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView mTextView;
public ViewHolder(View view) {
super(tv);
mTextView= (TextView)view.findViewById(R.id.textView2);
}
}
public NewsAdapter(String[] myDataset) {
mDataset = myDataset;
}
#Override
public NewsAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.news_item, parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.mTextView.setText(mDataset[position]);
}
#Override
public int getItemCount() {
return mDataset.length;
}
}
Related
I'm new to android studio . I'm trying to display items in RecycleView but it's doesn't show anything.
This is what android studio says:
E/RecyclerView: No layout manager attached; skipping layout
My Fragment :
public class Articles extends Fragment {
View root;
RecyclerView recyclerView;
NewsList[] myListData = new NewsList[] {
new NewsList("Article 1", "Some Author"),
new NewsList("Article2", "Some Author"),
new NewsList("Article3", "Some Author"),
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
root = inflater.inflate(R.layout.fragment_articles, container, false);
recyclerView = root.findViewById(R.id.recyclerView);
NewsAdapter adapter = new NewsAdapter(myListData);
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(adapter);
return root;
}
Here is the code of my Adapter class :
public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder> {
private NewsList[] listdata;
// RecyclerView recyclerView;
public NewsAdapter(NewsList[] listdata) {
this.listdata = listdata;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View listItem= layoutInflater.inflate(R.layout.list_item, parent, false);
ViewHolder viewHolder = new ViewHolder(listItem);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
final NewsList myListData = listdata[position];
holder.textView1.setText(listdata[position].getTitle());
holder.textView2.setText(listdata[position].getAuthor());
holder.relativeLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(view.getContext(),"click on item: "+myListData.getTitle(),Toast.LENGTH_LONG).show();
}
});
}
#Override
public int getItemCount() {
return listdata.length;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView textView1;
public TextView textView2;
public RelativeLayout relativeLayout;
public ViewHolder(View itemView) {
super(itemView);
this.textView1 = (TextView) itemView.findViewById(R.id.textView1);
this.textView2 = (TextView) itemView.findViewById(R.id.textView2);
relativeLayout = (RelativeLayout)itemView.findViewById(R.id.relativeLayout);
}
}
Previously I had an error where the app crashed when opened the fragment but now it's skips the RecyclerView.
I will be gratefull if you help me to resolve this issue.
You need to add a layoutManager to your recycler view:
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
root = inflater.inflate(R.layout.fragment_articles, container, false);
recyclerView = root.findViewById(R.id.recyclerView);
NewsAdapter adapter = new NewsAdapter(myListData);
recyclerView.setHasFixedSize(true);
// Add this line
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()))
recyclerView.setAdapter(adapter);
return root;
}
It's mandatory to have a Layout manager for your Recyclerview. For example, you can use a linear one by adding this after inflating your view :
recyclerView.setLayoutManager(new LinearLayoutManager( context ));
where context is whatever your context is
I'm trying to figure out how to do this in the most simple way possible. Setting the recycler view to wrap the content of course, adjusts the recycler to the biggest item. Setting it to match_parent adjusts all the items to be the maximum at all times.
Setting the maximum width in the Adapter makes all the items be that size no matter what. Dumbfounded at the moment.
My Adapter class
public class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.MessageViewHolder> {
private ArrayList<Message> messageList;
private Context context;
private MessageSelectListener messageSelectListener;
public MessageAdapter(Context context, ArrayList<Message> messageList){
this.messageList = messageList;
this.context = context;
}
//Create an interface
public interface MessageSelectListener{
void onMessageClick(Message message, int position);
}
public void setMessageClickListener(MessageSelectListener messageSelectListener){
this.messageSelectListener = messageSelectListener;
}
#NonNull
#Override
public MessageViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.message_list, parent, false);
RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
view.setLayoutParams(lp);
//View view = new TextView(context);
//View rootView = LayoutInflater.from(context).inflate(R.layout.order_list, parent, false);
return new MessageViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MessageViewHolder holder, final int position) {
final Message message = messageList.get(position);
holder.text.setText(message.getMessageText());
holder.text.setBackgroundResource(R.drawable.rounded_corner_white_noborder);
// passing Order and Position as parameter to interface method,
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
messageSelectListener.onMessageClick(message, position);
}
});
}
#Override
public int getItemCount() {
return messageList == null ? 0 : messageList.size();
}
public class MessageViewHolder extends RecyclerView.ViewHolder{
public TextView text;
public Message message;
public MessageViewHolder(#NonNull View itemView) {
super(itemView);
text = (TextView) itemView;
}
}
}
The Solution was to change the layout parameters in the onCreateViewHolder() method to WRAP_CONTENT
#NonNull
#Override
public MessageViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.message_list, parent, false);
RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.**WRAP_CONTENT**, ViewGroup.LayoutParams.WRAP_CONTENT);
view.setLayoutParams(lp);
//View view = new TextView(context);
//View rootView = LayoutInflater.from(context).inflate(R.layout.order_list, parent, false);
return new MessageViewHolder(view);
}
I want to make CardViews visible on a RecyclerView inside a Fragment, but all I get is a infinite loading sign and no cardviews are being showed. I'm very new to Android Programming so please be kind..
MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentPage fragment = new FragmentPage();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.placeholder, fragment);
fragmentTransaction.commit();
ViewPager viewpager = findViewById(R.id.viewpager);
viewpager.setOffscreenPageLimit(1);
SwipeAdapter adapter = new SwipeAdapter(getSupportFragmentManager());
viewpager.setAdapter(adapter);
viewpager.setPageTransformer(true, new DepthPageTransformer());
viewpager.setCurrentItem(0);
}
}
This is my Adapter class(I followed a Tutorial)
public class ListAdapterIT extends RecyclerView.Adapter {
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return null;
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
}
#Override
public int getItemCount() {
return 0;
}
private class ListViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private ImageView mImageView;
public ListViewHolder (View itemView) {
super(itemView);
mImageView = itemView.findViewById(R.id.image2);
itemView.setOnClickListener(this);
}
public void BindViewHolder(int position) {
mImageView.setImageResource(OurData.picturePath[position]);
}
public void onClick(View view) {
}
}
}
This is my Fragment I also think the Problem is in that class
public class FragmentPage extends Fragment {
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.page_fragment, container, false);
ArrayList<Integer> items = new ArrayList<>();
items.add(R.layout.example_item);
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.listRecyclerView);
ListAdapterIT listAdapter = new ListAdapterIT() {};
recyclerView.setAdapter(listAdapter);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
return view;
}
}
RecyclerView items not visible
I am using a string array name item test and pass it to String array list, I used the same idea before and was working correctly
listItemsTest = new ArrayList<>(Arrays.asList(itemsTest));
recyclerView = findViewById(R.id.RecycleViewTest);
recycleViewAdapterTest = new RecycleViewAdapterTest(this,listItemsTest);
recyclerView.setAdapter(recycleViewAdapterTest);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
My Adapter
public class RecycleViewAdapterTest extends
RecyclerView.Adapter<RecycleViewAdapterTest.MyViewHolder> {
private ArrayList<String> ListTest;
Context context;
public RecycleViewAdapterTest(Context context, ArrayList<String> listTest) {
this.ListTest = listTest;
this.context = context;
}
#NonNull
#Override
public RecycleViewAdapterTest.MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.test_list,parent,false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(#NonNull RecycleViewAdapterTest.MyViewHolder holder, int position) {
}
#Override
public int getItemCount() {
return ListTest.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
LinearLayout linearLayout;
TextView textView;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
linearLayout = itemView.findViewById(R.id.LLTest);
textView = itemView.findViewById(R.id.textViewTest);
}
}
#Override
public void onBindViewHolder(#NonNull RecycleViewAdapterTest.MyViewHolder holder, int position) {
String value = this.ListTest.get(position);
holder.textView.setText(value);// Try to make the textView public
}
because you need to set list value to viewholder's textview in OnBindViewHolder. :(
I want to make a custom Adapter for my RecyclerView because I need to use a custom method inside who will init my List later when my presenter will be ready:
public void setList(List<Object> data){
this.data = data;
}
This is my not custom interface for my Adapter without implementation.
final class AdapterReviews extends RecyclerView.Adapter<AdapterReviews.ReviewViewHolder> {}
The question is how should be the interface for my custom Adapter?
**public class GetHolidaylistAdapter extends RecyclerView.Adapter<GetHolidaylistAdapter.ViewHolder> {
ArrayList<HashMap<String, String>> arrayList;
public GetHolidaylistAdapter(ArrayList<HashMap<String, String>> arrayList) {
this.arrayList = arrayList;
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView holiyDay_Date_Tv, holidayName_tv, holidayType_tv, day_tv;
public ViewHolder(View itemView) {
super(itemView);
holiyDay_Date_Tv = (TextView) itemView.findViewById(R.id.holiyDay_Date_Tv);
holidayName_tv = (TextView) itemView.findViewById(R.id.holidayName_tv);
holidayType_tv = (TextView) itemView.findViewById(R.id.holidayType_tv);
}
}
#Override
public int getItemCount() {
return arrayList.size();
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
GetHolidaylistAdapter.ViewHolder viewHolder = null;
Log.d(TAG, "Rv_Child_Active.." + viewType);
viewHolder = new GetHolidaylistAdapter.ViewHolder(LayoutInflater.from(parent.getContext()).
inflate(R.layout.holiday_child_rv, parent, false));
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
String date = arrayList.get(position).get(TAG_HOLIDAYDATE);
holder.holidayName_tv.setText(arrayList.get(position).get(TAG_HOLIDAYName));
holder.holiyDay_Date_Tv.setText(arrayList.get(position).get(TAG_HOLIDAYDATE));
holder.holidayType_tv.setText(arrayList.get(position).get(TAG_HOLIDAYtype));
***}
}
recycle_view=(RecyclerView)findViewById(R.id.recycle_view);
linearLayoutManager=new LinearLayoutManager(this);
recycle_view.setLayoutManager(linearLayoutManager);
adapter=new CustomAdapter(modelRecyclerArrayList);
recycle_view.setAdapter(adapter);
RecyclerView recycle_view;
LinearLayoutManager linearLayoutManager;
CustomAdapter adapter;
ArrayList<ModelRecycler> modelRecyclerArrayList = new ArrayList<>();*
A basic RecyclerView CustomAdapter looks like this
public class CustomAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final Context context;
ArrayList<String> list = new ArrayList<>();
public CustomAdapter(Context context, ArrayList<String> list) { // you can pass other parameters in constructor
this.context = context;
this.list = list;
}
private class CustomAdapterItemView extends RecyclerView.ViewHolder {
final TextView textView;
CustomAdapterItemView(final View itemView) {
super(itemView);
textView = (TextView) itemView;
}
void bind(int position) {
textView.setText("");
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new CustomAdapterItemView(LayoutInflater.from(context).inflate(R.layout.item_color, parent, false));
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((CustomAdapterItemView) holder).bind(position);
}
#Override
public int getItemCount() {
return list.size();
}
// Add your other methods here
}
You can check this. Here you have complete example of RecyclerView. It is all made by Google.