在Activity中响应ListView内部按钮的点击事件

Posted 请叫我码农怪蜀黍

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Activity中响应ListView内部按钮的点击事件相关的知识,希望对你有一定的参考价值。

最近交流群里面有人问到一个问题:如何在Activity中响应ListView内部按钮的点击事件,不要在Adapter中响应?

对于这个问题,我最初给他的解答是,在Adapter中定义一个回调接口,在Activity中实现该接口,从而实现对点击事件的响应。

下班后思考了一下,觉得有两种方式都能比较好的实现:使用接口回调和使用抽象类回调

正好可以复习一下接口和抽象类的区别,于是写了两个Demo:

1.使用接口回调:

Adapter类

复制代码
 1 package com.ivan.adapter;
 2 
 3 import java.util.List;
 4 
 5 import android.content.Context;
 6 import android.util.Log;
 7 import android.view.LayoutInflater;
 8 import android.view.View;
 9 import android.view.View.OnClickListener;
10 import android.view.ViewGroup;
11 import android.widget.BaseAdapter;
12 import android.widget.Button;
13 import android.widget.TextView;
14 
15 import com.ivan.listvieweventcallback.R;
16 
17 public class ContentAdapter extends BaseAdapter implements OnClickListener {
18 
19     private static final String TAG = "ContentAdapter";
20     private List<String> mContentList;
21     private LayoutInflater mInflater;
22     private Callback mCallback;
23 
24     /**
25      * 自定义接口,用于回调按钮点击事件到Activity
26      * @author Ivan Xu
27      * 2014-11-26
28      */
29     public interface Callback {
30         public void click(View v);
31     }
32 
33     public ContentAdapter(Context context, List<String> contentList,
34             Callback callback) {
35         mContentList = contentList;
36         mInflater = LayoutInflater.from(context);
37         mCallback = callback;
38     }
39 
40     @Override
41     public int getCount() {
42         Log.i(TAG, "getCount");
43         return mContentList.size();
44     }
45 
46     @Override
47     public Object getItem(int position) {
48         Log.i(TAG, "getItem");
49         return mContentList.get(position);
50     }
51 
52     @Override
53     public long getItemId(int position) {
54         Log.i(TAG, "getItemId");
55         return position;
56     }
57 
58     @Override
59     public View getView(int position, View convertView, ViewGroup parent) {
60         Log.i(TAG, "getView");
61         ViewHolder holder = null;
62         if (convertView == null) {
63             convertView = mInflater.inflate(R.layout.list_item, null);
64             holder = new ViewHolder();
65             holder.textView = (TextView) convertView
66                     .findViewById(R.id.textView1);
67             holder.button = (Button) convertView.findViewById(R.id.button1);
68             convertView.setTag(holder);
69         } else {
70             holder = (ViewHolder) convertView.getTag();
71         }
72         holder.textView.setText(mContentList.get(position));
73 
74         
75         holder.button.setOnClickListener(this);
76         holder.button.setTag(position);
77         return convertView;
78     }
79 
80     public class ViewHolder {
81         public TextView textView;
82         public Button button;
83     }
84 
85     //响应按钮点击事件,调用子定义接口,并传入View
86     @Override
87     public void onClick(View v) {
88         mCallback.click(v);
89     }
90 }
复制代码

Activity类:

复制代码
 1 package com.ivan.listvieweventdemo;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 import android.app.Activity;
 7 import android.os.Bundle;
 8 import android.view.Menu;
 9 import android.view.View;
10 import android.widget.AdapterView;
11 import android.widget.AdapterView.OnItemClickListener;
12 import android.widget.ListView;
13 import android.widget.Toast;
14 
15 import com.ivan.adapter.ContentAdapter;
16 import com.ivan.adapter.ContentAdapter.Callback;
17 import com.ivan.listvieweventcallback.R;
18 //MainActivity需要实现自定义接口
19 public class MainActivity extends Activity implements OnItemClickListener,
20         Callback {
21 
22     // 模拟listview中加载的数据
23     private static final String[] CONTENTS = { "北京", "上海", "广州", "深圳", "苏州",
24             "南京", "武汉", "长沙", "杭州" };
25     private List<String> contentList;
26     private ListView mListView;
27 
28     @Override
29     protected void onCreate(Bundle savedInstanceState) {
30         super.onCreate(savedInstanceState);
31         setContentView(R.layout.activity_main);
32 
33         init();
34     }
35 
36     private void init() {
37         mListView = (ListView) findViewById(R.id.listview);
38         contentList = new ArrayList<String>();
39         for (int i = 0; i < CONTENTS.length; i++) {
40             contentList.add(CONTENTS[i]);
41         }
42         //
43         mListView.setAdapter(new ContentAdapter(this, contentList, this));
44         mListView.setOnItemClickListener(this);
45     }
46 
47     @Override
48     public boolean onCreateOptionsMenu(Menu menu) {
49         getMenuInflater().inflate(R.menu.main, menu);
50         return true;
51     }
52 
53     /**
54      * 响应ListView中item的点击事件
55      */
56     @Override
57     public void onItemClick(AdapterView<?> arg0, View v, int position, long id) {
58         Toast.makeText(this, "listview的item被点击了!,点击的位置是-->" + position,
59                 Toast.LENGTH_SHORT).show();
60     }
61 
62     /**
63      * 接口方法,响应ListView按钮点击事件
64      */
65     @Override
66     public void click(View v) {
67         Toast.makeText(
68                 MainActivity.this,
69                 "listview的内部的按钮被点击了!,位置是-->" + (Integer) v.getTag() + ",内容是-->"
70                         + contentList.get((Integer) v.getTag()),
71                 Toast.LENGTH_SHORT).show();
72     }
73 }
复制代码

2.使用抽象类回调

Adapter类:

复制代码
 1 package com.ivan.adapter;
 2 
 3 import java.util.List;
 4 
 5 import android.content.Context;
 6 import android.util.Log;
 7 import android.view.LayoutInflater;
 8 import android.view.View;
 9 import android.view.View.OnClickListener;
10 import android.view.ViewGroup;
11 import android.widget.BaseAdapter;
12 import android.widget.Button;
13 import android.widget.TextView;
14 
15 import com.ivan.listvieweventabstract.R;
16 
17 public class ContentAdapter extends BaseAdapter {
18 
19     private static final String TAG = "ContentAdapter";
20     private List<String> mContentList;
21     private LayoutInflater mInflater;
22     private MyClickListener mListener;
23 
24     public ContentAdapter(Context context, List<String> contentList,
25             MyClickListener listener) {
26         mContentList = contentList;
27         mInflater = LayoutInflater.from(context);
28         mListener = listener;
29     }
30 
31     @Override
32     public int getCount() {
33         Log.i(TAG, "getCount");
34         return mContentList.size();
35     }
36 
37     @Override
38     public Object getItem(int position) {
39         Log.i(TAG, "getItem");
40         return mContentList.get(position);
41     }
42 
43     @Override
44     public long getItemId(int position) {
45         Log.i(TAG, "getItemId");
46         return position;
47     }
48 
49     @Override
50     public View getView(int position, View convertView, ViewGroup parent) {
51         Log.i(TAG, "getView");
52         ViewHolder holder = null;
53         if (convertView == null) {
54             convertView = mInflater.inflate(R.layout.list_item, null);
55             holder = new ViewHolder();
56             holder.textView = (TextView) convertView
57                     .findViewById(R.id.textView1);
58             holder.button = (Button) convertView.findViewById(R.id.button1);
59             convertView.setTag(holder);
60         } else {
61             holder = (ViewHolder) convertView.getTag();
62         }
63         holder.textView.setText(mContentList.get(position));
64         holder.button.setOnClickListener(mListener);
65         holder.button.setTag(position);
66         return convertView;
67     }
68 
69     public class ViewHolder {
70         public TextView textView;
71         public Button button;
72     }
73 
74     /**
75      * 用于回调的抽象类
76      * @author Ivan Xu
77      * 2014-11-26
78      */
79     public static abstract class MyClickListener implements OnClickListener {
80         /**
81          * 基类的onClick方法
82          */
83         @Override
84         public void onClick(View v) {
85             myOnClick((Integer) v.getTag(), v);
86         }
87         public abstract void myOnClick(int position, View v);
88     }
89 }
复制代码

Activity类:

复制代码
 1 package com.ivan.listvieweventdemo;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 import android.app.Activity;
 7 import android.os.Bundle;
 8 import android.view.Menu;
 9 import android.view.View;
10 import android.widget.AdapterView;
11 import android.widget.AdapterView.OnItemClickListener;
12 import android.widget.ListView;
13 import android.widget.Toast;
14 
15 import com.ivan.adapter.ContentAdapter;
16 import com.ivan.adapter.ContentAdapter.MyClickListener;
17 import com.ivan.listvieweventabstract.R;
18 
19 public class MainActivity extends Activity implements OnItemClickListener {
20 
21     // 模拟listview中加载的数据
22     private static final String[] CONTENTS = { "北京", "上海", "广州", "深圳", "苏州",
23             "南京", "武汉", "长沙", "杭州" };
24     private List<String> contentList;
25     private ListView mListView;
26 
27     @Override
28     protected void onCreate(Bundle savedInstanceState) {
29         super.onCreate(savedInstanceState);
30         setContentView(R.layout.activity_main);
31 
32         init();
33     }
34 
35     private void init() {
36         mListView = (ListView) findViewById(R.id.listview);
37         contentList = new ArrayList<String>();
38         for (int i = 0; i < CONTENTS.length; i++) {
39             contentList.add(CONTENTS[i]);
40         }
41         //实例化ContentAdapter类,并传入实现类
42         mListView.setAdapter(new ContentAdapter(this, contentList, mListener));
43         
44         mListView.setOnItemClickListener(this);
45     }
46 
47     @Override
48     public boolean onCreateOptionsMenu(Menu menu) {
49         getMenuInflater().inflate(R.menu.main, menu);
50         return true;
51     }
52 
53     //响应item点击事件
54     @Override
55     public void onItemClick(AdapterView<?> arg0, View v, int position, long id) {
56         Toast.makeText(this, "listview的item被点击了!,点击的位置是-->" + position,
57                 Toast.LENGTH_SHORT).show();
58     }
59 
60     /**
61      * 实现类,响应按钮点击事件
62      */
63     private MyClickListener mListener = new MyClickListener() {
64         @Override
65         public void myOnClick(int position, View v) {
66             Toast.makeText(
67                     MainActivity.this,
68                     "listview的内部的按钮被点击了!,位置是-->" + position + ",内容是-->"
69                             + contentList.get(position), Toast.LENGTH_SHORT)
70                     .show();
71         }
72     };
73 }
复制代码

 

以下是布局文件

复制代码
 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:paddingBottom="@dimen/activity_vertical_margin"
 6     android:paddingLeft="@dimen/activity_horizontal_margin"
 7     android:paddingRight="@dimen/activity_horizontal_margin"
 8     android:paddingTop="@dimen/activity_vertical_margin"
 9     tools:context=".MainActivity" >
10 
11     <ListView
12         android:id="@+id/listview"
13         android:layout_width="match_parent"
14         android:layout_height="match_parent" >
15     </ListView>
16 
17 </RelativeLayout>
复制代码
复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:descendantFocusability="blocksDescendants"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="content"
        android:textColor="#ff0000"
        android:textSize="20sp" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:focusable="false"
        android:text="Button"
        android:textColor="#ff0000"
        android:textSize="20sp" />

</LinearLayout>
复制代码

 

两种方式的区别在于,抽象类在Activity中实现的时候,只能定义一个成员变量来实现,不能由Activity直接实现,因为Java不支持多继承。而接口既可以由Activity直接实现,也可以由其成员变量来实现。

 

原创文章,转载请注明出处!

以上是关于在Activity中响应ListView内部按钮的点击事件的主要内容,如果未能解决你的问题,请参考以下文章

如何将数据从一个 Activity 中的 ListView 传递到另一个 Activity 上的 TextView?

我正在尝试使用 listview 按钮从 cutomlistadapter 打开 Android Activity。我尽了最大努力,但没有结果?

将所选数据的 ListView 显示到 textView 中的下一个 Activity

在另一个 Activity 中将字符串(或数组)传递给 ListView(NPE 错误)

Android ListView滑动删除及响应事件详解

android 弹出多个Activity的问题