4

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" />

SpaceCore186
  • 586
  • 1
  • 8
  • 22
kai hello
  • 135
  • 1
  • 2
  • 13

4 Answers4

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);
Ralph Bergmann
  • 3,015
  • 4
  • 30
  • 61
  • 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? – kai hello Apr 14 '16 at 16:00
2

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);
        }
    }
}
Ralph Bergmann
  • 3,015
  • 4
  • 30
  • 61
2

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.

Sourabh
  • 8,243
  • 10
  • 52
  • 98
0

You can create a list of ViewHolder then later you will be able to update all text color in each ViewHolder like this:

public class EffectPanelRecyclerViewAdapter extends RecyclerView.Adapter<EffectPanelRecyclerViewAdapter.ViewHolder> {
    private ArrayList<String> mDataset = null;

    private List<ViewHolder> viewHolderList = new ArrayList<>(); // create a list of your ViewHolder class

    private MyItemClickListener mItemClickListener;

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

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

    @Override
    public EffectPanelRecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
        ViewHolder vh = new ViewHolder(v, mItemClickListener);
        viewHolderList.add(vh); // add viewHolder in list
        return vh;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, final int 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) {

                updateColors(); // now call this function to update all ViewHolders at once

            }
        });
    }

    // function to update colors
    public void updateColors() {  
        for (ViewHolder viewHolder : viewHolderList) {
            if (viewHolder != null) {
                viewHolder.mTextView.setTextColor(Color.RED);
            }
        }
    }
}

Make sure you use try catch to catch exceptions while setting colors

Mussa Charles
  • 659
  • 7
  • 10