how to control visibility in android?
if the user does not upload a photo, the ImageView will gone. In contrast, if the user has upload the photo the ImageView will visible.
so how can I do?
this is my xml code.
<LinearLayout
android:id="#+id/infophoto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/post_pic"
android:layout_width="match_parent"
android:layout_height="300dp"
android:scaleType="centerCrop"
android:src="#drawable/expic"
android:transitionName="sharedView"
android:visibility="invisible"
/>
</LinearLayout>
and this is my adapter code.
public void onBindViewHolder(final ViewHolder holder, final int position) {
glide.load(newFeedModels.get(position).getFeedimageURL()).into(holder.uploader_pro_pic);
glide.load(newFeedModels.get(position).getFeedPostImageURL()).into(holder.post_pic);
}
class ViewHolder extends RecyclerView.ViewHolder{
post_pic = (ImageView) itemView.findViewById(R.id.post_pic);
}
this is homefragment code.
String TAG_FeedMediaPhoto_URL = "FeedPostPhoto";
newFeedModel.setFeedimageURL(json.getString(TAG_FeedMediaPhoto_URL));
I need to modify where code?
At the First step is to check whether this particular item having pic or not
public void onBindViewHolder(final ViewHolder holder, final int position) {
if(!TextUtils.isEmpty(newFeedModels.get(position).getFeedPostImageURL())){
holder.post_pic.setVisibility(View.VISIBLE)
glide.load(newFeedModels.get(position).getFeedPostImageURL()).into(holder.post_pic);
}else{
holder.post_pic.setVisibility(View.GONE)
}
}
The android:visibility="invisible" command controls the visibility of the imageview section.
By using:imageview.setVisibility(View.visible); you can change the visibility of the imageview.
Related
I'm trying to set the height of a ViewHolder in onBindViewHolder after changing its content but it only works at the beginning. When it gets recycled, the heights are wrong. I guess it keeps the height of the previous content. Why does it not adjust it again? What am I doing wrong?
My code (simplified):
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mItem = mValues.get(position);
holder.mMyView.setText(holder.mItem.getValue());
holder.mView.measure(
View.MeasureSpec.makeMeasureSpec(Resources.getSystem().getDisplayMetrics().widthPixels, View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
);
int layoutHeight = holder.mView.getMeasuredHeight();
holder.mMyView.getLayoutParams().height = layoutHeight;
//holder.mView.requestLayout();
}
public class ViewHolder extends RecyclerView.ViewHolder {
final View mView;
final TextView mMyView;
ViewHolder(View view) {
super(view);
mView = view;
mMyView= view.findViewById(R.id.myView);
}
}
Edit: My original code is a bit more complicated than this. I need to adjust the size of a view to match the size of another view. The code above is simplified to make it easier to read.
Edit 2: As requested, here is a simplified version of my XML to understand why I want to adjust the height. My goal is to adjust the ImageView height to match the height of the TextViews.
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#id/imageView"
app:layout_constraintStart_toStartOf="parent"
/>
<ImageView
android:id="#+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#imageView" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
Edit 3: I just set the height to a fixed value now. Calculating the height had a big impact on the performance anyway. Ridiculous how difficult it is to make layouts responsive in Android.
Thanks in advance.
Simply set height of the TextView to wrap_content in its XML file. Then change the onBindViewHolder as following:
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mItem = mValues.get(position);
holder.mMyView.setText(holder.mItem.getValue());
}
Height of the TextView will be change accordingly to its content.
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
//this is called when you scroll items
//this will reset to origin xml default items
//here heightChanged is the status , set true if changed
if(heightChanged){
//height according to logic
}else{
//do nothing
}
}
It seems like the height of items are different from each other, try adding status for height that has been changed (write logs to find out the height of each view you will get an idea how to solve this)
you have to set the height of Viewholder dynamically.just use,
public class ViewHolder extends RecyclerView.ViewHolder {
final View mView;
final TextView mMyView;
ViewHolder(View view) {
super(view);
mView = view;
mMyView= view.findViewById(R.id.myView);
view.setMinimumHeight(600); // 600 you can type you height that you want...
}
}
I'm trying to implement a 2 expandable recyclerview with 2 headings.So my view has
1.
2.
3.
4.
Since my recyclerview is expandable, and when I expand the 1st recyclerview , it goes inside my 2nd textview.
ie.there is a separate scroll for my recycler view.
I want the 2nd textview and recyclerview to move down when expanding the 1st recyclerview.
activity.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_marginBottom="10dp"
tools:context=".ListActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="22sp"
android:text="Weightage: 40%"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="#+id/recview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#fafafa" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="22sp"
android:layout_marginBottom="10dp"
android:text="Weightage: 60%"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/recview2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#fafafa" />
</LinearLayout>
</ScrollView>
the same happens with the second recyclerview. On expanding the second recycler view, recyclerview items have a separate scroll and the text above stays at a place.The overall scroll doesn't work.
You can achieve this using only one Recyclerview. Make one model class named "Model" of your data, in which add one variable like "isHeader". When you prepare your data list to show in Recyclerview make 2 model object with
'isHeader = true'
Also, make two (item_layout.xml & header_layout.xml) xml files, one for header & another for your original data item.
And in Recyclerview adapter class you have two separate ViewHolder classes for each of the above layouts. refer this for more details and example
public class MultiViewTypeAdapter extends RecyclerView.Adapter {
public static final int HEADER_VIEW = 0;
public static final int LIST_VIEW = 1;
private Resources resources;
private DownloadListener downloadListener;
public MyToursAdapter(List<Model> objects) {
super(objects);
resources = App.getApp().getResources();
}
#NonNull
#Override
public RecycleView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
if (viewType == HEADER_VIEW) {
return new SectionHeaderItemViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.header_layout, parent, false));
} else
return new ListItemViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false));
}
#Override
public void onBindViewHolder(#NonNull BaseRecycleAdapter.ViewHolder holder, int position) {
if (getItemViewType(position) == HEADER_VIEW)
((HeaderItemViewHolder) holder).bindHeaderViewHolder(objects.get(position));
else
((ListItemViewHolder) holder).bindListViewHolder(objects.get(position));
}
#Override
public int getItemViewType(int position) {
if (objects.get(position).isHeader())
return HEADER_VIEW;
else
return LIST_VIEW;
}
public class ListItemViewHolder extends BaseRecycleAdapter.ViewHolder {
//write code to show data from list object.
}
public class HeaderItemViewHolder extends BaseRecycleAdapter.ViewHolder {
//write code to show data from list object.
}
}
enter code here
I am following the code from Android Developers:RecyclerView
, and I want a more complex layout for a single item in the RecyclerView (I want it to have an image, and 2 text views inside a RelativeLayout, rather than just a single TextView without any Layout parent.
The code works when my my_text_view.xml file contains just a TextView like so:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/my_text_view"
android:layout_width="match_parent"
android:layout_height="28dp"
android:textSize="24sp"
tools:text="Hello John Doe" />
But when I try to change it to a more complex layout, that contains an ImageView and 2 TextViews under a RelativeLayout, like so:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="6dip" >
<ImageView
android:id="#+id/icon"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true"
android:layout_marginRight="6dip"
android:contentDescription="TODO"
android:src="#drawable/ic_launcher" />
<TextView
android:id="#+id/secondLine"
android:layout_width="fill_parent"
android:layout_height="26dip"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_toRightOf="#id/icon"
android:ellipsize="marquee"
android:maxLines="1"
android:text="Description"
android:textSize="12sp" />
<TextView
android:id="#+id/firstLine"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="#id/secondLine"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_alignWithParentIfMissing="true"
android:layout_toRightOf="#id/icon"
android:gravity="center_vertical"
android:text="Example application"
android:textSize="16sp" />
</RelativeLayout>
Then the app will crash.
I really don't know where I should apply more changes, I am quite lost in their explanation on holders, and adapters, and layout managers. What exactly in their code should be changed? I basically copied their code if you need reference (And it worked, that's why I didn't copy their code here)
Edit: I believe the changes should be somewhere in this code, but I don't know where and how exactly
package com.example.lastlocation.recyclerviewer;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private String[] mDataset;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class MyViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView mTextView;
public MyViewHolder(TextView v) {
super(v);
mTextView = v;
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(String[] myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
TextView v = (TextView) LayoutInflater.from(parent.getContext())
.inflate(R.layout.my_text_view, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.mTextView.setText(mDataset[position]);
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataset.length;
}
}
If you modify the contents of the item view XML file, you will also have to modify your ViewHolder class and your Adapter's onCreateViewHolder() and onBindViewHolder() methods.
In your new version, you have a RelativeLayout, an ImageView, and two TextViews. You probably don't need to do anything to the RelativeLayout, so your ViewHolder will only have references to the ImageView and TextViews:
public static class MyViewHolder extends RecyclerView.ViewHolder {
public final ImageView icon;
public final TextView firstLine;
public final TextView secondLine;
public MyViewHolder(View itemView) {
super(itemView);
icon = itemView.findViewById(R.id.icon);
firstLine = itemView.findViewById(R.id.firstLine);
secondLine = itemView.findViewById(R.id.secondLine);
}
}
Your onCreateViewHolder() method doesn't need to change much. Mostly you just need to remove the cast, since now you're no longer inflating a TextView object:
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.my_text_view, parent, false);
return new MyViewHolder(itemView);
}
Your onBindViewHolder() method needs to change to use the new views you've specified:
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.icon.setImageResource(R.drawable.whatever);
holder.firstLine.setText("Hello");
holder.secondLine.setText("World");
}
I am using a recyclerview for displaying and broadcasting videos of users. However, when I scroll through the recycler view, I see my first view, which has my video gets recycled hence why it's not visible to other users. Is there a way I can make sure that the first view is not recycled so I dont have to worry about my video view getting resetrecycled every single time I scroll through my list?
Here's my code :
In my fragment...
...
<android.support.v7.widget.RecyclerView
android:id="#+id/videoList"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="invisible"
app:layout_constraintBottom_toTopOf="#+id/myButtonContainer"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/myoldContainer">
...
and the corresponding adapter...
public class GroupAdapter extends RecyclerView.Adapter<GroupAdapter.myViewHolder> {
private CopyOnWriteArrayList<Person> persons;
private Context mContext;
public GroupAdapter(#NonNull final CopyOnWriteArrayList<Person> persons , Context context) {
this.persons = persons;
this.mContext= context;
for (Person person : this.persons) {
//get names
}
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final View layout = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_person, parent, false);
final MyViewHolder viewHolder = new MyViewHolder(layout);
return viewHolder;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
final Person person = person.get(position);
final Participant participant = person.getParticipant();
if (person.getName() != null) {
holder.personName.setText(person.getName());
}
if (person.getImage() != null) {
holder.personImage.setImageBitmap(person.getImage());
} else {
holder.personImage.setImageResource(R.drawable.default_profile);
}
holder.personImage.setVisibility(View.INVISIBLE);
holder.personImage.setVisibility(View.VISIBLE);
final VideoView videoView;
if (participant.isMe) {
videoView = participant.videoStreamer.videoView;
} else {
videoView = participant.videoPlayer.videoView;
}
if (holder.personVideo.getChildCount() != 0) {
holder.personVideo.removeAllViews();
}
if (videoView.getParent() != null) {
ViewGroup parent = (ViewGroup) videoView.getParent();
parent.removeView(videoView);
}
holder.personVideo.addView(videoView, myViewHolder.videoLayoutParams);
if (person.isVideoPaused()) {
holder.personVideo.setVisibility(View.INVISIBLE);
holder.personImage.setVisibility(View.VISIBLE);
} else {
holder.personVideo.setVisibility(View.VISIBLE);
holder.personImage.setVisibility(View.INVISIBLE);
}
}
#Override
public int getItemCount() {
return persons.size();
}
public static final class MyViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.personVideo)
public ViewGroup personVideo;
#BindView(R.id.personImage)
public ImageView personImage;
#BindView(R.id.personName)
public TextView personName;
protected static FrameLayout.LayoutParams videoLayoutParams = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
);
public MyViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}
Here's how I am setting it in my fragment:
LinearLayoutManager manager = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);
videoAdapter = new VideoAdapter(myHelper.getPeople(), getContext());
videoList.setLayoutManager(manager);
videoList.setAdapter(videoAdapter);
item_person:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginTop="0dp"
android:background="#drawable/person_border"
xmlns:app="http://schemas.android.com/apk/res-auto">
<RelativeLayout
android:id="#+id/personContainer"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent">
<FrameLayout
android:id="#+id/personVideo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/black" />
<ImageView
android:id="#+id/personImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/black"
android:src="#drawable/default_profile" />
<TextView
android:id="#+id/personName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#AA555555"
android:gravity="center_horizontal|bottom"
android:textColor="#color/green"
android:textSize="12sp"
android:lines="1"
android:ellipsize="end"
tools:text="androiduser#gmail.com"
android:layout_alignParentBottom="true" />
</RelativeLayout>
</android.support.constraint.ConstraintLayout>
fragment with recycle view: xml
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<RelativeLayout>
....
</RelativeLayout>
<include containers>...</include>
...
<android.support.v7.widget.RecyclerView
android:id="#+id/personList"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="invisible"
>
</android.support.v7.widget.RecyclerView>
</android.support.constraint.ConstraintLayout>
I don't think that "not recycling" the video view will actually stop it from being destroyed when you scroll. It's not the recycling is the problem but the view unbinding.
I think such complex component such as VideoView should not be inside the RecyclerView at all.. You can try adding it as a static content on top, which most likely will solve the issue. You can use a NestedScrollView for that. Take a look here: Recyclerview inside scrollview- How to scroll whole content?
If you still think you want to keep it in the RecyclerView and disable the recycling, do the following.
Create a separate view type for your video view items. Here is an example:
https://stackoverflow.com/a/26573338/3086818. Treat your video view item as a header view from the example.
Once you do this, there is a RecycledViewPool class which manages the recycling of items inside a RecyclerView. You can tell it which views to recycle and which not. By default it recycles all views. To disable recycling for your video view items use your new view type like this:
recyclerView.getRecycledViewPool().setMaxRecycledViews(TYPE_VIDEO_VIEW, 0);
where TYPE_VIDEO_VIEW is the new type that you created using the previous example. The number 0 tells the RecyclerView how many items to recycle - in this case it's 0, meaning "do not recycle". More info about this here: https://stackoverflow.com/a/36313437/3086818.
I hope this helps.. Good luck!
The answer is yes, you can actually do that.
Since you said "The first item" so you simply add a check.
if(position == 0)
{
holder.setIsRecyclable(false); //This line prevents the row from recycling
}
New items are added to RecyclerView each time when Adapter have created.
In photo I showed a process where darken dish images appear, though I managed image darking with a condition if(holder.mDish.getPicurl()!=null), but it doest work.
If I go into darken dish image details and go back to list, there will by three darken images. Is it problem with RecyclerView or it is my fault?
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.mDish = DISHES.get(position);
final int id = holder.mDish.getId();
if(holder.mDish.getPicurl()!=null) {
Picasso.with(mContext)
.load(holder.mDish.getPicurl())
.fit()
.transform(new RoundedTransformation(20, 0))
.into(holder.mIvBackground);
holder.mIvBackground.setColorFilter(Color.parseColor("#aaaaaa"), PorterDuff.Mode.MULTIPLY);
} else {
holder.mIvBackground.setImageResource(R.drawable.vector_drawable_dish);
}
holder.mTvName.setText(holder.mDish.getName());
//holder.mTvDescription.setText(holder.mDish.getDescription());
holder.mTvPrice.setText("T " + String.valueOf(holder.mDish.getPrice()));
holder.mBtnAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(mListener!=null){
mListener.onAddToBasketInteraction(id);
}
}
});
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mListener.onStartDetailActivity(id);
}
});
}
public void addDishes(List<Dish> dishes){
DISHES.clear();
DISHES.addAll(dishes);
notifyDataSetChanged();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public Dish mDish;
public final View mView;
public final ImageView mIvBackground;
public final TextView mTvName;
//public final TextView mTvDescription;
public final TextView mTvPrice;
public final ImageButton mBtnAdd;
public ViewHolder(View itemView) {
super(itemView);
mView = itemView;
mIvBackground = (ImageView) itemView.findViewById(R.id.dishBackground);
mTvName = (TextView) itemView.findViewById(R.id.name);
//mTvDescription = (TextView) itemView.findViewById(R.id.description);
mTvPrice = (TextView) itemView.findViewById(R.id.price);
mBtnAdd = (ImageButton) itemView.findViewById(R.id.btnAdd);
}
}
xml of item:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="90dp"
android:orientation="horizontal"
android:padding="2dp">
<ImageView
android:id="#+id/dishBackground"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Плов узбекский"
android:textColor="#color/colorAccent2"
android:layout_marginLeft="5dp"
android:layout_marginBottom="5dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:textSize="14sp" />
<TextView
android:id="#+id/price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:layout_marginTop="5dp"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="T 3000"
android:textColor="#android:color/holo_orange_light" />
<ImageButton
android:id="#+id/btnAdd"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:background="#drawable/ic_add_shopping_cart_black_24dp" />
</RelativeLayout>
You don't undo view changes in conditional statement
The culprit is this piece of code:
if(holder.mDish.getPicurl()!=null) {
Picasso.with(mContext)
.load(holder.mDish.getPicurl())
.fit()
.transform(new RoundedTransformation(20, 0))
.into(holder.mIvBackground);
holder.mIvBackground.setColorFilter(Color.parseColor("#aaaaaa"), PorterDuff.Mode.MULTIPLY);
} else {
holder.mIvBackground.setImageResource(R.drawable.vector_drawable_dish);
}
The way RecyclerView works is it reuses the same views with a different data (hence recycler), so the onBindViewHolder method may be called multiple times for each position, but the ViewHolder might have been already created and previously bound to a different piece of data. That way some changes applied to the view inside the onBindViewHolder method might persist through bind calls to different pieces of data.
In your case, the following call:
holder.mIvBackground.setColorFilter(Color.parseColor("#aaaaaa"), PorterDuff.Mode.MULTIPLY);
alters the view with the color filter within one call to onBindViewHolder. Then, when another piece of data is bound to the same ViewHolder, the condition holder.mDish.getPicurl()!=null might be false, but the effect still persists, because there is no removal of this color filter in the else branch of your statement.
Fix
You need to explicitly set and unset any changes to a single view in your RecyclerView for every separate condition you wish to implement:
if(holder.mDish.getPicurl()!=null) {
holder.mIvBackground.setColorFilter(Color.parseColor("#aaaaaa"), PorterDuff.Mode.MULTIPLY);
} else {
holder.mIvBackground.setColorFilter(null); // removes color filter
}
You don't see any problems with your mIvBackground because you set a different one in each branch of your if-else statement, so no unwanted state persists.