【问题标题】:What is the difference between the states selected, checked and activated in Android?Android中选择、检查和激活的状态有什么区别?
【发布时间】:2012-07-15 07:59:54
【问题描述】:

我想知道这些州有什么不同。我没有找到任何网页来说明这一点。

【问题讨论】:

标签: android android-view selected checked


【解决方案1】:

Checked 和 Activated 的区别其实很有趣。甚至谷歌文档也很抱歉(在下面添加了重点):

...例如,在具有单选或多选的列表视图中 启用,当前选择集中的视图被激活。 (嗯, 是的,我们对这里的术语深表歉意。) 状态会向下传播到它所设置的视图的子视图。

所以这里有区别:

  1. 在 Honeycomb 中引入了Activated,因此在此之前您无法使用它
  2. Activated 现在是每个视图的属性。它有方法 setActivated() 和 isActivated()
  3. Activated 传播到设置它的 View 的子级
  4. Checked 围绕实现 Checkable 接口的视图展开。方法 setChecked()、isChecked()、toggle()
  5. ListView(在 Honeycomb 之后)调用 setChecked() 或 setActivated() 取决于 Android 版本如下(取自 Android 源代码):

    if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null) {
        if (child instanceof Checkable) {
            ((Checkable) child).setChecked(mCheckStates.get(position));
        } else if (getContext().getApplicationInfo().targetSdkVersion
                >= android.os.Build.VERSION_CODES.HONEYCOMB) {
            child.setActivated(mCheckStates.get(position));
        }
    }
    

    注意 mCheckStates 变量。它会跟踪您列表中的哪些位置被选中/激活。这些可以通过例如 getCheckedItemPositions() 访问。另请注意,对 ListView.setItemChecked() 的调用会调用上述内容。换句话说,它同样可以被称为 setItemActivated()。

  6. 在 Honeycomb 之前,我们必须实施变通办法以在列表项中反映 state_checked。这是因为 ListView 仅在布局中最顶层的视图上调用 setChecked() (并且布局不实现可检查)......并且它不会在没有帮助的情况下传播。这些变通方法具有以下形式: 扩展根布局以实现 Checkable。在其构造函数中,递归查找所有实现 Checkable 的子代。当 setChecked() 等被调用时,将调用传递给这些视图。如果这些视图使用不同的可绘制 state_checked 实现状态列表可绘制对象(例如 CheckBox),则选中状态会反映在 UI 中。

  7. 要在 Honeycomb 之后为列表项做一个漂亮的背景,你需要做的就是有一个可绘制的状态列表,其中 state_activated 的可绘制状态如下所示(当然还要使用 setItemChecked()):

    <item android:state_pressed="true"
        android:drawable="@drawable/list_item_bg_pressed"/>
    <item android:state_activated="true"
        android:drawable="@drawable/list_item_bg_activated"/>
    <item android:drawable="@drawable/list_item_bg_normal"/>
    

  8. 要在 HoneyComb 之前为列表项做一个漂亮的背景,您可以为 state_checked 执行上述操作,并且您还需要扩展最顶层视图以实现 Checkable 接口。然后,您需要通过实现 onCreateDrawableState() 并在状态更改时调用 refreshDrawableState() 来告诉 Android 您正在实现的状态是真还是假。

    <item android:state_pressed="true"
        android:drawable="@drawable/list_item_bg_pressed"/>
    <item android:state_checked="true"
        android:drawable="@drawable/list_item_bg_checked"/>
    <item android:drawable="@drawable/list_item_bg_normal"/>
    

...在RelativeLayout中结合state_checked实现Checkable的代码可能是:

public class RelativeLayoutCheckable extends RelativeLayout implements Checkable {

    public RelativeLayoutCheckable(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public RelativeLayoutCheckable(Context context) {
        super(context);
    }

    private boolean mChecked = false;

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
    }
    @Override
    public boolean isChecked() {
        return mChecked;
    }

    @Override
    public void setChecked(boolean checked) {
        mChecked = checked;
        refreshDrawableState();
    }

    private static final int[] mCheckedStateSet = {
        android.R.attr.state_checked,
    };

    @Override
    protected int[] onCreateDrawableState(int extraSpace) {
        final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
        if (isChecked()) {
            mergeDrawableStates(drawableState, mCheckedStateSet);
        }
        return drawableState;
    }    

    @Override
    public void toggle() {
        setChecked(!mChecked);
    }
}

感谢以下人员:

http://sriramramani.wordpress.com/2012/11/17/custom-states/

堆栈溢出:How to add a custom button state

堆栈溢出:Custom Checkable View which responds to Selector

http://www.charlesharley.com/2012/programming/custom-drawable-states-in-android/

http://developer.android.com/guide/topics/resources/drawable-resource.html#StateList

http://blog.marvinlabs.com/2010/10/29/custom-listview-ability-check-items/

【讨论】:

  • 这个答案是无价的。我希望在尝试解决如何实现 Checkable 布局等之前先阅读它。非常感谢。
  • 很好的答案,但没有解决“选定”项目。我在你引用之前的句子中找到了答案:Selection is a transient property, representing the view (hierarchy) the user is currently interacting with. Activation is a longer-term state that the user can move views in and out of. For example, in a list view with single or multiple selection enabled, the views in the current selection set are activated. (Um, yeah, we are deeply sorry about the terminology here.)source
  • 我的自定义背景颜色仅出现在选定/聚焦的项目后面,而不是选中的项目,当使用您在上面发布的后蜂窝方法时:调用setItemChecked(),然后使用具有属性android:state_activated="true"的选择器
  • 非常感谢,我浪费了 3 天的时间试图弄清楚这一点,直到我最终决定问自己“检查、选择和激活之间有什么区别”,处理像菜单必须如此复杂,谷歌的天才们过度设计,几乎看起来像是这家公司故意设置的障碍,以减慢其他人的速度。
【解决方案2】:

根据doc

  • android:state_selected 布尔值。 "true" 如果在导航时对象为当前用户选择时应使用此项 带有方向控制(例如在列表中导航时) 带方向键); "false" 如果该项目应该在对象被使用时使用 未选中的。焦点时使用选中状态 (android:state_focused) 是不够的(比如当列表视图有 焦点并使用 d-pad 选择其中的项目)。

  • android:state_checked 布尔值。 “true”如果在检查对象时应该使用此项; "false" 如果应该在 对象未选中。

  • android:state_activated 布尔值。 "true" 如果在对象被激活为持久选择时应使用此项(例如 至于“突出显示”先前选择的列表项 导航视图); "false" 如果在对象不是时应该使用它 活性。 API 级别 11 中引入。

我认为文档很清楚,那么问题是什么?

【讨论】:

  • 你能详细说明一下android:state_selected。设置为true的情况是什么?
  • @Anderson 这将取决于您正在使用的 ViewGroup - ListView、RecyclerView(可能是它的 LayoutManagers)、GridView 可能有不同的实现:ListView 调用 setFocused,而 GridView 调用 setSelected。这可能只是在不同平台版本上检查您的应用的情况。
  • @Anderson:如果你有一个列表,并且用户有箭头键,那么一个是“选中的”,当他们向上/向下箭头时,选择向上/向下移动。当他们按下“激活”键时,它会“激活”控件,将其视为类似于鼠标悬停的选择,而将检查/激活视为类似于单击。
  • 我想知道,我将使用激活来突出显示列表视图中的一个项目,但它是否将其他列表项的激活设置为 false ...如果不这样做这样我就不必找到另一个激活的子项并将激活设置为 false?
【解决方案3】:

这里是这个问题的其他解决方案: https://github.com/jiahaoliuliu/CustomizedListRow/blob/master/src/com/jiahaoliuliu/android/customizedlistview/MainActivity.java

我已经覆盖了 setOnItemClickListener 方法并检查了代码中的不同情况。但毫无疑问,马文的解决方案要好得多。

listView.setOnItemClickListener(new OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position,
        long id) {
    CheckedTextView checkedTextView =
            (CheckedTextView)view.findViewById(R.id.checkedTextView);
    // Save the actual selected row data
    boolean checked = checkedTextView.isChecked();
    int choiceMode = listView.getChoiceMode();
    switch (choiceMode) {
    // Not choosing anything
    case (ListView.CHOICE_MODE_NONE):
        // Clear all selected data
        clearSelection();
        //printCheckedElements();
        break;
    // Single choice
    case (ListView.CHOICE_MODE_SINGLE):
        // Clear all the selected data
        // Revert the actual row data
        clearSelection();
        toggle(checked, checkedTextView, position);
        //printCheckedElements();
        break;
    // Multiple choice
    case (ListView.CHOICE_MODE_MULTIPLE):
    case (ListView.CHOICE_MODE_MULTIPLE_MODAL):
        // Revert the actual selected row data
        toggle(checked, checkedTextView, position);
        //printCheckedElements();
        break;
    }
    }
});

【讨论】:

    猜你喜欢
    • 2011-12-19
    • 2012-05-24
    • 1970-01-01
    • 1970-01-01
    • 2011-09-23
    • 1970-01-01
    • 2023-03-26
    • 2012-11-14
    • 2022-01-22
    相关资源
    最近更新 更多