【问题标题】:Android listActivity onListItemClick with CheckBoxAndroid listActivity onListItemClick 与 CheckBox
【发布时间】:2011-09-23 00:28:44
【问题描述】:

我的问题是如何访问和更改列表活动中任何项目的复选框模式。我有一个带有复选框和文本视图的 XML 模板文件,它们定义了一行。到目前为止,这是我正在尝试的:

@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);
        Toast.makeText(this, "You selected: " + Integer.toString(position), Toast.LENGTH_LONG).show();

        CheckBox checkbox = (CheckBox) findViewById(R.id.checkbox); 
        if (checkbox.isChecked() == false) {
            checkbox.setChecked(true); 
        } else {
            checkbox.setChecked(false); 
        }

}

显然,尽管使用 R.id.checkbox 只会切换第一个复选框(实际上,它会执行我在屏幕上查看的列表的任何部分的第一个复选框)。我不确定使用什么函数来获取任何行的复选框。顺便说一句,Toast 工作正常,所以至少它正确地记录了位置。

感谢您的帮助。

编辑 - 我现在正在尝试继承 SimpleCursorAdapter 以更好地控制我想要的行为。这是那个子类:

public class musicPlaylist extends SimpleCursorAdapter {

private Cursor c;
private Context context;
private ArrayList<String> checkList = new ArrayList<String>();
private final static int SELECTED = 1;
private final static int NOT_SELECTED = 0;

public musicPlaylist(Context context, int layout, Cursor c,
        String[] from, int[] to) {
    super(context, layout, c, from, to);
    this.c = c;
    this.context = context;

}

public View getView(int pos, View inView, ViewGroup parent) {
    View v = inView;
    if (v == null) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = inflater.inflate(R.layout.song_item, null);
    }

    this.c.moveToPosition(pos);     
    int columnIndex = this.c.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME);
    String song = this.c.getString(columnIndex);

    TextView sTitle = (TextView) v.findViewById(R.id.text1);
    sTitle.setText(song);
    v.setId(NOT_SELECTED);
    v.setTag(song); 
    v.setOnClickListener(new OnClickListener() {



        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub


            if (v.getId() == NOT_SELECTED) {
                v.setId(SELECTED);
                Toast.makeText(context, "Test: " + v.getId(), Toast.LENGTH_SHORT).show();  
                v.setBackgroundColor(Color.parseColor("#FFFFFF"));

            } else {
                v.setId(NOT_SELECTED);
                Toast.makeText(context, "Test: " + v.getId(), Toast.LENGTH_SHORT).show();  
                v.setBackgroundColor(Color.parseColor("#000000"));
            }

        }
    });

    return v; 
}

}

作为参考,这里是我正在制作的 ListActivity 的 XML:

<?xml version="1.0" encoding="utf-8"?>

 <ListView android:id="@android:id/list"
           android:layout_width="fill_parent"
           android:layout_height="fill_parent"
           android:layout_weight="1"
           android:drawSelectorOnTop="false"
           android:fastScrollEnabled="true"
           android:cacheColorHint="#00000000"
           />

 <TextView android:id="@android:id/empty"
           android:layout_width="fill_parent"
           android:layout_height="fill_parent"
           android:text="No data"/>

当前行为:SD 卡中的歌曲列表被制作成一个很好的可滚动列表。我确实从 getView() 的 onClick 中得到了一些适当的响应:我第一次点击一个项目时,它的标签是“1”并且它的背景变白,而第二次我为同一个项目敬酒时,我得到“ 0" 并且背景变黑,这与预期的一样。

问题是如果我选择 item1(使其背景为白色)然后向下滚动,我会注意到 item11、item21、item31、... 等也有白色背景。但是当我点击它们时,它们的 ID 属性变为“1”,这意味着它们在技术上从未被点击过!所以基本上当滚动“刷新”到下一个10个列表时,它会复制前10个的配色方案......?

希望我解释清楚。

【问题讨论】:

    标签: java android xml checkbox listactivity


    【解决方案1】:

    我认为这是一个更深层次的问题,不需要直接回答。

    你想达到什么目标?您真的只想选择您在屏幕上看到的复选框吗?请注意,这可能是非常随机的 - 列表视图仅包含屏幕上可见的复选框的项目视图,并且只要项目滚动到屏幕外,它们就会重复用于其他项目。

    我想说,几乎可以肯定,您需要更改列表中所有复选框的状态(即使是那些不可见的)或其中的某些子集(如部分)。这真的转化为应该做的正确方式:

    • 适当修改您的数据模型 标记在相应数据模型元素中选择的适当标志 (您为每个项目存储的一些布尔值)
    • 在您的适配器上调用 notifyDataSetChanged()。

    因此,列表视图将重新创建屏幕上可见的所有视图。假设适配器中的“getView()”编写正确,它将读取正确的模型并适当地更新项目的检查状态。 通过 notifyDataSetChanged - 如果您在屏幕上有 10 个项目可见,则每个可见项目都会调用 10 次 getView()。

    【讨论】:

    • 我认为你是对的。到目前为止,我所做的是创建一个继承 SimpleCursorAdapter 的新类,并且我正在覆盖 getView() 方法。一切正常,但我通过更改文本背景颜色测试了 onClick 的视图,并且我得到了“回收”效果或调用它,如果我在屏幕上选择 item1,它假设我也选择了item11、item21 等(并更改所有背景颜色)。我该怎么做才能使每个视图的 onClick 都是唯一的?
    • 啊..这是另一个问题。看看这篇文章 - 它详细解释了它:developer.android.com/resources/articles/…。如果您使用自定义背景,则只需使用 cacheColorHint(或禁用 Android listView 中实现的优化)即可。
    • 嗯,我不认为这是我的问题,因为我做了 cacheColorHint 并且我仍然遇到 item1 的 onClick 应用于 item11、item21 等的回收问题(基本上每当屏幕刷新到新一组选项)。你回答的最后一句话提到了 notifyDataSetChanged - 我应该在某个地方实现吗?怎么样?
    • 改变所有元素的背景也可能是由于没有改变 Drawable 造成的。如果你得到“stateDrawable”并且不改变它,那么它就是选择/聚焦等状态在同一个drawable的不同实例之间共享(你需要在使用之前改变它)。在适配器上调用 notifyDataSetChanged() 将使列表视图重新查询所有可见元素的适配器 - 我认为这不是你的问题。您需要发布一些代码示例和观察到的行为的屏幕截图,因为我有一种感觉,我们不知何故彼此不理解:)。
    • 马上编辑 OP 并尽力解释,感谢您的支持 =)
    【解决方案2】:

    我建议使用android:choiceMode="multipleChoice" 而不是以这种方式手动操作您的行。行小部件需要实现Checkable 接口,这可以通过使用CheckedTextView 作为行本身或creating a subclass of your desired container and implementing Checkable on it 来完成。

    【讨论】:

      【解决方案3】:

      您使用“全局”视图而不是行视图。试试这样:

       @Override
       protected void onListItemClick(ListView l, View v, int position, long id) {
         super.onListItemClick(l, v, position, id);
      
          CheckBox checkbox = (CheckBox) v.findViewById(R.id.checkbox); 
          if (checkbox.isChecked() == false) {
              checkbox.setChecked(true); 
          } else {
              checkbox.setChecked(false); 
          }
       }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-06-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-19
        相关资源
        最近更新 更多