如何通过onClick事件更改RecyclerView中的所有元素?

时间:2018-12-03 17:46:21

标签: java android

我有一个RecyclerView,其中每个元素都有一个onClickEventListener()来改变外观。它可以正常工作,但是我实际上需要更改所有其他元素的外观。具体来说,我需要在clicked元素中填充颜色,而其他元素只能带有笔触。我认为,比遍历RecyclerView的所有元素的数组,还有一种更为优雅的方法。
我当前的代码如下:

vh.mImageView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            GradientDrawable typeShape = (GradientDrawable) vh.mImageView.getDrawable();
            if (vh.clicked) {
                typeShape.setColor(Color.parseColor("#00ff5800"));
            } else {
                typeShape.setColor(Color.parseColor("#ff5800"));
            }
            vh.clicked = !vh.clicked;
        }
    });

2 个答案:

答案 0 :(得分:1)

我认为,“最佳”方法是使用大多数人不熟悉的RecyclerView API的一部分: notifyItemRangeChanged()接受有效载荷对象。

https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter#notifyitemrangechanged

传递有效负载对象时,将调用onBindViewHolder()的特殊版本,并将该有效负载传递给此方法。

https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#onbindviewholder_5

这一切使您可以高效地重新绑定任何显示的ViewHolder对象,并且仅更新您知道已更改的视图部分。

在您的特定示例中,您可以让适配器跟踪selectedPosition,并让onBindViewHolder()方法根据项目的位置是否等于当前所选位置来设置项目的背景:

private void updateBackground(ViewHolder holder, int position) {
    holder.itemView.setBackgroundResource(
        (position == selectedPosition) ? R.drawable.highlight : R.drawable.stroke);
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    updateBackground(holder, position);
    // other view binding stuff
}

然后,您可以具有特殊的onBindViewHolder()调用的实现,以进行部分更新:

@Override
public void onBindViewHolder(ViewHolder holder, int position, List<Object> payloads) {
    if (payloads != null && payloads.contains("BACKGROUND")) {
        updateBackground(holder, position);
    }
}

同时设置了这两种设置后,只要更改所选位置,就可以致电:

adapter.selectedPosition = 23; // or whatever else
adapter.notifyItemRangeChanged(0, adapter.getItemCount(), "BACKGROUND");

调用此特殊版本的notifyItemRangeChanged()时,系统将调用特殊的onBindViewHolder(),您将有机会重新绘制所有当前可见视图的背景。但是,您不会浪费时间来更新任何当前不可见的视图,也不会浪费时间来绑定完全没有改变的数据(规范onBindViewHolder()实现中的所有“其他视图绑定内容”)

答案 1 :(得分:1)

创建一个变量以保存选择:

add_filter( 'pre_get_document_title', function( $title ) {
    global $post;
    if ( ! $post || ! $post->post_content ) {
        return $title;
    }
    if ( preg_match( '#\[mc_set_title.*\]#', $post->post_content, $matches ) !== 1 ) {
        return '';
    }
    return do_shortcode( $matches[0] );
} );

add_shortcode( 'mc_set_title', function( $atts ) {
    if ( ! doing_filter( 'pre_get_document_title' ) ) {
        # just remove the shortcode from post content in normal shortcode processing
        return '';
    }
    # in filter 'pre_get_document_title' - you can use $atts and global $post to compute the title
    return 'MC TITLE';
} );

在您的onClickListener内部:

int selectedItem = -1;// -1 means no selected item by default.

最后,无论是在ViewHolder还是onBindViewHolder中:

int position = getAdapterPosition();
// Make sure your position is available on your list.
if (position != RecyclerView.NO_POSITION) {
    if (position == selectedItem) {
        return;// Here, I don't want to generate a click event on an already selected item.
    }

    int currentSelected = selectedItem;// Create a temp var to deselect an existing one, if any.
    selectedItem = position;// Check item.

    if (currentSelected != -1) {
        notifiyItemChanged(currentSelected);// Deselected the previous item.
    }

    notifyItemChanged(selectedItem);// Select the current item.
}