首页 > 其他分享 >Android之ListView详解

Android之ListView详解

时间:2023-09-12 14:35:02浏览次数:45  
标签:map tv iv 详解 put new Android ListView


前文 ListView作为Android最常用的控件之一,同时也是最难的控件之一,其难点主要在意用法的多变性,因此让众多的初学者都比较难掌握,包括我自己,也是在反复需要使用时,总会卡住.而在网上找了众多的ListView的实例,案例等,讲解得不尽人意,甚至让许多初学者有迷惑.所以才觉得写此文,将包括ListView的用法,具体的注解,详解以及方案,希望能帮到需要的人,若有不正之处还请指正,谢谢

由于ListView有指定的外观形式的,在此就不会使用那些

ListView显示数据的原理 与javaweb相比较:                javaweb                                                Android
                        m:                    mode                                                        mode    数据javabean

                        v:                      view                                                          view    listview

                        c:                     controller servlet                                      adapter


注意事项:使用listview高的时候用了wrap_contant会降低效率,jvm会在后台不停的配置, 所以用listview是要用match_contant


ListView显示复杂的页面
    通过打气筒inflate可以把一个布局转换成一个view对象

获取打气筒常用的api

//第一种
view = View.inflate(MainActivity.this, R.layout.item, null);

//第二种
view=LayoutInflater.from(MainActivity.this).inflate(R.layout.item, null);

//第三种
LayoutInflater inflater= (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.item, null);


ListView之指定列表项(无适配器)

1.定义ListView属性

<!-- ListView支持的常用xml属性 -->
    <!-- android:divider:为listview设置分隔条,可以定颜色,也可以用Drawable资源分割 -->
    <!-- android:dividerHeight:设置分隔条的高度 -->
    <!-- android:entries:用于数组资源为ListView指定列表项 -->
    <!-- android:footerDividersEnabled:用于设置是否在footer View前绘制分隔条,默认为true ,设置为false时表示不绘制,使用该组件时,需要通过ListView组件提供的addFooterView()方法为ListView设置footer View -->
    <!-- android:headerDividersEnabled:用于设置是否在herader View前绘制分隔条,默认为true ,设置为false时表示不绘制,使用该组件时,需要通过ListView组件提供的addHeaderView()方法为ListView设置header View -->

    <ListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:divider="@android:color/background_dark"
        android:dividerHeight="2dp"
        android:entries="@array/ctype"
        android:footerDividersEnabled="false"
        android:headerDividersEnabled="false" >
    </ListView>


2.由于属性中定义了从type的数组资源,所以在res/value目录中创建一个定义的数组资源的xml文件array.xml


<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string-array name="ctype">
        <item>你好</item>
        <item>我是老司机</item>
        <item>你了?</item>
        <item>交个朋友怎么样?</item>
    </string-array>

</resources>


3.运行即可


属性添加了android:footerDividersEnabled="false"     android:headerDividersEnabled="false"


file:///F:/%E7%AC%94%E8%AE%B0/temp/7c3314e7-e831-4e98-9e52-0e671208da4b/4/index_files/829c8791-514e-4d65-b600-8811b486b946.jpg      


属性没有添加android:footerDividersEnabled="false"        android:headerDividersEnabled="false"


file:///F:/%E7%AC%94%E8%AE%B0/temp/7c3314e7-e831-4e98-9e52-0e671208da4b/4/index_files/31ea0d61-f17b-461e-a26e-ba1b9b964793.jpg


     由于没有设置ListView的样式没有设置内边距,所以第一条目看不出是否有分隔条




ListView之ArrayAdapter

1,定义ListView属性(省略了咯)



2,在layout文件夹创建xml文件item来展示单个条目样式(可以有更多的样式设计)


3,定义需要展示的数组(注意是数组)

<TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@android:color/background_dark"
        android:textSize="20sp" />


注意选择适配器构造方法有多种,根据需求来选择,这里只给出一中来,原则就是要什么给什么

public class MainActivity extends Activity {
        private static String[] data = { "apple", "orange", "watermelon", "banana",
                        "pear", "cherry", "strawberry", "grape" };
        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                ListView lv = (ListView) findViewById(R.id.lv);

                // CharSequence与String都能用于定义字符串,但CharSequence的值是可读可写序列,而String的值是只读序列
                ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(
                                getApplicationContext(), //上下文,也可以是this和MainActivity.this
                                R.layout.item, //注意是int类型,需要展示的容器
                                R.id.tv, //注意是int类型,需要展示的具体控件
                                data//需要展示的数据
                                );
                lv.setAdapter(adapter);
        }




使用ArrayAdapter实现图文结合(此方法也适合单独的数组,条列更清晰)

通过创建list集合对象和map键值对来存储一组数据


1.创建一个Fruit类,实现其中的getter()与setter()和构造函数

public class Fruit {
        private String name;
        private int imageId;

        public String getName() {
                return name;
        }

        public void setName(String name) {
                this.name = name;
        }

        public int getImageId() {
                return imageId;
        }

        public void setImageId(int imageId) {
                this.imageId = imageId;
        }

        public Fruit(String name, int imageId) {
                super();
                this.name = name;
                this.imageId = imageId;
        }

}

2,在layout文件夹创建xml文件item来展示单个条目样式(可以有更多的样式设计)


<ImageView
        android:id="@+id/iv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@android:color/background_dark"
        android:textSize="20sp" />



3,创建一个自定义的适配器并继承ArrayAdapter,泛型指定为Fruit

public class myAdapter extends ArrayAdapter<Fruit> {
        private int resourceId;
        public myAdapter(Context context, int textViewResourceId,
                        List<Fruit> objects) {
                super(context, textViewResourceId, objects);
                resourceId = textViewResourceId;
        }
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
                Fruit fruit = getItem(position);
                View view=LayoutInflater.from(getContext()).inflate(resourceId, null);
               
                ImageView iv=(ImageView) view.findViewById(R.id.iv);
                TextView tv = (TextView) view.findViewById(R.id.tv);
                iv.setImageResource(fruit.getImageId());
                tv.setText(fruit.getName());
                return view;
        }
}



4.创建集合,初始化数据并实现

public class MainActivity extends Activity {
        //创建一个集合,存储数据
        private List<Fruit> fruitList = new ArrayList<Fruit>();

        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                //需要展示的数据初始化
                initFruit();
                //通过适配器,用创建好的条目样式文件展示对应存储的数据(形成一个条目展示一组数据)
                myAdapter adapter = new myAdapter(MainActivity.this, R.layout.item,
                                fruitList);
                ListView lv = (ListView) findViewById(R.id.lv);
                lv.setAdapter(adapter);
        }

        private void initFruit() {
                Fruit apple = new Fruit("apple", R.drawable.i1);
                fruitList.add(apple);
                Fruit orange = new Fruit("orange", R.drawable.i2);
                fruitList.add(orange);
                Fruit watermelon = new Fruit("watermelon", R.drawable.i3);
                fruitList.add(watermelon);
                Fruit banana = new Fruit("banana", R.drawable.i4);
                fruitList.add(banana);
                Fruit pear = new Fruit("pear", R.drawable.i5);
                fruitList.add(pear);
                Fruit cherry = new Fruit("cherry", R.drawable.i6);
                fruitList.add(cherry);
                Fruit strawberry = new Fruit("strawberry", R.drawable.i7);
                fruitList.add(strawberry);
                Fruit grape = new Fruit("grape", R.drawable.i8);
                fruitList.add(grape);
        }


5.运行结果


file:///F:/%E7%AC%94%E8%AE%B0/temp/7c3314e7-e831-4e98-9e52-0e671208da4b/4/index_files/2194fcea-c757-4cdc-bf51-e43fc290d368.jpg





ListView之SimpleAdapter1,可以将MainActivity继承ListActivity,然后setListAdapter(adapter)实现适配器

2,定义listview与item的xml样式文件(上面有就省略了)

运行结果:

public class MainActivity extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                SimpleAdapter adapter = new SimpleAdapter(this, getData(),
                                R.layout.item, new String[] { "iv", "tv",  },
                                new int[] { R.id.iv, R.id.tv });
                ListView lv = (ListView) findViewById(R.id.lv);
                lv.setAdapter(adapter);
        }
        private List<Map<String, Object>> getData() {
                List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();

                Map<String, Object> map = new HashMap<String, Object>();
                map.put("iv", R.drawable.i1);
                map.put("tv", "G1");
                list.add(map);

                map = new HashMap<String, Object>();
                map.put("tv", "G2");
                map.put("iv", R.drawable.i2);
                list.add(map);
                map = new HashMap<String, Object>();
                map.put("tv", "G3");
                map.put("iv", R.drawable.i3);
                list.add(map);
                map = new HashMap<String, Object>();
                map.put("tv", "G3");
                map.put("iv", R.drawable.i4);
                list.add(map);
                map = new HashMap<String, Object>();
                map.put("tv", "G3");
                map.put("iv", R.drawable.i5);
                list.add(map);
                map = new HashMap<String, Object>();
                map.put("tv", "G3");
                map.put("iv", R.drawable.i6);
                list.add(map);
                map = new HashMap<String, Object>();
                map.put("tv", "G3");
                map.put("iv", R.drawable.i7);
                list.add(map);
                map = new HashMap<String, Object>();
                map.put("tv", "G3");
                map.put("iv", R.drawable.i8);
                list.add(map);
                return list;
        }
}


file:///F:/%E7%AC%94%E8%AE%B0/temp/7c3314e7-e831-4e98-9e52-0e671208da4b/4/index_files/cdfe70b3-870c-4a53-a16d-3b34fef97e63.jpg






[size=1.2] 其实SimpleAdapter与ArrayAdapter不尽相同,如果要显示复制样式的ListView时,需要用集合来添加数据


[size=1.4]ListView之BaseAdapter(推荐)


优点:适应任何数据的适配


1,定义ListView属性(省略了咯)

2,具体代码(无优化的也省略了咯,)

public class MainActivity extends Activity {
        private List<Map<String, Object>> data;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                data=getData();
                ListView lv = (ListView) findViewById(R.id.lv);
                lv.setAdapter(new MyAdapter());
        }
        private List<Map<String, Object>> getData() {
        //创建List集合存储整个数据
                List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();               
        //创建Map集合对象,通过Key存储对应的Value,
        Map<String, Object> map = new HashMap<String, Object>();
                map.put("tv", "一");
                map.put("iv", R.drawable.i1);
                list.add(map);
                map = new HashMap<String, Object>();
                map.put("tv", "二");
                map.put("iv", R.drawable.i2);
                list.add(map);
                map = new HashMap<String, Object>();
                map.put("tv", "三");
                map.put("iv", R.drawable.i3);
                list.add(map);
                map = new HashMap<String, Object>();
                map.put("tv", "四");
                map.put("iv", R.drawable.i4);
                list.add(map);
                map = new HashMap<String, Object>();
                map.put("tv", "五");
                map.put("iv", R.drawable.i5);
                list.add(map);
                map = new HashMap<String, Object>();
                map.put("tv", "六");
                map.put("iv", R.drawable.i6);
                list.add(map);
                map = new HashMap<String, Object>();
                map.put("tv", "七");
                map.put("iv", R.drawable.i7);
                list.add(map);
                map = new HashMap<String, Object>();
                map.put("tv", "八");
                map.put("iv", R.drawable.i8);
                list.add(map);
                map = new HashMap<String, Object>();
                map.put("tv", "九");
                map.put("iv", R.drawable.i9);
                list.add(map);
                map = new HashMap<String, Object>();
                map.put("tv", "十");
                map.put("iv", R.drawable.i10);
                list.add(map);

                return list;
        }

        public class MyAdapter extends BaseAdapter {

        //获取数据的长度,从而决定要显示的行数
                @Override
                public int getCount() {
        //在实际开发中,此处的返回值是由数据库中查询出来的总条数
                        return data.size();
                }

        //根据ListView所在位置返回View
                @Override
                public Object getItem(int position) {
                        return null;
                }

        //根据ListView位置得到数据源集合中的If
                @Override
                public long getItemId(int position) {
                        return 0;
                }

        //重点在此,此方法觉得listview的界面样式
                @Override
                public View getView(int position, View convertView, ViewGroup parent) {
                        View view;
                        if (convertView == null) {
                                view = LayoutInflater.from(getApplicationContext()).inflate(
                                                R.layout.item, null);
                        } else {
                                view = convertView;
                        }
            //初始化控件,并绑定数据,由于控件是在容器的item界面中,需要通过view对象调用,不然会造成空指针异常
                        ImageView iv = (ImageView) view.findViewById(R.id.iv);
                        TextView tv = (TextView) view.findViewById(R.id.tv);
                        iv.setBackgroundResource( (Integer) data.get(position).get("iv"));
                        tv.setText((CharSequence) data.get(position).get("tv"));
                        return view;
                }
        }





ListView优化一

    通过缓存convertView,这种利用缓存contentView的方式可以判断如果缓存中不存在View才创建View,如果已经存在可以利用缓存中的View,提升了性能

@Override
                public View getView(int position, View convertView, ViewGroup parent) {
                        View view;
                        if (convertView == null) {
                  //将xml文件打包成界面显示出来
                                view = LayoutInflater.from(getApplicationContext()).inflate(
                                                R.layout.item, null);
                        } else {
                                view = convertView;
                        }
                        ImageView iv = (ImageView) view.findViewById(R.id.iv);
                        TextView tv = (TextView) view.findViewById(R.id.tv);
                        iv.setBackgroundResource( (Integer) data.get(position).get("iv"));
                        tv.setText((CharSequence) data.get(position).get("tv"));
                        return view;
                }


file:///F:/%E7%AC%94%E8%AE%B0/temp/7c3314e7-e831-4e98-9e52-0e671208da4b/4/index_files/fca106dc-ca6f-4565-a210-b910a1f567c5.jpg


ListView优化二(最优)

   通过convertView+ViewHolder来实现,ViewHolder就是一个静态类,使用 ViewHolder 的关键好处是缓存了显示数据的视图(View),加快了 UI 的响应速度。

   当我们判断 convertView == null  的时候,如果为空,就会根据设计好的List的Item布局(XML),来为convertView赋值,并生成一个viewHolder来绑定converView里面的各个View控件(XML布局里面的那些控件)。再用convertView的setTag将viewHolder设置到Tag中,以便系统第二次绘制ListView时从Tag中取出。

@Override
                public View getView(int position, View convertView, ViewGroup parent) {
                        ViewHolder viewHolder;
                        if (convertView == null) {
                                viewHolder = new ViewHolder();
                                convertView = mInflater.inflate(R.layout.item, null);
                                viewHolder.iv = (ImageView) convertView.findViewById(R.id.iv);
                                viewHolder.tv = (TextView) convertView.findViewById(R.id.tv);
                                convertView.setTag(viewHolder);
                        } else {
                                viewHolder = (ViewHolder) convertView.getTag();
                        }
                        viewHolder.iv.setImageResource((Integer) data.get(position).get(
                                        "iv"));
                        viewHolder.tv.setText((CharSequence) data.get(position).get("tv"));
                        return convertView;
                }


ListView点击事件的简单实现

lv.setOnItemClickListener(new OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view,
                                int position, long id) {
            //获取点击条目对象
                        Fruit fruit = fruitList.get(position);
                        Toast.makeText(getApplicationContext(), fruit.getName(),
                                        Toast.LENGTH_SHORT).show();
                }
        });


总结:

1.BaseAdapter(优先原则)


因为是最基本的适配器,个人认为最优化原则下,它能实现如ListView,GridView,Gallery,Spinner等众多布局.BaseAdapter直接继承接口类Adapter.


关键在与它有具体的优化,能狗极大提高效率,节约内存,至于优化一还是优化二,其实在笔者看来两者都可选.




2.掌握基础的用法


组合就五花八门了,关键在于数据与适配器的选择,如果只是简单的数组显示,任意选择都行,但是如果涉及到复杂显示,建议使用BaseAdapter或ArrayAdapter来提高效率,



3.getView的优化不仅仅能用于BaseAdapter,也能用于ArrayAdapter,



4.Android中Adapter类其实就是把数据源绑定到指定的View上,然后再返回该View,而返回来的这个View就是ListView中的某一行item。这里返回来的View正是由我们的Adapter中的getView方法返回的。这样就会容易理解数据是怎样一条一条显示在ListView中的



5.最后给一些自问


    问题1:为什么要重写一个adapter?


    问题2:究竟该继承那个Adapter?


    问题3:定义适配器是定义内部类还是工具类?


    问题4:理解应用中的数据源一般都会用到Map类型的List有什么用?


    问题5:adapter是怎样把数据一条条的item展示到ListView上的?


    问题6:重写的方法中各有什么用途?


    问题7:自己到底掌握没?

标签:map,tv,iv,详解,put,new,Android,ListView
From: https://blog.51cto.com/u_14523369/7445271

相关文章

  • android 很棒的UI合集 都是git地址很不错的需要makedown配合使用
    MaterialNameLicenseDemoMaterialDesignLibraryApacheLicenseV2DrawerArrowDrawableApacheLicenseV2MaterialTabsApacheLicenseV2PagerSlidingTabStripApacheLicenseV2material-rippleApacheLicenseV2RippleEffectMITLDrawerApacheLicenseV2material-design-icons......
  • Android静默安装实现方案
    之前有很多朋友都问过我,在Android系统中怎样才能实现静默安装呢?所谓的静默安装,就是不用弹出系统的安装界面,在不影响用户任何操作的情况下不知不觉地将程序装好。虽说这种方式看上去不打搅用户,但是却存在着一个问题,因为Android系统会在安装界面当中把程序所声明的权限展示给用户看,......
  • 详解SpringBoot下文件上传与下载的实现
    SpringBoot后台如何实现文件上传下载?最近做的一个项目涉及到文件上传与下载。前端上传采用百度webUploader插件。有关该插件的使用方法还在研究中,日后整理再记录。本文主要介绍SpringBoot后台对文件上传与下载的处理。单文件上传/单文件上传@RequestMapping(value="/uploa......
  • Android开发中常见的设计模式
    Android开发中常见的设计模式对于开发人员来说,设计模式有时候就是一道坎,但是设计模式又非常有用,过了这道坎,它可以让你水平提高一个档次。而在android开发中,必要的了解一些设计模式又是非常有必要的。对于想系统的学习设计模式的同学,这里推荐2本书。一本是HeadFirst系列的HeadH......
  • Android入门教程 | TextView简介(宽高、文字、间距)
    TextView简介文字,是我们传达信息的一种常见方式。在安卓应用上显示文字,我们通常使用TextView。之前我们已经知道如何获取到layout中的TextView,也知道setText()方法可以修改显示的文字。结合我们实际的生活和学习经验,写字的时候,有哪些方面是可以由我们来控制的?文本内容;文字颜色;大......
  • Android初级开发是如何一步步成为高级开发
    前言今年的面试形势不容乐观,竞争愈发激烈,进大厂的难度又增加了。初级程序员的市场价值越来越低,卷死卷活都难找到高薪工作。而相反的高级程序员很多公司一直稀缺,招不到人。这样就形成了两个极端。所以很多人对Android开发现状和前景特别不看好不只是Android,其实做程序这行的,如果不去......
  • Android官方推荐 无需向应用授予的照片选择器工具
    官网链接 https://developer.android.google.cn/training/data-storage/shared/photopicker?hl=en不能跳转链接看这Photopicker照片选择器对话框会显示在您的设备上的媒体文件中。选择一张照片与应用程序分享。图1.照片选择器提供了一个直观的用户界面,用于与您的应用程序分......
  • javascript事件循环机制及面试题详解
    javascript事件循环机制及面试题详解 javascript是单线程执行的程序,也就是它只有一条主线,所有的程序都是逐行“排队”执行,在这种情况下可能存在一些问题,比如说setTimeout、ajax等待执行的时间较长,就会阻塞后续代码的执行,使得整个程序执行的耗时非常久,那么为了应对这样一个问......
  • Redis.conf 详解
    一、NETWORK网络bind127.0.0.1#绑定的IPprotected-modeno#保护模式port6379#端口设置二、GENERAL通用daemonizeyes#以守护进程的方式运行,默认是no,我们需要自己开启为yespidfile/var/run/redis_6379.pid#如果是后台启动,我们需要指定一个pid文......
  • C++算法之旅、06 基础篇 | 第四章 动态规划 详解
    常见问题闫式DP分析法状态表示集合满足一定条件的所有方案属性集合(所有方案)的某种属性(Max、Min、Count等)状态计算(集合划分)如何将当前集合划分成多个子集合状态计算相当于集合的划分:把当前集合划分成若干个子集,使得每个子集的状态可以先算出来,从而推导当前......