Android:无法选中CheckedTextView?

52

一开始我希望有一个打勾的标记,且文本位于打勾标记的左侧。在这个网站上搜索后,我发现最好的解决方法是使用android:CheckedTextView。然而我发现用户无法手动更改打勾标记。这是设计上的问题吗?

<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android" 
 android:id="@+id/autoupdatecheckboxview" 
 android:layout_width="fill_parent" 
 android:layout_height="wrap_content" 
 android:gravity="center_vertical" 
 android:checkMark="?android:attr/listChoiceIndicatorMultiple" 
 android:paddingLeft="6dip" 
 android:paddingRight="6dip" 
 android:text="Pop up a message when new data available" 
 android:typeface="sans" android:textSize="16dip"/> 

那么 CheckedTextView 应该被命名为 ListCheckedTextView?该死的谷歌。 - EngineSense
7个回答

132

你想要的实现是可能的,而且相当简单。是的,CheckedTextView 主要用于在 ListView 行中具有单个可选视图,并使用 choiceMode 控制其子项的可选状态。然而,由于 CheckBox 看起来不支持右对齐的复选框,而 CheckedTextView 是一个右对齐的复选框,因此想要使用已有的控件是有意义的。

由于 ListView 控制列表项的选中状态,CheckedTextView 本身不响应点击事件,并且默认情况下不可点击或无法获取焦点。但是,它确实响应按下和聚焦状态,这意味着它可以接收焦点和点击事件,并且看起来像一个复选框应该看起来的样子。唯一缺少的是它不能在单击时切换其选中状态。因此,快速添加一个调用 .toggle() 的 OnClickListener 就可以得到你想要的最终结果。

简而言之,你需要三个东西:可点击、可获得焦点和 onClickListener:

    CheckedTextView chkBox = (CheckedTextView) findViewById(R.id.CheckedTextView01);
    chkBox.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v)
        {
            ((CheckedTextView) v).toggle();
        }
    });

和布局文件:

<CheckedTextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/CheckedTextView01"
    android:checked="true"
    android:clickable="true"
    android:focusable="true"
    android:text="Label on Left Side of Checkbox."
    />

2
感谢您的解释:默认情况下为什么这种控件可能是不可点击的并不明显。 - Smileek
5
很好的答案。为了使CheckedTextView更像列表项,您应该将背景设置为<item name="android:background">?android:attr/listChoiceBackgroundIndicator</item>。 - Moritz
也为这个点赞 https://dev59.com/XWcs5IYBdhLWcg3wtmID - nAkhmedov
非常感谢 @Joe,解释得非常好。 - mochadwi
在 Kotlin 中,我不得不使用 "with (view as CheckedTextView) {isChecked = !isChecked}" 或者使用 "if (checkbos.isChecked)... failed",因为 isChecked 的值是错误的。 - steven smith

38

你可能只需要使用普通的CheckBox(它继承自Button,因此也继承了TextView)。CheckedTextView是为列表视图设计的。下面是一个示例CheckBox布局XML:

<CheckBox
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Pop up a message when new data available"
    android:textSize="16dip" />

如果我不想添加另一个视图呢? - Chisko
5
这并没有回答问题。考虑到有些人知道CheckBox更适合,但仍然希望使用CheckedTextView。他们想知道如何让它正常工作,而不是被告知它不应该使用。 - NoHarmDan

9
您可以按照以下方式使用和切换CheckedTextView:
在布局中:
<CheckedTextView
        android:id="@+id/cv_id"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Some text here" 
        android:textSize="18sp"
        android:gravity="center_vertical"
        android:clickable="true"
        android:checkMark="@drawable/btn_check_off"
        android:focusable="true"
        android:checked="false"
        android:onClick="toggle"/>

在您的活动中:

public void toggle(View v)
{
    CheckedTextView cView = (CheckedTextView) v.findViewById(R.id.cv_file_name);
        if (cView.isSelected())
        {
            cView.setSelected(false);
            cView.setCheckMarkDrawable (R.drawable.btn_check_off);
        }
        else
        {
            cView.setSelected(true);
            cView.setCheckMarkDrawable (R.drawable.btn_check_on);
        }
}

不要忘记放置可绘制资源。我是从SDK中获取的...\android-sdk-windows\platforms\android-10\data\res\drawable-mdpi\


3
简单的回答是添加自己的onClickListener,并使用isChecked()方法而不是isSelected()方法。
CheckedTextView chkBox = (CheckedTextView) findViewById(R.id.CheckedTextView01);
chkBox.setOnClickListener(new View.OnClickListener() {
    public void onClick(View v)
    {
        if(((CheckedTextView) v).isChecked()){
            ((CheckedTextView) v).setChecked(false);
        }else{
            ((CheckedTextView) v).setChecked(true);            
        }
    }
});

使用view.isChecked()方法获取状态。


2

这个布局的外观和CheckedTextView类似:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="?attr/dropdownListPreferredItemHeight"
    android:gravity="center_vertical" >

    <TextView
        android:id="@android:id/text1"
        style="?android:attr/spinnerDropDownItemStyle"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:ellipsize="marquee"
        android:singleLine="true" />

    <CheckBox
        android:id="@android:id/checkbox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="false"
        android:duplicateParentState="true"
        android:focusable="false" />

</LinearLayout>

唯一需要额外的工作是在根视图上设置一个OnClickListener,并在CheckBox上调用checkBox.toggle()


1

这是我在SingleChoiceDialog中的使用

1.select_dialog_singlechoice.xml

<?xml version="1.0" encoding="UTF-8"?>
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/text1"
    style="@style/PopupSelectList"
    android:checkMark="@drawable/radio"
    android:ellipsize="marquee"
    android:gravity="center_vertical"
    android:paddingLeft="12.0dip"
    android:paddingRight="10.0dip" />

2.style.xml

<style name="PopupSelectList">
    <item name="android:textSize">16.0sp</item>
    <item name="android:textColor">@color/white</item>
    <item name="android:background">@drawable/list_item_selector</item>
    <item name="android:layout_width">fill_parent</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:minHeight">@dimen/dialog_select_height</item>
</style>

3.radio.xml

<?xml version="1.0" encoding="UTF-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/dot_selected" android:state_checked="true" android:state_window_focused="false"/>
    <item android:drawable="@drawable/dot_normal" android:state_checked="false" android:state_window_focused="false"/>
    <item android:drawable="@drawable/dot_normal" android:state_checked="false"/>
    <item android:drawable="@drawable/dot_selected" android:state_checked="true"/>
</selector>

在适配器的getView方法中。
CheckedTextView title = (CheckedTextView) convertView
                .findViewById(android.R.id.text1);
        title.setText(mItems[position]);
        title.setSelected(mCheckedItem == position ? true : false);
                    title.setCheckMarkDrawable(position == mCheckedItem ?                   R.drawable.dot_selected
                : R.drawable.dot_normal);

变量 mCheckedItem 在我的 ArrayAdapter 中找不到。 - JPM
您可以将CheckedTextView放置在任何您想要的地方。 - Geek4IT

0
如果您想更精细地控制标签和复选框,另一种选择是使用RelativeLayout和android:layout_alignParentRight属性:
<RelativeLayout 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
    <TextView
        android:id="@+id/my_checkbox_label" 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="my checkbox label" />
    <CheckBox
        android:id="@+id/my_checkbox" 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true" />
</RelativeLayout>

然后,您可以调整TextView和CheckBox的边距等以满足您的需求。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接