Recyclerview setOnClickListener on Textview changes background of another row Textview

只愿长相守 提交于 2019-12-13 08:44:27

问题


My RecyclerView is like this

When I Clicked on F-0 and S-0 for selection and changed background. It is also changed background color F-15 and S-15.

My Code is here.

MyRecyclerViewAdapter.java

public class MyRecyclerViewAdapter extends RecyclerView
    .Adapter<MyRecyclerViewAdapter
    .DataObjectHolder> {
private static String LOG_TAG = "MyRecyclerViewAdapter";
private ArrayList<DataObject> mDataset;
private static MyClickListener myClickListener;


public static class DataObjectHolder extends RecyclerView.ViewHolder
        implements View
        .OnClickListener {
    TextView label;
    TextView dateTime;

    public DataObjectHolder(View itemView) {
        super(itemView);
        label = (TextView) itemView.findViewById(R.id.textView);
        dateTime = (TextView) itemView.findViewById(R.id.textView2);
        Log.i(LOG_TAG, "Adding Listener");
        itemView.setOnClickListener(this);
        label.setOnClickListener(this);
        dateTime.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {

        if(v.getId() == label.getId()){
            label.setBackgroundColor(Color.parseColor("#FFFF00"));

        }else if(v.getId() == dateTime.getId()){
            dateTime.setBackgroundColor(Color.parseColor("#0000FF"));
        }else{
            Toast.makeText(v.getContext(), "ROW PRESSED = " + String.valueOf(getAdapterPosition()), Toast.LENGTH_SHORT).show();

        }
        int position  = getAdapterPosition();
        Log.i(LOG_TAG, String.valueOf(position));
        myClickListener.onItemClick(position, v);
    }
}

public void setOnItemClickListener(MyClickListener myClickListener) {
    this.myClickListener = myClickListener;
}

public MyRecyclerViewAdapter(ArrayList<DataObject> myDataset) {
    mDataset = myDataset;
}

@Override
public DataObjectHolder onCreateViewHolder(ViewGroup parent,
                                           int viewType) {
    View view = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.recyclerview_item, parent, false);

    DataObjectHolder dataObjectHolder = new DataObjectHolder(view);
    return dataObjectHolder;
}

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


    holder.label.setText(mDataset.get(position).getmText1());
    holder.dateTime.setText(mDataset.get(position).getmText2());
}

public void addItem(DataObject dataObj, int index) {
    mDataset.add(dataObj);
    notifyItemInserted(index);
}

public void deleteItem(int index) {
    mDataset.remove(index);
    notifyItemRemoved(index);
}

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

public interface MyClickListener {
    public void onItemClick(int position, View v);
}

}

DataObject.java

public class DataObject {
private String mText1;
private String mText2;

DataObject (String text1, String text2){
    mText1 = text1;
    mText2 = text2;
}

public String getmText1() {
    return mText1;
}

public void setmText1(String mText1) {
    this.mText1 = mText1;
}

public String getmText2() {
    return mText2;
}

public void setmText2(String mText2) {
    this.mText2 = mText2;
}

}

MainActivity.java

public class MainActivity extends AppCompatActivity {

private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private static String LOG_TAG = "RecyclerViewActivity";


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);


    mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
    mRecyclerView.setHasFixedSize(true);
    mLayoutManager = new LinearLayoutManager(this);
    mRecyclerView.setLayoutManager(mLayoutManager);
    mAdapter = new MyRecyclerViewAdapter(getDataSet());
    mRecyclerView.setAdapter(mAdapter);
    RecyclerView.ItemDecoration itemDecoration =
            new DividerItemDecoration(this, LinearLayoutManager.VERTICAL);
    mRecyclerView.addItemDecoration(itemDecoration);
}

@Override
protected void onResume() {
    super.onResume();
    ((MyRecyclerViewAdapter) mAdapter).setOnItemClickListener(new
          MyRecyclerViewAdapter.MyClickListener() {
              @Override
              public void onItemClick(int position, View v) {
                  Log.i(LOG_TAG, " Clicked on Item " + position);
              }
          });
}

private ArrayList<DataObject> getDataSet() {
    ArrayList results = new ArrayList<DataObject>();
    for (int index = 0; index < 20; index++) {
        DataObject obj = new DataObject("F-" + index,
                "S-" + index);
        results.add(index, obj);
    }
    return results;
}

}

So, can you please guide me how to select item for only one row?

Thanks in advance.


回答1:


onBindViewHolder freely recycles Views used by the adapter.

So if you had: DataObjectHolder X set to View A, and DataObjectHolder Y set to View B and you changed the background for Holder X, it actually changed it on View A, the same view can be then used by Holder Y, showing the wrong background.

So what you need to do, is store the state on DataObjectHolder, and in onBindViewHolder check the state and refresh the background color appropriately.

EDIT:

The ViewHolder:

public static class DataObjectHolder extends RecyclerView.ViewHolder
        implements View
        .OnClickListener {
    TextView label;
    TextView dateTime;
    int labelColor = Color.RED;
    int dateColor = Color.RED;

    public DataObjectHolder(View itemView) {
        super(itemView);
        ...
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == label.getId()) {
            labelColor = Color.BLUE;
        } else if(v.getId() == dateTime.getId()) {
            dateColor = Color.BLUE;
        } else {
            ...
        }
        adapter.notifyDataSetChanged(); 
        // or use notifyItemChanged(pos) if you know the position of the view
    }
}

In the Adapter code:

@Override
public void onBindViewHolder(DataObjectHolder holder, int position) {
    holder.label.setText(mDataset.get(position).getmText1());
    holder.dateTime.setText(mDataset.get(position).getmText2());

    // refresh the background color based on the value stored in holder:
    holder.label.setBackgroundColor(holder.labelColor);
    holder.dateTime.setBackgroundColor(holder.dateColor);
}



回答2:


After worked few days on the issue, I have finally solved it before few months. But I was busy with some work. So, I posted it late. Instead of Recyclerview, I have have used Listview. But I think it should also work with Recyclerview. Also, I changed example and put it here. click to view output

Please find code for above example.

MainActivity.Java

package com.example.listviewapplication;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.ListViewCompat;
import android.util.Log;
import android.widget.ListView;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

private ListView listView;
ContentAdapter contentAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    listView = (ListView)findViewById(R.id.listview);
    contentAdapter = new ContentAdapter(getApplicationContext(),R.layout.row_layout);
    listView.setAdapter(contentAdapter);
    for (int index = 0; index < 60; index++) {
        Content content = new Content(index+1,"A-" + index,
                "B-" + index,"C-"+index);
        contentAdapter.add(content);
        contentAdapter.notifyDataSetChanged();
    }
  }
}

ContentAdapter.java

Please make sure that ContactHoder declare as final.

package com.example.listviewapplication;

import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashMap;

public class ContentAdapter extends ArrayAdapter{
    ArrayList list = new ArrayList();
    private HashMap mIdToPosition;

    public ContentAdapter(Context context, int resource) {
        super(context, resource);

        init();

    }
    private void init() {
        mIdToPosition = new HashMap();
    }


    public void add(Content object) {
        super.add(object);
        list.add(object);
    }

    @Override
    public int getCount() {
        //return super.getCount();
        return list.size();
    }

    @Override
    public Object getItem(int position) {
        //return super.getItem(position);
        return list.get(position);
    }


    @Override
    public View getView(final int position, final View convertView, final ViewGroup parent) {

        View row;
        row = convertView;

        final ContactHolder contactHolder;

        if(row == null){
            LayoutInflater layoutInflater = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = layoutInflater.inflate(R.layout.row_layout,parent,false);
            contactHolder = new ContactHolder();
            contactHolder.tx_data1 = (TextView)row.findViewById(R.id.tx_data1);
            contactHolder.tx_data2 = (TextView)row.findViewById(R.id.tx_data2);
            contactHolder.tx_data3 = (TextView)row.findViewById(R.id.tx_data3);

            row.setTag(contactHolder);

        }else{
            contactHolder = (ContactHolder)row.getTag();
        }

        Content content = (Content) this.getItem(position);
        //get DataId as unique value, it is set from MainActivity for loop
        Integer dataId = content.getDataId();
        contactHolder.tx_data1.setText(content.getData1());
        contactHolder.tx_data1.setTag(dataId+"-"+content.getData1()+"-"+position+"-1");
        contactHolder.tx_data2.setText(content.getData2());
        contactHolder.tx_data2.setTag(dataId+"-"+content.getData2()+"-"+position+"-2");
        contactHolder.tx_data3.setText(content.getData3());
        contactHolder.tx_data3.setTag(dataId+"-"+content.getData3()+"-"+position+"-3");


        //check hashmap key (dataId) for already data is in listview or not
        //if textview was selected then check which textview is selected otherwise all textview has default color
        if(mIdToPosition.containsKey(dataId)){
            Log.d("containsKey",mIdToPosition.get(dataId).toString());
            String x = mIdToPosition.get(dataId).toString();
            String[] newarr = x.split("-");
            Integer mid = Integer.parseInt(newarr[0]);
            Integer pos = Integer.parseInt(newarr[3]);
            Integer textid = Integer.parseInt(newarr[4]);
            //Set Default Color for all textviews
//            contactHolder.tx_data1.setBackgroundResource(R.color.colorPrimaryDark);
//            contactHolder.tx_data2.setBackgroundResource(R.color.colorPrimaryDark);
//            contactHolder.tx_data3.setBackgroundResource(R.color.colorPrimaryDark);

            //check textview id and accordingly set color for selected textview
            switch (textid) {
                case 1:
                    contactHolder.tx_data1.setBackgroundResource(R.color.colorAccent);
                    contactHolder.tx_data1.setSelected(true);
                    break;
                case 2:
                    contactHolder.tx_data2.setBackgroundResource(R.color.colorAccent);
                    contactHolder.tx_data2.setSelected(true);
                    break;
                case 3:
                    contactHolder.tx_data3.setBackgroundResource(R.color.colorAccent);
                    contactHolder.tx_data3.setSelected(true);
                    break;
            }

        }
        else{
            contactHolder.tx_data1.setBackgroundResource(R.color.colorPrimaryDark);
            contactHolder.tx_data2.setBackgroundResource(R.color.colorPrimaryDark);
            contactHolder.tx_data3.setBackgroundResource(R.color.colorPrimaryDark);
        }


        //Set OnclickListner for all Textviews
        View.OnClickListener onClickListener = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String s = v.getTag().toString();
                String[] arr = s.split("-");

                //if textview already selected then unselect and set default color of textview.
                if(v.isSelected()){
                    v.setBackgroundResource(R.color.colorPrimaryDark);
                    v.setSelected(false);
                    mIdToPosition.remove(Integer.parseInt(arr[0]));
                }else{
                    switch (v.getId()){
                        case R.id.tx_data1:
                            v.setBackgroundResource(R.color.colorAccent);
                            v.setSelected(true);
                            //Store dataId key in  hashmap (DataId is unique id)
                            mIdToPosition.put(Integer.parseInt(arr[0]),s);
                            contactHolder.tx_data2.setBackgroundResource(R.color.colorPrimaryDark);
                            contactHolder.tx_data3.setBackgroundResource(R.color.colorPrimaryDark);
                            break;

                        case R.id.tx_data2:
                            v.setBackgroundResource(R.color.colorAccent);
                            v.setSelected(true);
                            //Store dataId key in  hashmap (DataId is unique id)
                            mIdToPosition.put(Integer.parseInt(arr[0]),s);
                            contactHolder.tx_data1.setBackgroundResource(R.color.colorPrimaryDark);
                            contactHolder.tx_data3.setBackgroundResource(R.color.colorPrimaryDark);
                            break;

                        case R.id.tx_data3:
                            v.setBackgroundResource(R.color.colorAccent);
                            v.setSelected(true);
                            //Store dataId key in  hashmap (dataId is unique id)
                            mIdToPosition.put(Integer.parseInt(arr[0]),s);
                            contactHolder.tx_data1.setBackgroundResource(R.color.colorPrimaryDark);
                            contactHolder.tx_data2.setBackgroundResource(R.color.colorPrimaryDark);
                            break;
                    }
                }
            }
        };

        contactHolder.tx_data1.setOnClickListener(onClickListener);
        contactHolder.tx_data2.setOnClickListener(onClickListener);
        contactHolder.tx_data3.setOnClickListener(onClickListener);

        return row;
    }

    static class ContactHolder{
        TextView tx_data1, tx_data2, tx_data3;
    }

}

Content.java

package com.example.listviewapplication;


public class Content {

    private String data1,data2,data3;
    private Integer dataId;

    public Content (Integer dataId,String data1,String data2,String data3){
        this.setData1(data1);
        this.setData2(data2);
        this.setData3(data3);
        this.setDataId(dataId);
    }

    public String getData1() {
        return data1;
    }

    public void setData1(String data1) {
        this.data1 = data1;
    }

    public String getData2() {
        return data2;
    }

    public void setData2(String data2) {
        this.data2 = data2;
    }

    public String getData3() {
        return data3;
    }

    public void setData3(String data3) {
        this.data3 = data3;
    }

    public Integer getDataId(){
        return dataId;
    }

    public void setDataId(Integer dataId){
        this.dataId = dataId;
    }

}

Please let me know, if any one required further assistance on it.



来源:https://stackoverflow.com/questions/37463862/recyclerview-setonclicklistener-on-textview-changes-background-of-another-row-te

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!