有时候在ListView嵌入的布局中有多个事件需要点击,比如一个item中有TextView和Button两个布局,当我们需要获取这两个点击事件时,我们应该如何去获取呢,通常来说,我们都是已经固定好了TextView和Button的id的,,所以,这两个点击事件的id肯定是不会变的,假如我们有10个item,我们需要获取第5个item中的布局的button和TextView的点击事件该如何获取呢?下面将依依介绍。(适合初学者)

首先先看初次布局界面:

activity_main.xml布局:ListView的布局

  1.  
    <?xml version="1.0" encoding="utf-8"?>
  2.  
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.  
    xmlns:tools="http://schemas.android.com/tools"
  4.  
    android:layout_width="match_parent"
  5.  
    android:layout_height="match_parent"
  6.  
    tools:context="com.qianfeng.listviewbutton.MainActivity">
  7.  
    <ListView
  8.  
    android:id="@+id/mList"
  9.  
    android:layout_width="match_parent"
  10.  
    android:layout_height="match_parent">
  11.  
    </ListView>
  12.  
    </RelativeLayout>

list_item.xml布局:ListView item的每个布局

  1.  
    <?xml version="1.0" encoding="utf-8"?>
  2.  
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.  
    android:orientation="horizontal" android:layout_width="match_parent"
  4.  
    android:layout_height="match_parent">
  5.  
    <TextView
  6.  
    android:id="@+id/mTv"
  7.  
    android:layout_marginTop="10dp"
  8.  
    android:layout_width="wrap_content"
  9.  
    android:layout_height="wrap_content"
  10.  
    android:textSize="20sp"
  11.  
    android:text="234"
  12.  
    />
  13.  
    <Button
  14.  
    android:id="@+id/mBtn"
  15.  
    android:layout_width="wrap_content"
  16.  
    android:layout_height="wrap_content"
  17.  
    android:layout_alignParentRight="true"
  18.  
    />
  19.  
    </RelativeLayout>

先看我们的初始代码:

MainActivity.java

  1.  
    public class MainActivity extends AppCompatActivity {
  2.  
    //ListView控件
  3.  
    private ListView mList;
  4.  
    //ListView数据源
  5.  
    private List<String> data;
  6.  
    @Override
  7.  
    protected void onCreate(Bundle savedInstanceState) {
  8.  
    super.onCreate(savedInstanceState);
  9.  
    setContentView(R.layout.activity_main);
  10.  
    data = new ArrayList<>();
  11.  
    mList = (ListView)findViewById(R.id.mList);
  12.  
    for(int i = 0; i < 20; i ++){
  13.  
    data.add("今天好手气" + i);
  14.  
    }
  15.  
    MyAdapter adapter = new MyAdapter(data);
  16.  
    mList.setAdapter(adapter);
  17.  
    //ListView item点击事件
  18.  
    mList.setOnItemClickListener(new ListView.OnItemClickListener(){
  19.  
     
  20.  
    @Override
  21.  
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
  22.  
    Toast.makeText(MainActivity.this,"我是item点击事件 i = " + i + "l = " + l,Toast.LENGTH_SHORT).show();
  23.  
    }
  24.  
    });
  25.  
    }
  26.  
    }

MyAdapter.java

  1.  
    public class MyAdapter extends BaseAdapter implements View.OnClickListener {
  2.  
    //上下文
  3.  
    private Context context;
  4.  
    //数据项
  5.  
    private List<String> data;
  6.  
    public MyAdapter(List<String> data){
  7.  
    this.data = data;
  8.  
    }
  9.  
    @Override
  10.  
    public int getCount() {
  11.  
    return data == null ? 0 : data.size();
  12.  
    }
  13.  
     
  14.  
    @Override
  15.  
    public Object getItem(int i) {
  16.  
    return data.get(i);
  17.  
    }
  18.  
     
  19.  
    @Override
  20.  
    public long getItemId(int i) {
  21.  
    return i;
  22.  
    }
  23.  
     
  24.  
    @Override
  25.  
    public View getView(int i, View view, ViewGroup viewGroup) {
  26.  
    ViewHolder viewHolder = null;
  27.  
    if(context == null)
  28.  
    context = viewGroup.getContext();
  29.  
    if(view == null){
  30.  
    view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item,null);
  31.  
    viewHolder = new ViewHolder();
  32.  
    viewHolder.mTv = (TextView)view.findViewById(R.id.mTv);
  33.  
    viewHolder.mBtn = (Button)view.findViewById(R.id.mBtn);
  34.  
    view.setTag(viewHolder);
  35.  
    }
  36.  
    //获取viewHolder实例
  37.  
    viewHolder = (ViewHolder)view.getTag();
  38.  
    //设置数据
  39.  
    viewHolder.mTv.setText(data.get(i));
  40.  
    //设置监听事件
  41.  
    viewHolder.mTv.setOnClickListener(this);
  42.  
    //设置数据
  43.  
    viewHolder.mBtn.setText("点我点我"+ i);
  44.  
    viewHolder.mBtn.setOnClickListener(this);
  45.  
    return view;
  46.  
    }
  47.  
     
  48.  
    @Override
  49.  
    public void onClick(View view) {
  50.  
    switch (view.getId()){
  51.  
    case R.id.mBtn:
  52.  
    Log.d("tag", "Btn_onClick: " + "view = " + view);
  53.  
    Toast.makeText(context,"我是按钮",Toast.LENGTH_SHORT).show();
  54.  
    break;
  55.  
    case R.id.mTv:
  56.  
    Log.d("tag", "Tv_onClick: " + "view = " + view);
  57.  
    Toast.makeText(context,"我是文本",Toast.LENGTH_SHORT).show();
  58.  
    break;
  59.  
    }
  60.  
    }
  61.  
     
  62.  
    static class ViewHolder{
  63.  
    TextView mTv;
  64.  
    Button mBtn;
  65.  
    }
  66.  
     
  67.  
    }

通过上图我们可以看到,当鼠标第一次停留的地方,我点击item项时,没有任何反应,当点击按钮和文本的时候就会弹出吐司,那么为什么点击item会没有触发事件呢?怎样才能让item也有触发事件呢?

因为一个item布局中有按钮控件的话,按钮会获得焦点,而此时item就获取不到焦点,所以点击Item时不能触发其点击事件,如果想让item也有点击事件的话,则设置Button的焦点默认为false,则我们只需要在list_item.xml中的Button控件中加入android:focusable="false"这样item就有了焦点,可以点击了

如下是改变焦点后的运行效果: 

但是随之又有一个问题了,我们如何判断我们点击的是哪个item中的TextView和Button呢,因为目前的点击时间只能判断是TextView点击了,还是Button,或者item被点击了,除了item能知道是哪一项被点击了,其他两个却不知道是在哪个item中被点击了,所以我们需要将代码进行在此修改。只需要在MyAdapter中修改代码即可。基本思路是,我们可以将每个被点击的控件中设置一个标记,通过View中的setTag(int key, Object tag)方法设置即可,第一个key必须是一个资源id

资源id的添加 

ids.xml

  1.  
    <?xml version="1.0" encoding="utf-8"?>
  2.  
    <resources>
  3.  
    <item name="btn" type="id"></item>
  4.  
    <item name="tv" type="id"></item>
  5.  
    </resources>

MyAdapter.java

  1.  
    public class MyAdapter extends BaseAdapter implements View.OnClickListener {
  2.  
    private Context context;
  3.  
    private List<String> data;
  4.  
    public MyAdapter(List<String> data){
  5.  
    this.data = data;
  6.  
    }
  7.  
    @Override
  8.  
    public int getCount() {
  9.  
    return data == null ? 0 : data.size();
  10.  
    }
  11.  
    @Override
  12.  
    public Object getItem(int i) {
  13.  
    return data.get(i);
  14.  
    }
  15.  
     
  16.  
    @Override
  17.  
    public long getItemId(int i) {
  18.  
    return i;
  19.  
    }
  20.  
     
  21.  
    @Override
  22.  
    public View getView(int i, View view, ViewGroup viewGroup) {
  23.  
    ViewHolder viewHolder = null;
  24.  
    if(context == null)
  25.  
    context = viewGroup.getContext();
  26.  
    if(view == null){
  27.  
    view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item,null);
  28.  
    viewHolder = new ViewHolder();
  29.  
    viewHolder.mTv = (TextView)view.findViewById(R.id.mTv);
  30.  
    viewHolder.mBtn = (Button)view.findViewById(R.id.mBtn);
  31.  
    view.setTag(viewHolder);
  32.  
    }
  33.  
    viewHolder = (ViewHolder)view.getTag();
  34.  
    //设置tag标记
  35.  
    viewHolder.mBtn.setTag(R.id.btn,i);//添加此代码
  36.  
    viewHolder.mBtn.setText("点我点我"+ i);
  37.  
    viewHolder.mBtn.setOnClickListener(this);
  38.  
    viewHolder.mTv.setText(data.get(i));
  39.  
    //设置tag标记
  40.  
    viewHolder.mTv.setTag(R.id.tv,i);//添加此代码
  41.  
    viewHolder.mTv.setOnClickListener(this);
  42.  
    return view;
  43.  
    }
  44.  
    @Override
  45.  
    public void onClick(View view) {
  46.  
    switch (view.getId()){
  47.  
    case R.id.mBtn:
  48.  
    int b = (int) view.getTag(R.id.btn);
  49.  
    Toast.makeText(context,"我是按钮 " + b,Toast.LENGTH_SHORT).show();
  50.  
    break;
  51.  
    case R.id.mTv:
  52.  
    int t = (int)view.getTag(R.id.tv);
  53.  
    Toast.makeText(context,"我是文本" + t,Toast.LENGTH_SHORT).show();
  54.  
    break;
  55.  
    }
  56.  
    }
  57.  
    static class ViewHolder{
  58.  
    TextView mTv;
  59.  
    Button mBtn;
  60.  
    }
  61.  
    }

基本已经实现了,案例比较简单,适合初学者。

如果你是用ImageView,还是会出现item点击无效,接着看下面:

Android开发中在ListView中经常有Item的点击事件及Button或ImageButton等需要被点击的事件之间的处理方法

解决的办法,在ListView的Item的xml文件中添加如下属性:

1)整个xml文件的根元素如LinearLayout中添加属性android:descendantFocusability="blocksDescendants"

2)被点击的控件如ImageButton中添加属性android:focusable="false"和android:clickable="true"

android:descendantFocusability=””方法解析:

开发中很常见的一个问题,项目中的listview不仅仅是简单的文字,常常需要自己定义listview,自己的Adapter去继承BaseAdapter,在adapter中按照需求进行编写,问题就出现了,可能会发生点击每一个item的时候没有反应,无法获取的焦点。原因多半是由于在你自己定义的Item中存在诸如ImageButton,Button,CheckBox等子控件(也可以说是Button或者Checkable的子类控件),此时这些子控件会将焦点获取到,所以常常当点击item时变化的是子控件,item本身的点击没有响应。

这时候就可以使用descendantFocusability来解决啦,API描述如下:

android:descendantFocusability

Defines the relationship between the ViewGroup and its descendants when looking for a View to take focus.

Must be one of the following constant values.

该属性是当一个为view获取焦点时,定义viewGroup和其子控件两者之间的关系。

属性的值有三种:

beforeDescendants:viewgroup会优先其子类控件而获取到焦点

afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点

blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点

通常我们用到的是第三种,即在Item布局的根布局加上android:descendantFocusability=”blocksDescendants”的属性就好了,至此listview点击的灵异事件告一段落。心得:遇到不会不懂的地方除了网上查询资料之外,也可以多多去尝试每种属性的作用,多阅读官方文档(我始终觉得还是读原文的比翻译的理解的会更好)。

ListView中嵌入布局的Button或多个点击事件的更多相关文章

  1. 解决ListView中Item的子控件与Item点击事件冲突

    常常会碰到在ListView中点击当中一个Item.会一并触发其子控件的点击事件.比如Item中的Button.ImageButton等.导致了点击Item中Button以外区域也会触发Button点 ...

  2. android ListView中的Item有Button时候点击异常处理

    1.当ListView中有Button的时候往往会遇到很多问题,比较常见的一个问题是: 假设:在ListView中有N个Item当点击其中某个Item中的Button的时候,需要改变当前Button的 ...

  3. 【转】Android - Button(按钮)的响应点击事件的4种写法

    原文网址:http://www.yrom.net/blog/2011/12/12/android-4-onclicklistener-of-button/ Button控件setOnclickList ...

  4. 注意:MainActivity的oncreate方法里不要再inflate布局了(MainActivity里的点击事件无响应)

    activity_main已经通过setContentView(R.layout.activity_main);设置给MainActivity, 不要再inflate出新布局,然后findviewby ...

  5. Android - Button(按钮)的响应点击事件的4种写法

    Button控件setOnclickListener(View.OnClickListener listener)来接收一个点击事件的监听器 自定义一个点击事件监听器类让其实现View.OnClick ...

  6. Button控件的点击事件

    Java的代码 主要重点: findViewById(); OnClickListener() package com.example.admin.myapplication; import andr ...

  7. js中嵌入jsp(html)代码的双引号转换问题--事件没反应

    下面是一段今天遇到问题的代码,select中写了onchange事件 ,在没有加转义的情况下,F12解析的代码是错乱的,双引号与内容中写的不一致,还会有空格出现,经过一段时间的摸索,发现在出错的地方加 ...

  8. ListView item中有button或EditText时 点击事件失效问题的解决

    加入:android:descendantFocusability="blocksDescendants" 代码如下: <LinearLayout xmlns:android ...

  9. ListView中多个EditText设置焦点 多次点击异常报错

    08-17 18:23:09.825: ERROR/AndroidRuntime(1608): FATAL EXCEPTION: main 08-17 18:23:09.825: ERROR/Andr ...

随机推荐

  1. .net core jenkins持续集成

    执行 Shell pwd ls echo ${PATH} whoami which dotnet dotnet --info dotnet --version echo '============== ...

  2. 树莓派安装系统+ssh登录

    一.准备工作: (1)树莓派3b (2)官网下载系统 (3)SD卡 (4)网线 (5)SDFormatter.exe (6)win32diskimager.exe (7)putty (7)笔记本 二. ...

  3. static 关键字在java语言中的特性

    ​ 一,将自己注入到一个静态变量中实现静态类,如下写法 以上方法的目的是要实现一个静态类,方便用类名获取对象实例,一般情况下调用普通方法需要对象实例.这对象要么new出来,要么spring的注入如下是 ...

  4. Parity game(带权并查集+离散化)

    题目链接  //kuangbin 题意: 现在你和你的朋友正在玩一种游戏. 你的朋友写下一串0和1的序列,然后你选择其中一串子序列(如[3,5])并且问他这个序列是包含奇数个1还是偶数个1(和是奇数还 ...

  5. Java.io.tmpdir介绍

    System.getproperty(“java.io.tmpdir”)是获取操作系统缓存的临时目录,不同操作系统的缓存临时目录不一样, 在Windows的缓存目录为:C:\Users\登录用户~1\ ...

  6. re正则match、search、findall、finditer函数方法使用

    match 匹配string 开头,成功返回Match object, 失败返回None,只匹配一个. search 在string中进行搜索,成功返回Match object, 失败返回None, ...

  7. 项目Alpha冲刺(团队) -- 测试

    项目Alpha冲刺(团队) --测试 1.团队信息 团队名 :男上加男 成员信息 : 队员学号 队员姓名 个人博客地址 备注 221600427 Alicesft https://www.cnblog ...

  8. 关于mysql数据库utf-8问题

    1.bug的出现 我们正常使用utf-8类型来给我们的字段的字符编码,对于正常的都没有问题,例如姓名呀,性别年龄等,但是会遇到一个问题就是如果存储表情emoji则无法存入utf-8编码的字段 2.my ...

  9. 使用Apache commons-maths3-3.6.1.jar包实现快速傅里叶变换(java)

    本例应用的是快速傅里叶变换 (fast Fourier transform),即利用计算机计算离散傅里叶变换(DFT)的高效.快速计算方法的统称,简称FFT.快速傅里叶变换是1965年由J.W.库利和 ...

  10. Generator 函数和for...of循环,实现斐波那契数列

    function* fib () { let [prev, cur] = [0,1] for (;;) { yield cur [prev, cur] = [cur, cur+prev] } } fo ...