【问题标题】:Multiple choice list with custom view?带有自定义视图的多项选择列表?
【发布时间】:2010-04-16 10:17:53
【问题描述】:

我从 ApiDemos 看到了示例 com.example.android.apis.view.List11。在该示例中,每一行都采用 android.R.simple_list_item_multiple_choice 视图。每个这样的视图都有一个TextView 和一个CheckBox

现在我希望每个视图有 2 个TextViews 和 1 个CheckBox,有点类似于 List3 示例。我尝试像这样创建自定义布局文件 row.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <CheckBox
        android:id="@+id/checkbox"
        android:layout_alignParentRight="true"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent" />
    <TextView
        android:id="@+id/text_name"
        android:textSize="13px"
        android:textStyle="bold"
        android:layout_toLeftOf="@id/checkbox"
        android:layout_alignParentLeft="true"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/text_phone"
        android:textSize="9px"
        android:layout_toLeftOf="@id/checkbox"
        android:layout_below="@id/text_name"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" /> 
</RelativeLayout>

然后在ActivityonCreate(),我喜欢这样:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Query the contacts
    mCursor = getContentResolver().query(Phones.CONTENT_URI, null, null, null, null);
    startManagingCursor(mCursor);

    ListAdapter adapter = new SimpleCursorAdapter(this,
            R.layout.row,
            mCursor, 
            new String[] { Phones.NAME, Phones.NUMBER}, 
            new int[] { R.id.text_name, R.id.text_phone });
    setListAdapter(adapter);
    getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
}

结果有点像我想要的,但看起来列表不知道选择了哪个项目。另外,我需要准确地点击CheckBox。在 List11 示例中,我只需要单击项目行。

那么我需要怎么做才能使用我的自定义视图为每一行制作一个多项选择列表?非常感谢。

【问题讨论】:

标签: android listview user-interface custom-view


【解决方案1】:

您必须创建自己的实现Checkable 接口的RelativeLayout,并引用CheckBoxCheckedTextView(如果是多选模式,则为列表)。

看看这个帖子: http://www.marvinlabs.com/2010/10/29/custom-listview-ability-check-items/

【讨论】:

  • 链接发布也解决了用户直接点击复选框时的问题
  • 教程很好,但缺少一个重要部分:如何处理包含 ListView 的 Activity 中的列表项点击,以便显示上下文操作栏?跨度>
  • @ferdy182 您所指的帖子不再可用。您能否提供文章的副本(或至少是代码)?谢谢
  • @MarekSebera 您可以在此处找到缓存版本,但最好将其复制到其他地方web.archive.org/web/20101105004007/http://www.marvinlabs.com/…
【解决方案2】:

Rahul Garg 的回答在第一次加载列表时很好,如果您希望根据模型数据检查某些行,但之后您必须自己处理检查/取消检查事件。

您可以覆盖ListActivityonListItemCLick() 以选中/取消选中行

@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);
    ViewGroup row = (ViewGroup)v;
 CheckBox check = (CheckBox) row.findViewById(R.id.checkbox);            
    check.toggle();
}

如果这样做,请不要将ListView设置为CHOICE_MODE_MULTIPLE,因为调用函数时会产生奇怪的事情。

要检索检查的行列表,你必须自己实现一个方法,在ListView 上调用getCheckItemIds() 不起作用:

ListView l = getListView();
int count = l.getCount();
for(int i=0; i<count; ++i) {
   ViewGroup row = (ViewGroup)l.getChildAt(i);
   CheckBox check = (Checked) row.findViewById(R.id.ck1);
   if( check.isChecked() ) {
      // do something
   }
}

【讨论】:

  • 谢谢@JVitela :) 为我工作
【解决方案3】:

每个这样的视图都有一个 TextView 和一个 复选框。

不,它没有。它有一个CheckedTextView

那么我需要做些什么来制作一个 带有我的自定义的多项选择列表 查看每一行?

尝试将CheckBox android:id 的值设为"@android:id/text1",看看是否有帮助。那是Android在simple_list_item_multiple_choice中为CheckedTextView使用的ID。

【讨论】:

  • 感谢 CommonsWare。我只是尝试过,但这对我不起作用。顺便说一句,我在哪里寻找 android.R.simple_list_item_multiple_choice 的实现?我在 ApiDemos 中找不到同名的 xml 文件。
  • 不在 ApiDemos 中,在 SDK 中。所有 SDK 资源都位于 $ANDROID_SDK/platforms/$VERSION/data/res,其中$ANDROID_SDK 是您安装 SDK 的位置,$VERSION 是某个 Android 版本(例如,android-2.1)。
  • 谢谢。我检查了 simple_list_item_multiple_choice 的内容。我发现如果每行的视图只是,它就可以工作。一旦我用布局包裹它,事情就不再起作用了。我不知道如何塞进一个视图来显示另一段文字。
  • 啊。好吧,那么您可能会陷入自己管理这一切的困境。下面是一个包含 RatingBar 和 TextView 的列表示例,在滚动时会保持 RatingBar 的状态:github.com/commonsguy/cw-android/tree/master/FancyLists/…——同样的技术可以适用于您自己的复选框。
【解决方案4】:

解决方案是创建一个实现 Clickable 接口的自定义 View。

public class OneLineCheckableListItem extends LinearLayout implements Checkable {

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

    private boolean checked;


    @Override
    public boolean isChecked() {
        return checked;
    }

    @Override
    public void setChecked(boolean checked) {
        this.checked = checked; 

        ImageView iv = (ImageView) findViewById(R.id.SelectImageView);
        iv.setImageResource(checked ? R.drawable.button_up : R.drawable.button_down);
    }

    @Override
    public void toggle() {
        this.checked = !this.checked;
    }
}

并使用新的小部件为列表项创建自定义布局。

<?xml version="1.0" encoding="utf-8"?>
<ax.wordster.OneLineCheckableListItem xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="4dp"
    android:background="@drawable/selector_listitem"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/SelectImageView"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:src="@drawable/button_friends_down" />

    <TextView
        android:id="@+id/ItemTextView"
        android:layout_width="fill_parent"
        android:layout_height="60dp"
        android:gravity="center"
        android:text="@string/___"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textColor="@color/text_item" />

</ax.wordster.OneLineCheckableListItem>

然后使用上面的布局创建一个新的自定义适配器。

【讨论】:

  • 你能帮我吗:如何在 itemView 和 onItemClick 中的 ImageView 上进行多项选择,而不是在 itemView 中进行多项选择,我可以进行其他操作吗?
  • 我的情况很奇怪,根本没有调用setChecked,而是调用了AbsListView.MultiChoiceModeListener#onItemCheckedStateChanged
【解决方案5】:

可以通过一些技巧来实现

在您的 ListActivtyClass 方法中

protected void onListItemClick(ListView l, View v, int position, long id) {
//just set
<your_model>.setSelected(true);
}

现在在您的自定义适配器中

public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(textViewResourceId, parent, false);
        }       
        if (<your_model>.isSelected()) {
            convertView.setBackgroundColor(Color.BLUE);
        } else {
            convertView.setBackgroundColor(Color.BLACK);
        }
        return convertView;
    }

这样您可以在列表中选择项目时自定义适配器中的视图。

【讨论】:

    【解决方案6】:

    如何将自定义布局用作自定义复选框的简单示例:

    private class FriendsAdapter extends ArrayAdapter<WordsterUser> {
        private Context context;
    
        public FriendsAdapter(Context context) {
            super(context, R.layout.listitem_oneline);
    
            this.context = context;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            final int pos = position;
    
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    
            View rv = inflater.inflate(R.layout.listitem_oneline, parent, false);
            rv.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    boolean checked = friendsListView.isItemChecked(pos); 
                    friendsListView.setItemChecked(pos, !checked);
                }
            });
    
            WordsterUser u = getItem(position);
    
            TextView itw = (TextView) rv.findViewById(R.id.ItemTextView);
            itw.setText(u.userName + " (" + u.loginName + ")");
    
            ImageView iv = (ImageView) rv.findViewById(R.id.SelectButton);
    
            if (friendsListView.isItemChecked(position)) {
                iv.setImageResource(R.drawable.downbutton);
            } else {
                iv.setImageResource(R.drawable.upbutton);
            }
    
            return rv;
        }
    }
    

    【讨论】:

    • 在您的示例中,FriendsAdapter 实例如何知道 friendsListView 引用的是什么?
    【解决方案7】:

    【讨论】:

    • Alvin Alexander 的 CheckableRelativeLayout 使行的顶级视图可检查,包括适当的可绘制状态 android.R.attr.state_checked。如果您将状态传递给它们,像 Checkbox 这样的子可绘制对象可以使用该状态。您必须将 android:duplicateParentState="true" 应用于 CheckableRelativeLayout 的每个子项,包括 Checkbox。
    【解决方案8】:

    得到解决方案...您可以通过在适配器本身中为每个视图添加侦听器来获得对视图的点击(如自定义行布局中的复选框),同时在 getView() 中返回转换后的视图。如果您打算获取任何列表特定信息,您可能必须传递列表对象的引用。比如行号。

    【讨论】:

      【解决方案9】:

      我想确认普里塔姆的回答是正确的。您需要在每个列表项上使用 onClickListener(在适配器的 getView() 中定义它)。

      您可以为每个项目创建一个新的onClickListener(),或者让适配器实现onClickListener() - 在这种情况下,必须标记项目以便侦听器知道它正在操作哪个项目。

      依赖列表 onItemClickListener() - 正如有人在另一个线程中建议的那样 - 将不起作用,因为 CheckBox 将拦截点击事件,因此列表将无法获取它。

      最后是@Rahul 和 JVitella:

      情况是列表项上的CheckBox 必须独立于列表项本身可单击和检查。因此,解决方案就像我上面描述的那样。

      【讨论】:

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