【问题标题】:Background Selector in RecyclerView ItemRecyclerView 项中的背景选择器
【发布时间】:2014-10-13 02:28:10
【问题描述】:

我正在使用RecyclerView,如下所示:

<android.support.v7.widget.RecyclerView
    android:id="@+id/list"
    android:layout_width="320dp"
    android:layout_height="match_parent"/>

还有我的列表项:

<LinearLayout  android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/selector_medium_high">
    <com.basf.suvinil.crie.ui.common.widget.CircleView
        android:id="@+id/circle"
        android:layout_width="22dp"
        android:layout_height="22dp"/>
    <TextView
        android:id="@+id/label"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="57.5dp"/>
</LinearLayout>

详细看这部分android:background="@drawable/selector_medium_high"这是一个普通的选择器:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/background_high" android:state_activated="true"/>
    <item android:drawable="@color/background_high" android:state_pressed="true"/>
    <item android:drawable="@color/background_high" android:state_checked="true"/>
    <item android:drawable="@color/background_high" android:state_focused="true"/>
    <item android:drawable="@color/background_medium"/>
</selector>

但是当我运行这段代码时,当我触摸行时,背景颜色没有变化......

【问题讨论】:

  • 不幸的是,使用可聚焦视图不是跟踪选择的好方法。检查我的答案以获得完整的解决方案。

标签: android selector android-recyclerview


【解决方案1】:

RecyclerView“列表”的所有元素中将clickablefocusablefocusableInTouchMode设置为true

【讨论】:

  • 今天,RecyclerView 没有onItemClick。但是在可点击、可聚焦和可聚焦的InTouchMode中设置为true已经解决了这个问题:)
  • 我不知道如何看到这种答案,但你帮我,我认为如果你只是删除第 2 步并在第 1 步中设置 true 而不是 false 就没有问题,它会没关系,答案是对的
  • “my_list_view”在哪里?在此示例中,我没有看到任何名为“my_list_view”的内容?令人困惑
  • 他的意思是“列表”而不是“my_list_view”
  • 为什么不使用 - android:background="?android:attr/selectableItemBackground" ?
【解决方案2】:

添加:

android:background="?android:attr/selectableItemBackground"

item.xml

【讨论】:

  • 但这会产生连锁反应。
【解决方案3】:

如果这些都不适合你,就像它不适合我一样,请使用以下代码:

android:foreground="?android:attr/selectableItemBackground"

诀窍在于android:foreground 属性...

【讨论】:

【解决方案4】:

android:background="?android:attr/selectableItemBackground" 添加到my_list_item.xml根布局 似乎对我有用(假设您想要默认选择颜色)。

还要确保根布局的android:layout_widthmatch_parent 而不是wrap_content,以确保整行都是可选的。

【讨论】:

  • 使用android:background="?android:attr/selectableItemBackground"时如何更改默认选择颜色?
【解决方案5】:

很遗憾,使用可聚焦视图来模拟项目选择不是一个好的解决方案,因为:

  • 调用notifyDataSetChanged 时失去焦点
  • 当子视图可聚焦时,焦点会出现问题

我编写了一个基础适配器类来使用 RecyclerView 自动处理项目选择。只需从中派生适配器并使用带有 state_selected 的可绘制状态列表,就像使用列表视图一样。

我有一个关于它的Blog Post Here,但这里是代码:

public abstract class TrackSelectionAdapter<VH extends TrackSelectionAdapter.ViewHolder> extends RecyclerView.Adapter<VH> {
    // Start with first item selected
    private int focusedItem = 0;

    @Override
    public void onAttachedToRecyclerView(final RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);

        // Handle key up and key down and attempt to move selection
        recyclerView.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                RecyclerView.LayoutManager lm = recyclerView.getLayoutManager();

                // Return false if scrolled to the bounds and allow focus to move off the list
                if (event.getAction() == KeyEvent.ACTION_DOWN) {
                    if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
                        return tryMoveSelection(lm, 1);
                    } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
                        return tryMoveSelection(lm, -1);
                    }
                }

                return false;
            }
        });
    }

    private boolean tryMoveSelection(RecyclerView.LayoutManager lm, int direction) {
        int tryFocusItem = focusedItem + direction;

        // If still within valid bounds, move the selection, notify to redraw, and scroll
        if (tryFocusItem >= 0 && tryFocusItem < getItemCount()) {
            notifyItemChanged(focusedItem);
            focusedItem = tryFocusItem;
            notifyItemChanged(focusedItem);
            lm.scrollToPosition(focusedItem);
            return true;
        }

        return false;
    }

    @Override
    public void onBindViewHolder(VH viewHolder, int i) {
        // Set selected state; use a state list drawable to style the view
        viewHolder.itemView.setSelected(focusedItem == i);
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        public ViewHolder(View itemView) {
            super(itemView);

            // Handle item click and set the selection
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // Redraw the old selection and the new
                    notifyItemChanged(focusedItem);
                    focusedItem = mRecyclerView.getChildPosition(v);
                    notifyItemChanged(focusedItem);
                }
            });
        }
    }
} 

【讨论】:

  • 谁是mRecyclerView?
【解决方案6】:
    viewHolder.mRlPrince.setOnTouchListener(new View.OnTouchListener() {
        @Override public boolean onTouch(View v, MotionEvent event) {

            if (event.getAction()==MotionEvent.ACTION_DOWN){
                viewHolder.mRlPrince.setBackgroundColor(Color.parseColor("#f8f8f8"));
            }if (event.getAction()==MotionEvent.ACTION_UP){
                viewHolder.mRlPrince.setBackgroundColor(Color.WHITE);
            }

            return false;
        }
    });

【讨论】:

  • 但 Material Design 的答案很糟糕,因为这会破坏涟漪效应。
【解决方案7】:

在您的项目“my_list_item.xml”中添加以下属性
android:descendantFocusability="blocksDescendants" 这对我有用!

【讨论】:

    【解决方案8】:

    你需要在元素xml中设置android:clickable="true",如果你的视图里面的某个视图有更多的选择器,你需要设置android:duplicateParentState="true" 也有。 这适用于预蜂窝 API。

    【讨论】:

      【解决方案9】:

      正如许多其他人回答的那样,唯一的方法是结合选择器和新类来跟踪选择,但最好将此计算委托给适配器。 FlexibleAdapter 库为您跟踪选择,配置更改也兼容。

      现在可以在没有 XML 部分的情况下使用带有波纹的背景颜色,而是在代码中管理动态数据。

      最后,您可以在同一个库中使用许多功能,选择是您可以拥有的一个微小的基本功能。

      请查看描述、Wiki 页面和完整的工作示例:https://github.com/davideas/FlexibleAdapter

      【讨论】:

        【解决方案10】:

        在您的设计或 xml 文件中只需放置以下行。

        android:clickable="true"
        android:focusable="true"
        android:background="?android:attr/activatedBackgroundIndicator"
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-28
          • 1970-01-01
          相关资源
          最近更新 更多