zoukankan      html  css  js  c++  java
  • ListView中嵌入布局的Button或多个点击事件

    有时候在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点击的灵异事件告一段落。心得:遇到不会不懂的地方除了网上查询资料之外,也可以多多去尝试每种属性的作用,多阅读官方文档(我始终觉得还是读原文的比翻译的理解的会更好)。

  • 相关阅读:
    ASP.NET 文件下载
    Asp.net 加密解密类
    ASP.Net 获取服务器信息
    Visual Studio 2013 和 ASP.NET 预览
    Windows Server 2012安装时所需要的KEY
    WordPress主题模板层次和常用模板函数
    小meta的大作用
    《淘宝技术这十年》之LAMP架构的网站
    面试题(八)
    面试题(七)
  • 原文地址:https://www.cnblogs.com/Alex80/p/11263253.html
Copyright © 2011-2022 走看看