【问题标题】:listeners inside arrayAdapter getView methodarrayAdapter getView 方法中的侦听器
【发布时间】:2012-12-29 16:14:06
【问题描述】:

我有一个用于 ListView 的自定义 row_item,其中包含一个图像、一对 TextView 和一个复选框。 据我了解,由于 checkBox 是一个可聚焦元素,它会从 listView 中窃取焦点,因此 OnListItemClicked 永远不会被触发,除非我将每个 row_item 都设置为不可点击并且我阻止后代的可聚焦性。

然后,为了管理复选框更改,我在适配器 getView 方法中为我的复选框设置了“OnCheckedChangeListener”。

这是一种不好的做法吗? (因为每次调用 getView 时我都会创建新的侦听器) 有没有其他方法可以做到这一点?

我附上一些代码,以便更容易理解我的意思。

getView 方法:(在 arrayAdapter 内)

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    /** recycling views */
    View row = convertView;
    PregoHolder holder = null;

    if(row == null)
    {
        LayoutInflater inflater = ((Activity)context).getLayoutInflater();
        row = inflater.inflate(layoutResourceId, parent, false);

        holder = new PregoHolder();
        holder.imgIcon = (ImageView)row.findViewById(R.id.thumbnail);
        holder.txtTitle = (TextView)row.findViewById(R.id.txtTitle);
        holder.txtNews = (TextView)row.findViewById(R.id.txtNews);
        holder.chBox = (CheckBox) row.findViewById(R.id.checkBox);

        row.setTag(holder);
    }
    else
    {
        holder = (PregoHolder)row.getTag();
    }

    Prego Prego = data[position];
    holder.txtTitle.setText(Prego.title);
    holder.imgIcon.setImageResource(Prego.icon);
    holder.txtNews.setText(Prego.news);
    holder.chBox.setChecked(Prego.checked);

    /** wiring up Listeners... 
     * (works fine but we are creating new listener each time)
     * (Done like this because of the custom list view focusable issue)
     */

    holder.chBox.setOnCheckedChangeListener(new OnCheckedChangeListener(){

        @Override
        public void onCheckedChanged(CompoundButton arg0, boolean checked) {
            /** Getting the view position in the ListView */
            ListView parent = (ListView)(arg0.getParent()).getParent();
            int pos = parent.getPositionForView(arg0);

            if (checked){
                checkedPregons[pos] = true;
                pregonsChecked++;
            }
            else if (!checked){
                checkedPregons[pos] = false;
                pregonsChecked--;
            }

            Toast.makeText(context, pregonsChecked+" is/are checked", Toast.LENGTH_SHORT).show();
        }
    });

    row.setOnClickListener(new OnClickListener(){

        @Override
        public void onClick(View v) {
            //mMode = ((Activity)context).startActionMode(new PregonsActionModes());
            ListView parent = (ListView)v.getParent();
            int pos = parent.getPositionForView(v);
            Toast.makeText(context, "getView should show prego "+pos,Toast.LENGTH_SHORT).show();

        }
    });

    return row;
}

提前致谢。

【问题讨论】:

  • 您是否需要使列表视图的其他元素可点击?能下钻吗?如果这两个都是否定的,那么最好在行点击时切换选中状态。
  • 我需要使列表项可点击,因此当您按下复选框外但在一行内时,它会打开另一个活动。我也尝试通过单击行来管理它,但是当我只在复选框内按下时,不会触发任何侦听器。 (所以我必须先切换复选框的状态,然后单击行...)这就是为什么我决定这样做...

标签: android listview listener


【解决方案1】:

我想可能有更好的方法来解决它,但这不是我会失眠的事情。您的方法已被许多新老安卓开发人员广泛实施,这只是一种简单自然的方式。此外,请记住,ListView 一次只能在屏幕上看到尽可能多的行(并且在滚动时不断调用getView),所以你说的是 8 - 12 个制造对象任何给定的时间(显然完全在猜测),所以你的瓶颈不会在这里。事实上,根据我需要修改的对象在哪里,我什至没有考虑它。

但是在ListView 中使用OnCheckedChangeListener 是我强烈警告的事情。就像我说的,getView 在滚动和制作时会为每一行调用。这个经过检查的已更改侦听器正在被触发,尽管它绝对不能保证每行只调用一次 getView,事实上我保证不会。因此,这些代码块可能会被 wazoo 激发,即使您可能只打算手动处理 CheckBox 框刻度。输入一个相对更密集的命令,如notifyDataSetChanged(),你会看到你的ListView 锁定了这个现象。

解决方案是简单地使用复选框onClickListener 并检查内部的isChecked()。

【讨论】:

  • 太棒了!!感谢您的回答!我认为在最坏的情况下,一次只能制作几个对象,如你所说,但我担心我是否做错了我什至没有想到的其他事情。 (如 onCheckedChangeListener)再次感谢!
猜你喜欢
  • 2012-09-06
  • 2013-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多