简体   繁体   English

Android:Recycler 视图的 UI 在项目点击时不会改变?

[英]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 .数据实际上已更改,但 UI 没有更改。 I have tried a lot trying different approaches but nothing worked .我尝试了很多尝试不同的方法,但没有任何效果。 Though i am calling notifyItemChanged() but it didn't work .虽然我正在调用 notifyItemChanged() 但它没有用。

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 .最后,我设法找到了我自己问题的答案以及没有 UI 更改的根本原因。

MISTAKE:错误:

i was actually setting on click listeners in onBindViewHolder(...) method .我实际上是在onBindViewHolder(...)方法中设置点击侦听器。

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如果您想在尝试更新点击事件上的回收器视图时避免notifyItemChanged(position)和其他东西,那么您应该在 viewHolder 类而不是onBindViewHolder设置点击侦听onBindViewHolder

PS: applying this change worked for me pretty well.@Blind Kai's solution also works but require the view to be refreshed . PS:应用此更改对我来说效果很好。@Blind Kai 的解决方案也有效,但需要刷新视图。 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:如果你想获得这种类型的行为,你可以尝试在你的类中添加字段,并在你每次在onBindViewHolder方法中绑定项目时检查它:

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; current - 在列表中i位置的项目;

  • itemView - root view of item; itemView - 项目的根视图;

    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: 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: 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: 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: 4) 结果:

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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