ListView中嵌入布局的Button或多个点击事件
有时候在ListView嵌入的布局中有多个事件需要点击,比如一个item中有TextView和Button两个布局,当我们需要获取这两个点击事件时,我们应该如何去获取呢,通常来说,我们都是已经固定好了TextView和Button的id的,,所以,这两个点击事件的id肯定是不会变的,假如我们有10个item,我们需要获取第5个item中的布局的button和TextView的点击事件该如何获取呢?下面将依依介绍。(适合初学者)
首先先看初次布局界面:
activity_main.xml布局:ListView的布局
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context="com.qianfeng.listviewbutton.MainActivity">
- <ListView
- android:id="@+id/mList"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- </ListView>
- </RelativeLayout>
list_item.xml布局:ListView item的每个布局
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal" android:layout_width="match_parent"
- android:layout_height="match_parent">
- <TextView
- android:id="@+id/mTv"
- android:layout_marginTop="10dp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="20sp"
- android:text="234"
- />
- <Button
- android:id="@+id/mBtn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- />
- </RelativeLayout>
先看我们的初始代码:
MainActivity.java
- public class MainActivity extends AppCompatActivity {
- //ListView控件
- private ListView mList;
- //ListView数据源
- private List<String> data;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- data = new ArrayList<>();
- mList = (ListView)findViewById(R.id.mList);
- for(int i = 0; i < 20; i ++){
- data.add("今天好手气" + i);
- }
- MyAdapter adapter = new MyAdapter(data);
- mList.setAdapter(adapter);
- //ListView item点击事件
- mList.setOnItemClickListener(new ListView.OnItemClickListener(){
- @Override
- public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
- Toast.makeText(MainActivity.this,"我是item点击事件 i = " + i + "l = " + l,Toast.LENGTH_SHORT).show();
- }
- });
- }
- }
MyAdapter.java
- public class MyAdapter extends BaseAdapter implements View.OnClickListener {
- //上下文
- private Context context;
- //数据项
- private List<String> data;
- public MyAdapter(List<String> data){
- this.data = data;
- }
- @Override
- public int getCount() {
- return data == null ? 0 : data.size();
- }
- @Override
- public Object getItem(int i) {
- return data.get(i);
- }
- @Override
- public long getItemId(int i) {
- return i;
- }
- @Override
- public View getView(int i, View view, ViewGroup viewGroup) {
- ViewHolder viewHolder = null;
- if(context == null)
- context = viewGroup.getContext();
- if(view == null){
- view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item,null);
- viewHolder = new ViewHolder();
- viewHolder.mTv = (TextView)view.findViewById(R.id.mTv);
- viewHolder.mBtn = (Button)view.findViewById(R.id.mBtn);
- view.setTag(viewHolder);
- }
- //获取viewHolder实例
- viewHolder = (ViewHolder)view.getTag();
- //设置数据
- viewHolder.mTv.setText(data.get(i));
- //设置监听事件
- viewHolder.mTv.setOnClickListener(this);
- //设置数据
- viewHolder.mBtn.setText("点我点我"+ i);
- viewHolder.mBtn.setOnClickListener(this);
- return view;
- }
- @Override
- public void onClick(View view) {
- switch (view.getId()){
- case R.id.mBtn:
- Log.d("tag", "Btn_onClick: " + "view = " + view);
- Toast.makeText(context,"我是按钮",Toast.LENGTH_SHORT).show();
- break;
- case R.id.mTv:
- Log.d("tag", "Tv_onClick: " + "view = " + view);
- Toast.makeText(context,"我是文本",Toast.LENGTH_SHORT).show();
- break;
- }
- }
- static class ViewHolder{
- TextView mTv;
- Button mBtn;
- }
- }
通过上图我们可以看到,当鼠标第一次停留的地方,我点击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
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <item name="btn" type="id"></item>
- <item name="tv" type="id"></item>
- </resources>
MyAdapter.java
- public class MyAdapter extends BaseAdapter implements View.OnClickListener {
- private Context context;
- private List<String> data;
- public MyAdapter(List<String> data){
- this.data = data;
- }
- @Override
- public int getCount() {
- return data == null ? 0 : data.size();
- }
- @Override
- public Object getItem(int i) {
- return data.get(i);
- }
- @Override
- public long getItemId(int i) {
- return i;
- }
- @Override
- public View getView(int i, View view, ViewGroup viewGroup) {
- ViewHolder viewHolder = null;
- if(context == null)
- context = viewGroup.getContext();
- if(view == null){
- view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item,null);
- viewHolder = new ViewHolder();
- viewHolder.mTv = (TextView)view.findViewById(R.id.mTv);
- viewHolder.mBtn = (Button)view.findViewById(R.id.mBtn);
- view.setTag(viewHolder);
- }
- viewHolder = (ViewHolder)view.getTag();
- //设置tag标记
- viewHolder.mBtn.setTag(R.id.btn,i);//添加此代码
- viewHolder.mBtn.setText("点我点我"+ i);
- viewHolder.mBtn.setOnClickListener(this);
- viewHolder.mTv.setText(data.get(i));
- //设置tag标记
- viewHolder.mTv.setTag(R.id.tv,i);//添加此代码
- viewHolder.mTv.setOnClickListener(this);
- return view;
- }
- @Override
- public void onClick(View view) {
- switch (view.getId()){
- case R.id.mBtn:
- int b = (int) view.getTag(R.id.btn);
- Toast.makeText(context,"我是按钮 " + b,Toast.LENGTH_SHORT).show();
- break;
- case R.id.mTv:
- int t = (int)view.getTag(R.id.tv);
- Toast.makeText(context,"我是文本" + t,Toast.LENGTH_SHORT).show();
- break;
- }
- }
- static class ViewHolder{
- TextView mTv;
- Button mBtn;
- }
- }
基本已经实现了,案例比较简单,适合初学者。
如果你是用ImageView,还是会出现item点击无效,接着看下面:
Android开发中在ListView中经常有Item的点击事件及Button或ImageButton等需要被点击的事件之间的处理方法
解决的办法,在ListView的Item的xml文件中添加如下属性:
1)整个xml文件的根元素如LinearLayout中添加属性android:descendantFocusability="blocksDescendants"
2)被点击的控件如ImageButton中添加属性android:focusable="false"和android:clickable="true"
开发中很常见的一个问题,项目中的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或多个点击事件的更多相关文章
- 解决ListView中Item的子控件与Item点击事件冲突
常常会碰到在ListView中点击当中一个Item.会一并触发其子控件的点击事件.比如Item中的Button.ImageButton等.导致了点击Item中Button以外区域也会触发Button点 ...
- android ListView中的Item有Button时候点击异常处理
1.当ListView中有Button的时候往往会遇到很多问题,比较常见的一个问题是: 假设:在ListView中有N个Item当点击其中某个Item中的Button的时候,需要改变当前Button的 ...
- 【转】Android - Button(按钮)的响应点击事件的4种写法
原文网址:http://www.yrom.net/blog/2011/12/12/android-4-onclicklistener-of-button/ Button控件setOnclickList ...
- 注意:MainActivity的oncreate方法里不要再inflate布局了(MainActivity里的点击事件无响应)
activity_main已经通过setContentView(R.layout.activity_main);设置给MainActivity, 不要再inflate出新布局,然后findviewby ...
- Android - Button(按钮)的响应点击事件的4种写法
Button控件setOnclickListener(View.OnClickListener listener)来接收一个点击事件的监听器 自定义一个点击事件监听器类让其实现View.OnClick ...
- Button控件的点击事件
Java的代码 主要重点: findViewById(); OnClickListener() package com.example.admin.myapplication; import andr ...
- js中嵌入jsp(html)代码的双引号转换问题--事件没反应
下面是一段今天遇到问题的代码,select中写了onchange事件 ,在没有加转义的情况下,F12解析的代码是错乱的,双引号与内容中写的不一致,还会有空格出现,经过一段时间的摸索,发现在出错的地方加 ...
- ListView item中有button或EditText时 点击事件失效问题的解决
加入:android:descendantFocusability="blocksDescendants" 代码如下: <LinearLayout xmlns:android ...
- ListView中多个EditText设置焦点 多次点击异常报错
08-17 18:23:09.825: ERROR/AndroidRuntime(1608): FATAL EXCEPTION: main 08-17 18:23:09.825: ERROR/Andr ...
随机推荐
- 如何传递大文件(GB级别)
一.拆分:压缩工具,压缩并拆分为多个小文件. 二.QQ离线传输 QQ离线文件有限制条件: 1.离线传送的文件,为用户保存7天,逾期接收方不接收文件,系统将自动删除该文件: 2. 离线传送的文件,单个文 ...
- day 10 预科
目录 IPO 编程 面向对象编程 类和对象 对象 类 定义类 定义对象 定义类语法 定义对象 (实例化对象) 定制对象独有特征 LeetCode检测机制 面向过程编程:面向(对着)-->过程(流 ...
- Android开发之常用Intent.Action【转】
1.从google搜索内容 Intent intent = new Intent(); intent.setAction(Intent.ACTION_WEB_SEARCH); intent.putEx ...
- JMeter性能测试,入门
原文转自:https://blog.csdn.net/lovesoo/article/details/78579547 Apache JMeter是一款纯java编写负载功能测试和性能测试开源工具软件 ...
- HDU1395 2^x mod n = 1——积与余数的性质
对于数论的学习比较的碎片化,所以开了一篇随笔来记录一下学习中遇到的一些坑,主要通过题目来讲解 本题围绕:积与余数 HDU1395 2^x mod n = 1 题目描述 输入一个数n,如果存在2的x次方 ...
- docker学习1-CentOS 7安装docker环境
前言 Docker 提供轻量的虚拟化,你能够从Docker获得一个额外抽象层,你能够在单台机器上运行多个Docker微容器,而每个微容器里都有一个微服务或独立应用,例如你可以将Tomcat运行在一个D ...
- Linux CentOS7.x安装docker全过程
1.在安装docker之前,首先使用yum -y remove docker命令移除系统中已有的旧版本的docker yum -y remove docker 这里显示该系统没有安装过docker: ...
- volatile原理
内存可见性 内存可见性相关概念:线程对共享变量修改的可见性.当一个线程修改了共享变量的值,其他线程能够立刻得知这个修改. 后面会继续总结一篇<Java内存模型(JMM)总结>以详细描述内存 ...
- Sql语句中Like嵌套用法
一般的Like用法: SELECT U_NAME FROM T_USER WHERE U_NAME LIKE '%A%' 但是,我此次like关键字后面的对应值是一个变量,需要用select语句来实现 ...
- hdu1171&&P2000——母函数
hdu1171 题意:有 $n$ 种设施,每种有价值 $v_i$ 和数量 $m_i$,求一种方案使得分成价值尽可能相近的两组.($n \leq 50, v_i \leq 50, m_i \leq 10 ...