简体   繁体   中英

Android: Recycler view's UI doesn't change on item click?

I am trying to change the background of recycler view's item when i click on that item . The data actually gets changed but the UI doesn't . I have tried a lot trying different approaches but nothing worked . Though i am calling notifyItemChanged() but it didn't work .

any solution to get this thing working would be very helpful .

**MY CODE: **

@Override
    public void onBindViewHolder(@NonNull final ViewHolder viewHolder, final int i) {


        customNoteView = notesList.get(i);
        notesText = viewHolder.notesWriteArea;
        notesImage = viewHolder.notesImage;
        notesAudio = viewHolder.notesAudio;
        notesAudioPlayButton = viewHolder.notesAudioPlayButton;
        notesAudioSeekBar = viewHolder.notesAudioSeekBar;
        notesAudioDeleteButton = viewHolder.notesAudioDeleteButton;



        if(customNoteView.getNoteText()!=null){
            editTextList.add(notesText);
            notesText.setVisibility(View.VISIBLE);
            notesImage.setVisibility(View.GONE);
            notesAudio.setVisibility(View.GONE);
            notesText.requestFocus();
            focussedEditText = notesText;
            notesText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
                @Override
                public void onFocusChange(View view, boolean b) {
                    if(b){
                        focussedEditText = ((CustomEditText)view);
                        //Toast.makeText(context, ((CustomEditText) view).getText().toString(), Toast.LENGTH_SHORT).show();
                    }
                }
            });
        }
        else if(customNoteView.getImageUri()!=0){
            notesImage.setVisibility(View.VISIBLE);
            notesText.setVisibility(View.GONE);
            notesAudio.setVisibility(View.GONE);
            Glide.with(notesImage.getContext())
                    .load(notesImage.getContext().getDrawable(customNoteView.getImageUri()))
                    .into(notesImage);

            notesImage.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Intent intent = new Intent(context, FullScreen.class);
                    ActivityOptionsCompat options =  ActivityOptionsCompat.makeSceneTransitionAnimation((Activity) context,
                            notesImage,
                            ViewCompat.getTransitionName(notesImage)
                            );

                    context.startActivity(intent, options.toBundle());

                }
            });
        }
        else if(customNoteView.getAudioUri()!=null){
            notesAudio.setVisibility(View.VISIBLE);
            notesImage.setVisibility(View.GONE);
            notesText.setVisibility(View.GONE);
            notesAudioPlayButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    notesAudioPlayButton.setBackground(context.getDrawable(R.drawable.ic_pause));
                    notesAudio.setBackground(context.getDrawable(R.drawable.gray_rectangular_background));
                    notifyItemChanged(viewHolder.getAdapterPosition());

                    Toast.makeText(context, ""+viewHolder.getAdapterPosition(), Toast.LENGTH_SHORT).show();
                }
            });

        }

    }

Finally i managed to find answer to my own question and the root cause for no UI change .

MISTAKE:

i was actually setting on click listeners in onBindViewHolder(...) method .

SOLUTION:

If you want to avoid the notifyItemChanged(position) and other stuff when trying to update recycler view on click events, then you should set the click listeners in viewHolder class and not onBindViewHolder

PS: applying this change worked for me pretty well.@Blind Kai's solution also works but require the view to be refreshed . I am quite sure this one is more easy and efficient.I appreciate his efforts though.

If you want to get that type behavior you could try to add field in your class and check it every time you bind item in your onBindViewHolder method:

if (current.isClicked) {
    viewHolder.itemView.setBackgroundColor(*needed_color*);
} else {
    viewHolder.itemView.setBackgroundColor(*default_color*);
}

viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        current.isClicked = !current.isClicked;
        notifyItemChanged(viewHolder.getAdapterPosition());
    }
});
  • current - the item on i position in your list;

  • itemView - root view of item;

    If you need more details feel free to ask and comment. (Answer was edited and cleaned up few times)

Try the following code:

1) MainActivity.class:

public class MainActivity extends AppCompatActivity {

private final String TAG = MainActivity.class.getSimpleName();
private RecyclerView rv;

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

    rv = (RecyclerView) findViewById(R.id.rv);
    rv.setLayoutManager(new LinearLayoutManager(MainActivity.this));
    List<String> data = new ArrayList<>();
    List<Boolean> selection_states = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        data.add("Item " + (i + 1));
        selection_states.add(false);
    }
    rv.setAdapter(new MyRecyclerViewAdapter(MainActivity.this, data, selection_states));
}

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

    private List<String> mData;
    private List<Boolean> mSelectionStates;
    private LayoutInflater mInflater;

    MyRecyclerViewAdapter(Context context, List<String> data, List<Boolean> selection_states) {
        this.mInflater = LayoutInflater.from(context);
        this.mData = data;
        this.mSelectionStates = selection_states;
    }

    @Override
    @NonNull
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = mInflater.inflate(R.layout.recycler_view_item, parent, false);
        return new ViewHolder(view);
    }

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

        holder.tv.setText(mData.get(position));

        holder.ll.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                int previous_selected = -1;
                for (int i = 0; i < getSelectionStates().size(); i++) {
                    if (getSelectionStates().get(i)) {
                        previous_selected = i;
                        break;
                    }
                }
                if (previous_selected == -1) { // nothing is selected
                    setSelectionState(position, true);
                    notifyItemChanged(position);
                } else if (previous_selected != position) { // selected (other than current selected)
                    setSelectionState(previous_selected, false);
                    setSelectionState(position, true);
                    notifyItemChanged(previous_selected);
                    notifyItemChanged(position);
                }
            }
        });

        if (mSelectionStates.get(position)) {
            //Log.i(TAG, "Select " + position);
            holder.ll.setBackgroundColor(ContextCompat.getColor(MainActivity.this, android.R.color.holo_red_dark));
        } else {
            //Log.i(TAG, "De-Select " + position);
            holder.ll.setBackgroundColor(ContextCompat.getColor(MainActivity.this, android.R.color.white));
        }

    }

    private List<Boolean> getSelectionStates() {
        return mSelectionStates;
    }

    private void setSelectionState(int position, boolean state) {
        mSelectionStates.set(position, state);
    }

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


    private class ViewHolder extends RecyclerView.ViewHolder {
        final LinearLayout ll;
        final TextView tv;

        ViewHolder(View itemView) {
            super(itemView);
            ll = (LinearLayout) itemView.findViewById(R.id.ll);
            tv = (TextView) itemView.findViewById(R.id.tv);
        }

    }

}

}

2) activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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"
tools:context=".MainActivity">

<androidx.recyclerview.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/rv">
</androidx.recyclerview.widget.RecyclerView>

</RelativeLayout>

3) recycler_view_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:padding="20dp"
android:id="@+id/ll"
android:layout_height="wrap_content">

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/tv"
    android:gravity="center"
    android:textSize="20sp"/>

</LinearLayout>

4) Result:

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM