This question already has an answer here:
I cant see any FirebaseRecyclerAdapter items on my layout
(1 answer)
Closed 3 years ago.
I am trying to use android studio to get firebase data and display it on the screen. I am trying to display anything that is in the database related to it to a RecyclerView. But the data does not return and nothing displays (no error statement). Any ideas why?
private void firebaseLotSearch() {
Toast.makeText(BuyingParking.this,"Started Search",Toast.LENGTH_LONG).show();
Query query = mUserDatabase.startAt(searchText).endAt(searchText+"\uf8ff");
FirebaseRecyclerOptions<Lot_Location> options =
new FirebaseRecyclerOptions.Builder<Lot_Location>()
.setQuery(query, Lot_Location.class)
.build();
// Lot_Location.class,R.layout.list_layout,LotViewHolder.class,mUserDatabase
FirebaseRecyclerAdapter<Lot_Location,LotViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Lot_Location, LotViewHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull LotViewHolder holder, int position, #NonNull Lot_Location model) {
holder.setDetails(model.getLocation(),model.getAdmin(),model.getPrice());
}
#NonNull
#Override
public LotViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
return null;
}
};
searchParking.setAdapter(firebaseRecyclerAdapter);
}
public class LotViewHolder extends RecyclerView.ViewHolder{
public LotViewHolder(#NonNull View itemView) {
super(itemView);
mView = itemView;
}
public void setDetails(String location,String admin,String price)
{
TextView m_location = (TextView)mView.findViewById(R.id.Lot);
TextView m_admin = (TextView)mView.findViewById(R.id.Admin);
TextView m_price = (TextView)mView.findViewById(R.id.price);
m_location.setText(location);
m_admin.setText(admin);
m_price.setText(price);
}
}
onCreateViewHolder is returning null. You need to return an object of LotViewHolder class.
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View rootView = mInflater.inflate(R.layout.your_item_view, parent, false);
ViewHolder holder = new ViewHolder(rootView);
return holder;
}
Related
I don't know how to write a holder for an image. I already have 2 texts set, but I don't know what the holder for the image should look like. Can you help me tell what the writeup for the image should look like in order for it to appear correctly?
holder.artistImage.setImageResource(model.getArtistImage());
My code:
public class ArtistsAdapter extends FirestoreRecyclerAdapter<ArtistsModel, ArtistsAdapter.holder> {
/**
* Create a new RecyclerView adapter that listens to a Firestore Query. See {#link
* FirestoreRecyclerOptions} for configuration options.
*
* #param options
*/
public ArtistsAdapter(#NonNull FirestoreRecyclerOptions<ArtistsModel> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull holder holder, int position, #NonNull ArtistsModel model) {
holder.artistName.setText(model.getArtistName());
holder.artistClass.setText(model.getArtistClass());
}
#NonNull
#Override
public holder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.artistrow, parent, false);
return new holder(view);
}
class holder extends RecyclerView.ViewHolder{
TextView artistName, artistClass;
ImageView artistImage;
public holder(#NonNull View itemView) {
super(itemView);
View view = itemView;
artistName = view.findViewById(R.id.tvartist_name);
artistClass = view.findViewById(R.id.tvartist_class);
artistImage = view.findViewById(R.id.ivartist_photo);
}
}
You can use a library like Glide or Picasso to load the image from a given URL. Both libraries have lots of extra options for things like making the image round, adding a placeholder image while it loads, or adding an error image to show if it can't load.
With Glide:
You can pass in a context to the adapter constructor, or get it from the holder root view to use with Glide
#Override
protected void onBindViewHolder(#NonNull holder holder, int position, #NonNull ArtistsModel model) {
holder.artistName.setText(model.getArtistName());
holder.artistClass.setText(model.getArtistClass());
Glide.with(holder.itemView)
.load(model.getArtistImage())
.into(holder.artistImage);
}
With Picasso:
#Override
protected void onBindViewHolder(#NonNull holder holder, int position, #NonNull ArtistsModel model) {
holder.artistName.setText(model.getArtistName());
holder.artistClass.setText(model.getArtistClass());
Picasso.get()
.load(model.getArtistImage())
.into(holder.artistImage);
}
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);
}
As I'm new to android, I'm struggling to highlight Recyclerview clicked or current item. I have tried some workarounds but nothing helps. Basically I want to highlight selected item even after it is coming back from respective Fragment. Please check my code and help me to get done. Thanks.
public class ContentaAdapter extends RecyclerView.Adapter<ContentaAdapter.MyViewHolder> {
Context context;
ArrayList<String> ItemTitle;
ArrayList<String> ItemSource;
public ContentaAdapter(Context context, ArrayList<String> ItemTitle, ArrayList<String> ItemSource) {
this.context = context;
this.ItemTitle = ItemTitle;
this.ItemSource = ItemSource;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.home_items_layout, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
holder.ItemTitle.setText(ItemTitle.get(position));
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Fragment contentdisplay = new ViewContentFragment();
Bundle bundle=new Bundle();
bundle.putStringArrayList("ItemTitle",ItemTitle);
bundle.putStringArrayList("ItemSource",ItemSource);
bundle.putInt("position",position);
bundle.putInt("ItemCounts",ItemTitle.size());
contentdisplay.setArguments(bundle);
((MainActivity)context).replaceFragment(contentdisplay);
}
});
}
#Override
public int getItemCount() {
return ItemTitle.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView ItemTitle;
public MyViewHolder(View itemView) {
super(itemView);
ItemTitle = (TextView) itemView.findViewById(R.id.item_title);
}
}
}
you need to to add isSelected state in to your list item data model and change it onClick.
And when you know state you can change background in ViewHolder
if (isSelected) {
// set selected background here
} else {
// set not selected background here
}
And instead of keeping two lists in adapter you should create one with model ArrayList<DataModel> similar to this:
class DataModel {
String ItemTitle;
String ItemSource;
Boolean isSelected;
}
also you shouldn't pass both list to other fragment, instead take only what you need, for example yourList.get(position);
This question already has answers here:
butterknife #OnClick inside ViewHolder in CustomAdapter
(4 answers)
Closed 5 years ago.
What would be the proper way of adding Butter Knife's #OnClick to the view in this method?
private List<Foo> foos;
private RecyclerView recyclerView;
private MapActivity mapView;
#Override
public RecyclerView.ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_foo, parent,
false);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int selectedPosition = recyclerView.getChildAdapterPosition(v);
mapView.onFooSelected(foos.get(selectedPosition));
}
});
return new FooInfoViewHolder(view);
}
The way this question is different is that I want to bind #OnClick to the FooInfoViewHolder itself.
Use ViewHolder class and inside of that class we can handle clicks for butter knife.
Below is the just example for understanding.
public class YourAdapter extends RecyclerView.Adapter<YourAdapter.ViewHolder> {
private List<Data> list;
public YourAdapter(List<Data> list) {
this.list = list;
}
#Override
public YourAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
return new ViewHolder(inflater.inflate(R.layout.list_item_layout, parent, false));
}
#Override
public void onBindViewHolder(YourAdapter.ViewHolder holder, int position) {
Data item = list.get(position);
holder.tvTitle1.setText(item.getTitle1());
}
#Override
public int getItemCount() {
int count = 0;
if (null != list) {
count = list.size();
}
return count;
}
public class ViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.tvVRValue1)
TextView tvTitle1;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
#OnClick(R.id.tvVRValue1)
public void onClickYourFunction(){
//Here your onclick method goes
}
}
}
Hope it will help you. Cheers !!!
I figured out what was wrong. Actually I think it's a slightly different answer than the possible duplicates.
The key was to implement the #OnClick on the ViewHolder ITSELF (not, like in the other question, on children of the view):
private List<Foo> foos;
private RecyclerView recyclerView;
private MapActivity mapView;
#Override
public RecyclerView.ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_foo, parent,
false);
return new FooInfoViewHolder(view);
}
And then the FooInfoViewHolder:
public class FooInfoViewHolder extends RecyclerView.ViewHolder {
#OnClick
public void onClick(View v) {
int selectedPosition = recyclerView.getChildAdapterPosition(v);
mapView.onFooSelected(foos.get(selectedPosition));
}
public FooInfoViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
The adapter was working just fine until I decided to add Native Ads, for that I made 6 changes in the adapter.
added new ViewType (AD_VIEW_TYPE)
added new ViewHolder (NativeExpressAdViewHolder)
changed getItemViewType (made it return AD_VIEW_TYPE at every 8th position)
added a new case in onCreateViewHolder
switch (viewType){
case AD_VIEW_TYPE:
View nativeExpressLayoutView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.native_express_ad_container, parent, false);
return new NativeExpressAdViewHolder(nativeExpressLayoutView);
Added a new case to onBindViewHolder
switch (viewType){
case AD_VIEW_TYPE:
NativeExpressAdViewHolder nativeExpressHolder = (NativeExpressAdViewHolder)holder;
NativeExpressAdView adView = (NativeExpressAdView)arrayList.get(position);
ViewGroup adCardView = (ViewGroup)nativeExpressHolder.itemView;
adCardView.removeAllViews();
if(adView.getParent() != null){
((ViewGroup)adView.getParent()).removeView(adView);
}
adCardView.addView(adView);
break;
Other than the above changes, I also changed my ArrayList<CardSetterGetter> to ArrayList<Object> in Activity and Adapter too.
Now the problem is that when I run the app, it throws NullPointerException.
the logcat says
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
at com.company.appname.adapters.RecyclerViewAdapter$RecyclerViewHolder.<init>(RecyclerViewAdapter.java:186)
at com.company.appname.adapters.RecyclerViewAdapter$RecyclerViewHolder.<init>(RecyclerViewAdapter.java:165)
at com.company.appname.adapters.RecyclerViewAdapter$NativeExpressAdViewHolder.<init>(RecyclerViewAdapter.java:150)
at com.company.appname.adapters.RecyclerViewAdapter.onCreateViewHolder(RecyclerViewAdapter.java:84)
at com.company.appname.adapters.RecyclerViewAdapter.onCreateViewHolder(RecyclerViewAdapter.java:48)
These are the part of my code where the logcat is pointing to
/*Line 48*/public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.RecyclerViewHolder> {
public RecyclerViewAdapter(Context context, ArrayList<Object> arrayList, ArrayList<String> favouriteItemList, int totalCount {...}
#Override
public long getItemId(int position){...}
#Override
public RecyclerViewAdapter.RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType){
case AD_VIEW_TYPE:
View nativeExpressLayoutView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.native_express_ad_container, parent, false);
/*Line 84*/ return new NativeExpressAdViewHolder(nativeExpressLayoutView);
case MENU_ITEM_VIEW_TYPE:
default:
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cards, parent, false);
return new RecyclerViewHolder(view);
}
}
#Override
public void onBindViewHolder(final RecyclerViewHolder holder, final int position){...}
public class NativeExpressAdViewHolder extends RecyclerViewHolder{
NativeExpressAdViewHolder(View view){
/*Line 150*/ super(view);
}
}
#Override
public int getItemViewType(int position){...}
#Override
public int getItemCount(){...}
/*Line 165*/ public class RecyclerViewHolder extends RecyclerView.ViewHolder {
TextView title;
RelativeLayout relativeLayout;
RelativeLayout cardDescription;
SimpleDraweeView image;
ImageView favourite_button;
CardSetterGetter cardSetterGetter;
ImageView share;
private RecyclerViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.image_title);
relativeLayout = (RelativeLayout) itemView.findViewById(R.id.activity_dash_board);
cardDescription = (RelativeLayout) itemView.findViewById(R.id.card_details);
image = (SimpleDraweeView) itemView.findViewById(R.id.image);
favourite_button = (ImageView) itemView.findViewById(R.id.favourite_button);
share = (ImageView) itemView.findViewById(R.id.share);
/*Line 186*/ image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Activity activity = (Activity) context;
saveInfo(constants.SERVERIP.concat(cardSetterGetter.getImageurl()), cardSetterGetter.getImageId(), cardSetterGetter.getDescription(), cardSetterGetter.getImagetitle(), cardSetterGetter.getFavourite());
Intent i = new Intent().setClass(context, DetailsImageviewActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
context.startActivity(i);
activity.overridePendingTransition(R.anim.pull_from_right, R.anim.pull_out_to_right);
}
});
}
}
}
I know what a NullPointerException is, I know the solution to those problems, but in this case it's getting hard for me to find the source and the solution of the problem. So if the solution is that simple, instead of marking the question as a duplicate, please consider helping me out with this.
When come to inflate 2 different view type in a recyclerView,we need to create 2 separate ViewHolder class to contain the different element inside of each layout
Try the following:
//make this a separate class,but not inside the onBindViewHolder
private class NativeExpressAdViewHolder extends RecyclerView.ViewHolder{
NativeExpressAdViewHolder(View view){
super(view);
//find the view here
adView = (NativeExpressAdView)view.findViewById(R.id.native_ad);
}
private class RecyclerViewHolder extends RecyclerView.ViewHolder{
//this one as usual..
}
//change your onCreateViewHolder for this as well,
// cause now you have 2 view type,so you just override from universal
//RecyclerView.ViewHolder,not need RecyclerViewAdapter.RecyclerViewHolder
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { }
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
int viewType = getItemViewType(position);
switch (viewType){
case AD_VIEW_TYPE:
final NativeExpressAdViewHolder adHolder (NativeExpressAdViewHolder)holder
//here find your view and load the ad
break;
case MENU_ITEM_VIEW_TYPE:
final RecyclerViewHolder viewHolder = (RecyclerViewHolder)holder
//do your thing here,find view,assign value to the layout
}
And one more thing,please check your XML,your XML should look like this
<com.google.android.gms.ads.NativeExpressAdView
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="#+id/native_ad"
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
ads:adSize="360x132"
ads:adUnitId="#string/your_ads">
</com.google.android.gms.ads.NativeExpressAdView>