ListView配合BaseAdapter

  BaseAdapter使用比较麻烦,它是个抽象类,需要重写4个方法分别是getCount() getItem(..) getItemId(..) getVew(..),相应的使用BaseAdapter

可以自由的定义自己想要的布局,先看看程序效果图:

这个布局一共有5个元素分别是:ImageViw 2个TextView CheckBox Button

先看这个ListView的Item布局文件list_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_gravity="center_horizontal"
    android:layout_width="match_parent"
    android:layout_height="50dp">
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:src="@drawable/ic_launcher"
        android:id="@+id/iv_image"/>
    <!-- 注意这个里两个TextView的布局是垂注布局的-->
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:layout_weight="4">
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textSize="25dp"
            android:text="hah"
            android:id="@+id/tv_item"/>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="content"
            android:id="@+id/tv_content"/>
    </LinearLayout>

    <CheckBox
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:id="@+id/ck_box"
        />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:textSize="20sp"
        android:text="Select"
        android:id="@+id/btn_select"
        android:background="@drawable/btn_selector"/>
</LinearLayout>
View Code

整理一下我们要做的事情:1、首先在主布局里要放一个ListView;
            2、准备ListView显示需要的数据;

                                 3、重写适配器,将布局文件与数据放到ListView中显示,这一部分最复杂,还有布局文件中还有点击事件需要设置。

下面是主程序代码:

package com.skymaster.hs.baseadaptertest;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.HashMap;

public class MainActivity extends AppCompatActivity {
    private ListView listView;
    private HsAdapter hsAdapter;
    private ArrayList<HashMap<String,Object>> listItem;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listView = (ListView) findViewById(R.id.lv_list);
        hsAdapter = new HsAdapter(getLayoutInflater());
        DataInit();
        listView.setAdapter(hsAdapter);
    }
    /*
    * 初始化显示的内容ListView表的数据结构对应的是ArrayList
    * 但是ListView内部每一项Item有细分多个View,所以ArrayList泛型定义为Map
    * 这样就可以定义多中数据类型了,没一个key对应一个View,适配器在填充内容的时候
    * 可以根据key来获取内容,这里要注意一点:HashMap<String,Object> hashMap = new HashMap<>();
    * 一定要放到循环里面,因为ListView有多少个Item就应该有多少个数据对象也就是说有多少new出来得对象实例
    * */
    private void DataInit(){
        listItem = new ArrayList<>();
        for(int i=0;i<10;i++){
            HashMap<String,Object> hashMap = new HashMap<>();
            hashMap.put("title","title:"+i);
            hashMap.put("content","content:"+i);
            hashMap.put("image",image_index[i]);
            listItem.add(hashMap);
        }
    }
    /*
    * 这里定义ImageView的数组索引,适配器在设置ImageView背景的时候使用比较方便
    * */
    private final int[] image_index = {
            R.drawable.ic_launcher,
            R.drawable.image1,
            R.drawable.image2,
            R.drawable.image3,
            R.drawable.image4,
            R.drawable.image5,
            R.drawable.image6,
            R.drawable.image7,
            R.drawable.image8,
            R.drawable.image9,
    };
    /*
    * convertView配合ViewHolder可以提高UI加载的效率,这里定义成static型
    * 相当于全局保存布局文件中的View对象实例。
    * */
    static class ViewHolder{
        TextView tv_item;
        TextView tv_content;
        ImageView iv_image;
        Button btn_select;
        CheckBox ck_box;
    }

    private class HsAdapter extends BaseAdapter{
        /*
         * 这里需要解释一下LayoutInflater的用法:/**
         * Instantiates a layout XML file into its corresponding {@link android.view.View}
         * objects. It is never used directly. Instead, use
         * {@link android.app.Activity#getLayoutInflater()} or
         * {@link Context#getSystemService} to retrieve a standard LayoutInflater instance
         * that is already hooked up to the current context and correctly configured
         * for the device you are running on.
         * 以上是源码的注释
         * 首先这个是一个抽象对象,所以从来不会直接实例化来引用,而且它也没有任何的子类。
         * 所以要使用这个类,唯一的办法就是:1、从Activity.getLayoutInflater()中获得
         *                               2、从上下文Context.getSystemService找回当前上下文连接的
         *                                LayoutInflater实例。
         *  eg:LayoutInflater inflater = (LayoutInflater)context.getSystemService
         *      (Context.LAYOUT_INFLATER_SERVICE)
         * 因此我们设置适配器构造函数的时候传入了Activity的布局解析器
         * */
        private LayoutInflater mInflator;
        private ViewHolder viewHolder;
        public HsAdapter(LayoutInflater mInflator){
            this.mInflator = mInflator;
        }
        @Override
        public int getCount() {
            return listItem.size();
        }

        @Override
        public Object getItem(int position) {
            System.out.println("getItem");
            return null;
        }

        @Override
        public long getItemId(int position) {
            System.out.println("getItemId:"+position);
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if(convertView == null){
                /*
                * 1.这段代码执行的次数与ListView的项数有关系,如果手机屏幕最大显示数目是6个,那么执行的次数
                * 就是7次,最后会保留一个convertView实例在viewHolder中,并且保存在convertView的Tag中,
                * 这样做的目的是当ListView滑动,显示变化需要加载新的Item的时候可以不用再执行这一段代码
                * 直接用tag中保存的引用来填充Item,提高效率。这就是setTag()的目的。
                * 2.注意viewHolder = new ViewHolder();与convertView = mInflator.inflate(R.layout.list_item, null);
                * 是对应的,不然会引起空指针错误。
                * 3.一段代码加载的原理就是:在ListView初始化的时候每加载一项Item都会执行一次getView,并且这个时候
                * convertView都是空,如果反过来理解其实每一项viewHolder的引用都必须通过findViewById来指向一个实例,不然就会报错。
                * 当屏幕最大显示的6项加载完毕,在多保留一个viewHolder引用备用就不会执行了。这个时候如果滑动ListView
                * 需要加载新的Item,这个时候又会调用getView,而这个时候会直接用预留的一个convertView。如果继续滑动,
                * 这个时候convertView并不为空,这是因为滑动的过程中除了会出现新的Item,旧的Item会移出屏幕不在显示,这个时候
                * convertView其实装载的是旧的引用,如此循环,因此可以判断如果手机整个屏幕ListView最大显示的
                * item的数据是n那么convertView的引用数据就是n+1了
                * */
                viewHolder = new ViewHolder();
                convertView = mInflator.inflate(R.layout.list_item, null);
                viewHolder.tv_item = (TextView)convertView.findViewById(R.id.tv_item);
                viewHolder.iv_image = (ImageView)convertView.findViewById(R.id.iv_image);
                viewHolder.tv_content = (TextView)convertView.findViewById(R.id.tv_content);
                viewHolder.btn_select = (Button)convertView.findViewById(R.id.btn_select);
                viewHolder.ck_box = (CheckBox)convertView.findViewById(R.id.ck_box);

                viewHolder.btn_select.setTag(position);//设置按键的 Tag辅助判断是哪一个按键按下,因为这里所有项的按键实体id只有一个所有需要
                                                       //position来辅助判断
                viewHolder.btn_select.setOnClickListener(new KeyPressService());//设置按键监听一定要放在里面,因为getView调用的次数非常多
                                                                                //而我们只需要对有效Item的按键设置监听。
                viewHolder.ck_box.setTag(position);//同理按键
                viewHolder.ck_box.setOnClickListener(new KeyPressService());//同理按键

                convertView.setTag(viewHolder);//保存引用
            }else{
                viewHolder = (ViewHolder)convertView.getTag();
                viewHolder.btn_select.setTag(position);
                viewHolder.btn_select.setOnClickListener(new KeyPressService());
                viewHolder.ck_box.setOnClickListener(new KeyPressService());
                viewHolder.ck_box.setTag(position);
            }
            /*
             * 这里就是适配器绑定数据源与View的过程。利用Map的数据结构可以方便找到
             * 因为是HashMap<String,Object>返回的value是object所以要强转
             * */
            viewHolder.iv_image.setBackgroundResource((Integer) listItem.get(position).get("image"));
            viewHolder.tv_item.setText((String) listItem.get(position).get("title"));
            viewHolder.tv_content.setText((String) listItem.get(position).get("content"));

            return convertView;
        }
    }

    private class KeyPressService implements View.OnClickListener{
        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.btn_select:
                    ClickEventProcess(v,"Button");
                    break;
                case R.id.ck_box:
                    ClickEventProcess(v,"checkbox");
                    break;
            }

        }
        private void ClickEventProcess(View v,String str){

            switch ((Integer)v.getTag()){
                case 0:
                    Toast.makeText(MainActivity.this,"click:0"+str,Toast.LENGTH_SHORT)
                            .show();
                    break;
                case 1:
                    Toast.makeText(MainActivity.this,"click:1"+str,Toast.LENGTH_SHORT)
                            .show();
                    break;
                case 2:
                    Toast.makeText(MainActivity.this,"click:2"+str,Toast.LENGTH_SHORT)
                            .show();
                    break;
                case 3:
                    Toast.makeText(MainActivity.this,"click:3"+str,Toast.LENGTH_SHORT)
                            .show();
                    break;
                case 4:
                    Toast.makeText(MainActivity.this,"click:4"+str,Toast.LENGTH_SHORT)
                            .show();
                    break;
                case 5:
                    Toast.makeText(MainActivity.this,"click:5"+str,Toast.LENGTH_SHORT)
                            .show();
                    break;
                case 6:
                    Toast.makeText(MainActivity.this,"click:6"+str,Toast.LENGTH_SHORT)
                            .show();
                    break;
                case 7:
                    Toast.makeText(MainActivity.this,"click:7"+str,Toast.LENGTH_SHORT)
                            .show();
                    break;
                case 8:
                    Toast.makeText(MainActivity.this,"click:8"+str,Toast.LENGTH_SHORT)
                            .show();
                    break;
                case 9:
                    Toast.makeText(MainActivity.this,"click:9"+str,Toast.LENGTH_SHORT)
                            .show();
                    break;
            }
        }
    }
}
View Code

下面是程序执行的效果:

主界面的布局activity_main.xml:

<?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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.skymaster.hs.baseadaptertest.MainActivity">

    <ListView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/lv_list"/>
</RelativeLayout>

按键的drawable文件btn_normal.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="45dp"/>
    <size android:height="10dp"
        android:width="30dp"/>
    <solid android:color="@color/colorPrimary"/>
</shape>

btn_press.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="45dp"/>
    <size android:height="10dp"
        android:width="30dp"/>
    <solid android:color="@color/colorPrimary"/>
    <stroke android:color="#ff0000"
        android:width="10dp"/>
</shape>

btn_selector.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/btn_press"/>
    <item android:state_pressed="false" android:drawable="@drawable/btn_normal"/>
</selector>

 

转载于:https://www.cnblogs.com/ashitaka/p/5893311.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值