I'm trying to implement RecyclerView in an app. I followed the android hive guide but the items won't show. After a lot of checks I still couldn't find the problem.
Do I need to use implementation RecylerView in my build.app I'm using androidX
I'm using this RecylcerView in a fragment not activity
My adapter class:
public class CouponsAdapter extends RecyclerView.Adapter<CouponsAdapter.ViewHolder> {
private List<CouponsModel> couponsList;
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView productIds,couponUsage,couponLimit,couponAmount,couponCode,couponType,date;
public ViewHolder(#NonNull View itemView) {
super(itemView);
productIds=(TextView)itemView.findViewById(R.id.products_ids);
couponUsage=(TextView)itemView.findViewById(R.id.usage_limit);
couponAmount=(TextView)itemView.findViewById(R.id.coupon_amount);
couponCode=(TextView)itemView.findViewById(R.id.coupon_code);
couponType=(TextView)itemView.findViewById(R.id.coupon_type);
date=(TextView)itemView.findViewById(R.id.date);
}
}
public CouponsAdapter (List<CouponsModel> couponsList){
this.couponsList=couponsList;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.coupons_list,parent,false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
CouponsModel couponsModel=couponsList.get(position);
holder.date.setText(couponsModel.getDate());
holder.couponType.setText(couponsModel.getCouponType());
holder.couponCode.setText(couponsModel.getCouponCode());
holder.couponAmount.setText(couponsModel.getCouponAmount());
holder.couponUsage.setText(couponsModel.getCouponUsage());
holder.productIds.setText(couponsModel.getProductIds());
}
#Override
public int getItemCount() {
if(couponsList.size() == 0)
return 1;
return couponsList.size();
}
My fragment :
// Inflate the layout for this fragment
View view= inflater.inflate(R.layout.fragment_coupons, container, false);
recyclerView=view.findViewById(R.id.coupons_recyler_view);
couponsAdapter=new CouponsAdapter(couponsModelList);
recyclerView.setAdapter(couponsAdapter);
int x=32;
couponsModelList.add(new CouponsModel(x,x,x,x,"free50","free",x));
couponsAdapter.notifyDataSetChanged();
return view;
}
You should set Layout Manager to your RecyclerView.
If layout manager is not set, you will get the following error: No layout manager attached; Skipping layout
You are missing Layout-manager .Just add this line to your code.
recyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false));
Related
This question already has an answer here:
showing RecyclerView on fragment with data from Firebase
(1 answer)
Closed 3 years ago.
I am not able to attach the Firestore Recycler Adapter in the fragment.
I googled many things but no good yet.
The fragment is one of the tabs of the bottomtablayout.
The data is retrieved from a single collection. I want represent the list of multlipe-user post in a single view.
I have tried the below code but to no good yet.
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
//just change the fragment_dashboard
//with the fragment you want to inflate
//like if the class is HomeFragment it should have R.layout.home_fragment
//if it is DashboardFragment it should have R.layout.fragment_dashboard
View view = inflater.inflate(R.layout.fragment_home, container, false);
final FragmentActivity c = getActivity();
LinearLayoutManager layoutManager = new LinearLayoutManager(c);
Query query = PostsRef.orderBy("timestamp", Query.Direction.DESCENDING);
FirestoreRecyclerOptions<PostsModel> options = new FirestoreRecyclerOptions.Builder<PostsModel>()
.setQuery(query, PostsModel.class)
.build();
adapter = new PostsAdapter(options);
recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(c));
recyclerView.setAdapter(adapter);
mParent =view.findViewById(R.id.relative_home);
return inflater.inflate(R.layout.fragment_home, null);
}
Adapter Code
public class PostsAdapter extends FirestoreRecyclerAdapter<PostsModel, PostsAdapter.PostsHolder> {
private OnItemClickListener listener;
public PostsAdapter(#NonNull FirestoreRecyclerOptions<PostsModel> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull PostsHolder holder, int position, #NonNull PostsModel model) {
//retrieve the fields here
holder.textViewTitle.setText(model.getPostTitle());
holder.textViewDescription.setText(model.getPostContent());
holder.textViewPriority.setText(String.valueOf(model.getSpinnerC()));
holder.AuthorName.setText(model.getName());
holder.AuthorGender.setText(model.getGender());
}
#NonNull
#Override
public PostsHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.post_list_layout,
parent, false);
return new PostsHolder(v);
}
public void deleteItem(int position) {
getSnapshots().getSnapshot(position).getReference().delete();
}
class PostsHolder extends RecyclerView.ViewHolder {
TextView textViewTitle;
TextView textViewDescription;
TextView textViewPriority;
TextView AuthorName;
TextView AuthorGender;
public PostsHolder(View itemView) {
super(itemView);
textViewTitle = itemView.findViewById(R.id.quote1);
textViewDescription = itemView.findViewById(R.id.name1);
textViewPriority = itemView.findViewById(R.id.timestamp1);
}
}
}
You're inflating the other view in the onCreateView method.
return inflater.inflate(R.layout.fragment_home, null);
Which is the code to obtain a Horizontal RecyclerView of images? I already have the code for horizontal RecyclerView of Strings. I need to have the same but of Images.
I have to create a RecyclerView of 10 horizontal scrollable imageView.
This is my actual code of 10 horizontal TextViews:
public class HorizontalAdapter extends RecyclerView.Adapter<HorizontalAdapter.HorizontalViewHolder> {
private String[] items;
public HorizontalAdapter(String[] items) {
this.items = items;
}
#Override
public HorizontalViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.item_layout_recycler_view_top_10, parent, false);
return new HorizontalViewHolder(view);
}
#Override
public void onBindViewHolder(HorizontalViewHolder holder, int position) {
holder.text.setText(items[position]);
}
#Override
public int getItemCount() {
return items.length;
}
public class HorizontalViewHolder extends RecyclerView.ViewHolder {
TextView text;
public HorizontalViewHolder(View itemView) {
super(itemView);
text = itemView.findViewById(R.id.text_view_top_10_ricette_titolo_ricetta);
} }
}
and I manage it on a Fragment in this way:
RecyclerView list = (RecyclerView) view.findViewById(R.id.recycler_view_ricette_categorie_primi_top_10);
list.setLayoutManager(new LinearLayoutManager(getActivity(),LinearLayoutManager.HORIZONTAL,false));
list.setAdapter(new HorizontalAdapter(new String[]{"Android","Programming","Java","RecyclerView","Layout"}));
How I have to modify this?
Try this make below changes in your HorizontalAdapter
public class HorizontalAdapter extends RecyclerView.Adapter<HorizontalAdapter.HorizontalViewHolder> {
private int[] items;
public HorizontalAdapter(String[] int) {
this.items = items;
}
#Override
public HorizontalViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.item_layout_recycler_view_top_10, parent, false);
return new HorizontalViewHolder(view);
}
#Override
public void onBindViewHolder(HorizontalViewHolder holder, int position) {
holder.image.setImageResource(items[position]);
}
#Override
public int getItemCount() {
return items.length;
}
public class HorizontalViewHolder extends RecyclerView.ViewHolder {
ImageView image;
public HorizontalViewHolder(View itemView) {
super(itemView);
image = itemView.findViewById(R.id.imageviewid);
} }
}
code for RecyclerView
RecyclerView list = (RecyclerView) view.findViewById(R.id.recycler_view_ricette_categorie_primi_top_10);
list.setLayoutManager(new LinearLayoutManager(getActivity(),LinearLayoutManager.HORIZONTAL,false));
list.setAdapter(new HorizontalAdapter(new int[]{R.mipmap.ic_launcher,R.mipmap.ic_launcher,R.mipmap.ic_launcher,R.mipmap.ic_launcher,R.mipmap.ic_launcher}));
NOTE : Your layout (item_layout_recycler_view_top_10) needs to contain a ImageView instead of a TextView
Instead of a recyclerView full of textViews (R.layout.item_layout_recycler_view_top_10) you want images?
Just create another layout which contains an ImageView instead of a TextView in it and use it accordingly to your current solution.
String array change to image url array or drawable image array create and send to adapter and set into imageview.
I've created a recyclerView into a fragment. Everything goes well but when i scroll in the list of elements, the attributes change without reason
Here is the code of the fragment:
public class HistorySectionFragment extends Fragment {
private static final String TAG = HistorySectionFragment.class.getSimpleName();
static ArrayList<String> a;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
RecyclerView recyclerView = (RecyclerView) inflater.inflate(
R.layout.recycler_view, container, false);
ContentAdapter adapter = new ContentAdapter();
recyclerView.setAdapter(adapter);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
return recyclerView;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
static TextView card_title;
static TextView card_text;
public ViewHolder(LayoutInflater inflater, ViewGroup parent) {
super(inflater.inflate(R.layout.item_card, parent, false));
card_title = (TextView)itemView.findViewById(R.id.card_title);
card_text = (TextView)itemView.findViewById(R.id.card_text);
}
}
public static class ContentAdapter extends RecyclerView.Adapter<ViewHolder>{
// Set numbers of Card in RecyclerView.
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()), parent);
}
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
final String name = MainActivity.getTestByPosition(position).getName();
holder.card_title.setText(name);
final String description = MainActivity.getTestByPosition(position).getDescription();
holder.card_text.setText(description);
}
#Override
public int getItemCount() {
return MainActivity.getSize();
}
}
}
The problem is when the recyclerview calls to create new elements.
EDIT:
When i say the attributes change i mean the information of each cardView change doing scroll
I have a feeling the views in your RecyclerView are not stable. When the views get recycled, the ids are being saved and the data is mismatched.
Trying doing this.
recyclerView.setHasStableIds(false);
Firstly why you use inflater for the recyclerview? the best way is to declare your recyclerview in xml file and get the recyclerview via findviewById.
Secondly, what do you mean about the attributes change without reason
And finally:it's not very appreciate to use viewholder and adapter like that,
http://javatechig.com/android/android-recyclerview-example
SOLVED.
The problem was in the recycler and in the viewHolder are both Static classes.
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;
}
}
Im trying to add a listview inside a fragment witch is also inside a tabhost. the app is not crashing or anything, but the list view is not showing anything.
Here is my code:
Class for the tabPager
public class TabPagerAdapter extends FragmentPagerAdapter {
public TabPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
return new FragmentHome();
case 1:
return new FragmentBadges();
case 2:
return new FragmentBenefits();
}
return null;
}
Following is the fragment where I want the listview:
public class FragmentBadges extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_badges_list, null);
BadgesListAdapter adapter = new BadgesListAdapter(this.getActivity(), getCurrentBadges());
ListView badgeslist = (ListView) rootView.findViewById(R.id.badges_list);
badgeslist.setAdapter(adapter);
badgeslist.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
//TODO do some
}
});
return rootView;
}
And following is the adapter:
public class BadgesListAdapter extends ArrayAdapter<String> {
private final Activity context;
private List<Badge> badges;
public BadgesListAdapter(Activity context, List<Badge> badges) {
super(context, R.layout.fragment_badges_listrow);
this.context = context;
this.badges = badges;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView= inflater.inflate(R.layout.fragment_badges_listrow, null, true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.text);
ImageView imageView = (ImageView) rowView.findViewById(R.id.img);
txtTitle.setText(badges.get(position).getName());
imageView.setImageResource(badges.get(position).getDrawableValue());
return rowView;
}
while debugging I found out that the getView method inside the badgesListAdapter is never called.
I have this same code for another app but without the tabpager and there it all works perfectly...
Check whether getCurrentBadges() method not returns empty list. If so there is no data to show in ListView.
I was able to make it work by inhering ListFragment in FragmentBadges, following this tutorial https://www.youtube.com/watch?v=heR4zhj_wV0