【问题标题】:ListActivity's onListItemClick does not workListActivity 的 onListItemClick 不起作用
【发布时间】:2012-05-22 20:27:35
【问题描述】:

在我的带有 ListActivity 的应用程序中,通过单击 ListView 项目不会触发覆盖的 onListItemClick 回调。

我已经定义了一个自定义列表视图,其中包含以下 xml 文件,permissionview.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/btn_Apply"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/btn_apply"
            android:onClick="onApplyClick" />

        <Button
            android:id="@+id/btn_install"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/btn_install"
            android:onClick="onInstallClick" />

        <Button
            android:id="@+id/btn_cancel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Cancel" />

    </LinearLayout>

    <ListView android:id="@android:id/list" 
            android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:focusable="false">

    </ListView>  
</LinearLayout>

以及视图项布局checkable.xml

  <?xml version="1.0" encoding="utf-8"?>
  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >


   <ImageView android:id="@+id/img" android:layout_width="wrap_content"
        android:layout_height="wrap_content" android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true" android:layout_alignParentBottom="true"
        android:src="@drawable/ic_launcher" android:focusable="false" />

    <CheckBox
        android:id="@+id/check"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
       android:layout_alignParentRight="true"
        android:layout_marginLeft="4px"
    android:layout_marginRight="10px"

    android:clickable="true">

 </CheckBox>

    <TextView
        android:id="@+id/label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_toRightOf="@+id/img"
        android:gravity="bottom"
        android:text="@+id/label"
        android:textSize="15px"/>
</RelativeLayout>

定义的ArrayAdapter定义如下:

     public class InteractiveArrayAdapter extends ArrayAdapter<Model> {


    private final List<Model> list;
    private final Activity context;
    private boolean changeable;

    public InteractiveArrayAdapter(Activity context, List<Model> list, boolean changeable) {
        super(context, R.layout.checkable, list);
        this.context = context;
        this.list = list;
        this.changeable = changeable;
    }

    static class ViewHolder {
        protected TextView text;
        protected CheckBox checkbox;
        protected ImageView image;
        protected int pos;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        View view = null;
        if (convertView == null) {
            LayoutInflater inflater = context.getLayoutInflater();
                view = inflater.inflate(R.layout.checkable, null);


            final ViewHolder viewHolder = new ViewHolder();
            viewHolder.text = (TextView) view.findViewById(R.id.label);
            viewHolder.checkbox = (CheckBox) view.findViewById(R.id.check);
            viewHolder.image = (ImageView) view.findViewById(R.id.img);
            viewHolder.pos = position;


            view.setClickable(true);

            if (!changeable)viewHolder.checkbox.setEnabled(false);


            viewHolder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {



                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    Model element = (Model) viewHolder.checkbox.getTag();

                    element.setActive(buttonView.isChecked());
                }

            }
            );



            view.setTag(viewHolder);
            viewHolder.checkbox.setTag(list.get(position));

        } else {
            view = convertView;
            ((ViewHolder) view.getTag()).checkbox.setTag(list.get(position));

        }
        ViewHolder holder = (ViewHolder) view.getTag();
        holder.text.setText(list.get(position).showPermission());
        holder.checkbox.setChecked(list.get(position).isActive());

        if (list.get(position).isRedundant()) {
            holder.image.setImageDrawable(context.getResources().getDrawable(R.drawable.warning));
        } else {
            holder.image.setImageDrawable(context.getResources().getDrawable(R.drawable.ok));
        }
        return view;

    }

}

在扩展 ListActivity 的类中,定义的 ArrayAdapter 用 asyncTask 中的 arrayList 填充(列表信息在doInBackground() 方法中计算):

public class PermissionViewActivity extends ListActivity {

    private final static String TAG = "PMA";
    ...
     @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.permissionview);
        ...
    }

    ... 

     private class CurrentPermissions extends AsyncTask<String, Integer, String> {

        private ListActivity la;
        private Context context;



        private int progress = 0;

        public CurrentPermissions(ListActivity la) {
            this.la = la;
            this.context = la;

        }

        protected void onPreExecute() {
        ...

        protected void onPostExecute(String result) {
          adapter = new InteractiveArrayAdapter(la, permissionList, changeable);
          la.setListAdapter(adapter);
          /output with number of listitems
              System.out.println("DEBUG1 " + la.getListAdapter().getCount());
        }
     }
      ...
      @Override
      protected void onListItemClick(ListView l,  View view, int position, long id) {
        super.onListItemClick(l, view, position, id);
        System.out.println("clicked !");
      }
      ...
    }

onListItemClick 方法未执行。在 ArrayAdapter 中定义 onClickListener 时,点击事件起作用:

 view.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {

                    System.out.println("Klick D1 " + list.get(viewHolder.pos));

                }

            });

为什么 ArrayAdapter 中的 click-event 定义有效,但 ListActivity 中的覆盖无效?我找不到失败的地方。

【问题讨论】:

    标签: android android-listview adapter listactivity


    【解决方案1】:

    尝试将行布局中的CheckBox 也设置为不是focusable

    //...
     <CheckBox
        android:id="@+id/check"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_marginLeft="4px"
        android:layout_marginRight="10px"
        android:focusable="false" 
        android:clickable="true">
    
    //...
    

    【讨论】:

    • 阅读焦点问题并尝试了这个,但没有帮助。
    • @user1411093 您是否也尝试过android:descendantFocusability="beforeDescendants" 上的android:descendantFocusability="beforeDescendants" 属性(并从ListView 中删除android:focusable="false")?(但保留android:focusable="false" 上的CheckBox )
    • 终于找到了解决办法,是android:descendantFocusability="afterDescendants"谢谢你的帮助。
    【解决方案2】:

    如果您想要一个“通用”点击监听器(适用于列表视图中的所有项目),您的活动应该实现 OnItemClickListener

    public class PermissionViewActivity extends ListActivity implements OnItemClickListener
    

    您将需要覆盖该方法

    @Override
    public void onItemClick(AdapterView<?> arg0, View v, int position, long arg3)
    {
         Toast.makeText(this, "Clicked", Toast.LENGTH_SHORT).show();
    }
    

    那么你必须在你的listview上手动设置点击监听

    例如

    public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.permissionview);
            ...
            getListView().setOnItemClickListener(this);
    }
    

    【讨论】:

    • 试过这个,但没用。 getListView() 传递一个对象,也可以使用getOnItemClickListener 访问它,但是当我单击时侦听器没有“触发”。我找不到问题,是否有任何选项可以阻止执行侦听器事件?
    • 是的!您的列表视图中有一个复选框,它实质上将“窃取”列表视图中的点击功能。在 checkable.xml 中的 标记下添加 android:focusable="false"
    • 是的,我发现,checkbos“窃取”了点击事件,当我为复选框设置clickable="false"时,click vor listitem 有效,但我需要两者并且可聚焦不起作用。
    • 终于找到了解决办法,是android:descendantFocusability="afterDescendants",感谢您的帮助。
    【解决方案3】:

    我在包含 ListView 的视图中执行此操作:

    ListView lv = (ListView)findViewById(R.id.myList);
    lv.setAdapter(new myCustomAdapter,items);
    lv.setOnItemClickListener(new AdapterView.OnItemClickListener(){
        public void onItemClick(AdapterView<?> arg0, View arg1, int position, long id){
            /* do something i've been clicked */
    
    });
    

    或在 onItemSelected 事件中

    lv.setOnItemSelectedListener(new AdapterView.onItemSelectedListener(){
        public void onItemSelected(AdapterView<?> arg0, View arg1, int position, long id){
            ...
        }
        public void onNothingSelected(AdapterView<?> arg0){
            ...
        }
    });
    

    希望对你有帮助

    【讨论】:

    • 我尝试了类似的方法,但我定义了ListView lv = getListView()。我不明白 id myList 是在哪里定义的?思想 ListView 必须用@android:id/list 定义?
    【解决方案4】:

    如果您在 ListItem 中有可单击视图,则需要将可聚焦标志设置为 false。通过在布局中设置 focusable=false,当以编程方式设置 Listener 时,它将被覆盖。

    我的解决方案通过以编程方式调用设置可聚焦性为我工作

    listview.setOnItemClickListener(this);
    listview.setFocusable(false);
    

    【讨论】:

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