How to get all RecyclerView ViewHolder?

21,494

Solution 1

it is not tested!!!

public class EffectPanelRecyclerViewAdapter extends
    RecyclerView.Adapter<EffectPanelRecyclerViewAdapter.ViewHolder> {

    private ArrayList<DataClass> mDataset = null;

    public EffectPanelRecyclerViewAdapter(ArrayList<DataClass> datats) {
        mDataset = datats;
    }

    /**
     * ViewHolder
     */
    @Override
    public EffectPanelRecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                                        int viewType) {
        // create a new view
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
        // set the view's size, margins, paddings and layout parameters
        ViewHolder vh = new ViewHolder(v);
        Log.d("hello", "onCreateViewHolder");
        return vh;
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, final int position) {

        Log.d("hello", "onBindViewHolder,position=" + position);
        holder.mTextView.setText(mDataset.get(position).text);
        holder.mTextView.setTextColor(mDataset.get(position).clicked ? Color.RED : Color.BLUE);
        holder.mTextView.setTag(position);
        holder.mTextView.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                mDataset.get(position).clicked = true;
                notifyItemChanged(position);
            }
        });
    }

    @Override
    public int getItemCount() {
        return mDataset.size();
    }


    private static class DataClass {

        public String  text;
        public boolean clicked;
    }


    private static class ViewHolder extends RecyclerView.ViewHolder {

        public TextView mTextView;

        public ViewHolder(View v) {
            super(v);
            mTextView = (TextView) v.findViewById(R.id.tv);
        }
    }
}

Solution 2

Store a flag in your adapter class like this private boolean clicked = false;. In the onclicklistener set it to true and call notifiyDatasetChanged()

In the onBindViewHolder method add a if like this

if (clicked)
   viewHolder.mTextView.setTextColor(Color.RED); 
else
   viewHolder.mTextView.setTextColor(Color.BLUE);

Solution 3

notifyDatasetChanged() and its sibling methods doesn't work if you want to animate all visible views. To animate, you can update the data source but not call notifyDatasetChanged(), instead you get all ViewHolders and animate them yourself. On scroll, any items re-binded will have correct state, which you can do by writing code similar to what Ralph Bergmann posted.

AnimatorSet set = new AnimatorSet();
ArrayList<Animator> animators = new ArrayList<>(mRecyclerView.getChildCount());
for (int i = 0, size = mRecyclerView.getChildCount(); i < size; i++) {
    RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(mRecyclerView.getChildAt(i));
    if (holder != null) {
        // do stuff like this
        ObjectAnimator animator = ObjectAnimator.ofFloat(holder.itemView, "alpha", 0F);
        animators.add(animator);
    }
}
set.playTogether(animators);
set.setDuration(200);
set.start();

PS: Untested code, but it should work.

Share:
21,494
kai hello
Author by

kai hello

Updated on July 25, 2022

Comments

  • kai hello
    kai hello almost 2 years

    I want to change all items' text color when I click on one of them. My problem is that the color is changing only on visible items. The color of invisible items does not change at all.

    New: Also I would like to know how to change the color of the clicked item only.

    EffectPanelRecyclerViewAdapter.java:

    public class EffectPanelRecyclerViewAdapter extends RecyclerView.Adapter<EffectPanelRecyclerViewAdapter.ViewHolder> {
    private ArrayList<String> mDataset = null;
    private MyItemClickListener mItemClickListener;
    
    public EffectPanelRecyclerViewAdapter(ArrayList<String> datats) {
        mDataset = datats;
    }
    
    
    public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        public TextView mTextView;
        private MyItemClickListener mListener;
    
        public ViewHolder(View v, MyItemClickListener listener) {
            super(v);
            mListener = listener;
            mTextView = (TextView) v.findViewById(R.id.tv);
            v.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
            if (mListener != null) {
                Log.d("hello", "getAdapterPosition=" + getAdapterPosition());
                mListener.onItemClick(v, getAdapterPosition());
            }
        }
    
    }
    
    @Override
    public int getItemCount() {
        return mDataset.size();
    }
    
    public interface MyItemClickListener {
        public void onItemClick(View view, int postion);
    }
    
    /**
     * ViewHolder
     */
    @Override
    public EffectPanelRecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // create a new view
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
        // set the view's size, margins, paddings and layout parameters
        ViewHolder vh = new ViewHolder(v, mItemClickListener);
        Log.d("hello", "onCreateViewHolder");
        return vh;
    }
    
    @Override
    public void onBindViewHolder(ViewHolder holder, final int position) {
        Log.d("hello", "onBindViewHolder,position=" + position);
        ViewHolder mHolder = (ViewHolder) holder;
        mHolder.mTextView.setText(mDataset.get(position));
        mHolder.mTextView.setTag(position);
        mHolder.mTextView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mItemClickListener.onItemClick(v, position);
            }
        });
    }
    
    public void setOnItemClickListener(MyItemClickListener listener) {
        this.mItemClickListener = listener;
    }
    

    }

    MainActivity.java:

    public class MainActivity extends AppCompatActivity {
    
    private ArrayList<String> mDatas;
    private RecyclerView mRecyclerView;
    private EffectPanelRecyclerViewAdapter mAdapter;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initDatas();
        mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview_horizontal);
        final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        mRecyclerView.setLayoutManager(linearLayoutManager);
        mAdapter = new EffectPanelRecyclerViewAdapter(mDatas);
        mRecyclerView.setAdapter(mAdapter);
        mAdapter.setOnItemClickListener(new EffectPanelRecyclerViewAdapter.MyItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                Toast.makeText(MainActivity.this, "position=" + position, Toast.LENGTH_SHORT).show();
                //I want to change all item text color.How to do it ?
                for (int i = 0; i < mAdapter.getItemCount(); i++) {
                    EffectPanelRecyclerViewAdapter.ViewHolder viewHolder = (EffectPanelRecyclerViewAdapter.ViewHolder) mRecyclerView.findViewHolderForAdapterPosition(i);
                    if (viewHolder != null) {
                        viewHolder.mTextView.setTextColor(Color.RED);
                        Log.d("hellotom", "if i=" + i);
                    } else {
                        Log.d("hellotom", "else i=" + i);
                    }
                }
            }
        });
    }
    
    private void initDatas() {
        mDatas = new ArrayList();
        for (int i = 0; i < 10; i++) {
            mDatas.add(i, "i=" + i);
        }
    }
    

    }

    activity_main.xml:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <android.support.v7.widget.RecyclerView
        android:id="@+id/id_recyclerview_horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerVertical="true"
        android:paddingBottom="18dp"
        android:paddingTop="15dp"
        android:scrollbars="none" />
    

    item.xml:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    
    <TextView
        android:id="@+id/tv"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:drawableTop="@drawable/ic_launcher_select"
        android:textColor="@color/select_color"
        android:gravity="center"
        android:text="@string/app_name" />
    

  • kai hello
    kai hello about 8 years
    Thanks,it is work. I have a new idea, I want to click current item,only current text color will be change.Ohters don't change. How to change code?