• <Android基础>(三) UI开发 Part 2 ListView


    ListView

    1)ListView的简单用法

    2)定制ListView界面

    3)提升ListView的运行效率

    4)ListView的点击事件

    3.5 ListView

    3.5.1 ListView的简单用法

    1.新建项目,修改activity_main.xml中的代码,插入<ListView>控件

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <ListView
            android:id="@+id/list_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
    
        </ListView>
    </LinearLayout>

    2.修改MainActivity中的代码

    public class MainActivity extends AppCompatActivity {
    
        private String[] data = new String[]{"gareen","teemo","shana","annie",
                "gareen","teemo","shana","annie","gareen","teemo","shana","annie","gareen","teemo","shana","annie",
                "gareen","teemo","shana","annie",};
        @Override
        protected void onCreate(Bundle savedInstanceState) {
    
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main_activity_layout);
    
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(
                    MainActivity.this, android.R.layout.simple_list_item_1,data);
            ListView listView = (ListView)findViewById(R.id.list_view);
            listView.setAdapter(adapter);
        }
    }

    a.提供好数据,用一组字符串数组data来测试。

    b.数组中数据无法直接传递给ListView,需要借助适配器来完成。

    ArrayAdapter通过泛型来指定要适配的数据类型,然后在构造函数中把要适配的数据传入。

    将ArrayAdapter的泛型指定为String,在构造函数中依次上传当前上下文、ListView子项布局的id、以及要适配的数据。

    运行程序的结果

    3.5.2 定制ListView的界面

    对ListView界面进行定制,让显示更丰富的内容,实现让英雄名称旁边都有各自对应的英雄头像

    1.准备好一组图片存在drawable-hdpi

    2.定义一个实体类,作为ListView适配器的适配类型。新建类Hero

    public class Hero {
        private String name;
        private int imageId;
    
        public Hero(String name, int imageId) {
            this.name = name;
            this.imageId = imageId;
        }
    
        public String getName() {
    
    
            return name;
        }
        public int getImageId(){
            return imageId;
        }
    }

    name表示英雄名字,imageId表示对应的图片资源id

    3.在layout目录下新建hero_item.xml为ListView指定自定义的布局

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <ImageView
            android:id="@+id/hero_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    
        <TextView
            android:id="@+id/hero_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="10dp"/>
    
    </LinearLayout>

     4.创建一个自定义的适配器,继承自ArrayAdapter,并将泛型指向Hero类。

    新建类HeroAdapter。

    HeroAdapter重写了父类的一组构造方法,用于将上下文,ListView子项布局的id和数据都传递进来。

    另外又重写了getView()方法。首先通过getItem()方法得到当前项的Hero实例,然后使用LayoutInflater来为这个子项加载传入的布局。inflate()方法接受3个参数,第三个参数指定成false,表明只让在父布局中声明layout属性生效,但不会为这个View添加父布局。

    接下来调用View的findViewById()方法分别获取ImageView和TextView的实例,并分别调用它们的setImageResource()和setText()方法来设置显示的图片和文字,最后将布局返回。

    import android.content.Context;
    import android.provider.ContactsContract;
    import android.support.annotation.NonNull;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    import java.util.List;
    
    public class HeroAdapter extends ArrayAdapter<Hero> {
        private int resourceId;
    
        public HeroAdapter(Context context, int textViewResoureced,
                            List<Hero> objects){
            super(context, textViewResoureced, objects);
            resourceId = textViewResoureced;
        }
    
        @NonNull
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            Hero hero = getItem(position);
            View view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
            ImageView heroImage = (ImageView) view.findViewById(R.id.hero_image);
            TextView heroName = (TextView)view.findViewById(R.id.hero_name);
            heroImage.setImageResource(hero.getImageId());
            heroName.setText(hero.getName());
            return view;
        }
    }

     5.修改MainActivity中的代码

    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.widget.ArrayAdapter;
    import android.widget.ListView;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class MainActivity extends AppCompatActivity {
        private List<Hero> heroList = new ArrayList<>();
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initHeros();
            HeroAdapter adapter = new HeroAdapter(MainActivity.this,
                    R.layout.hero_item,heroList);
            ListView listView = (ListView) findViewById(R.id.list_view);
            listView.setAdapter(adapter);
        }
    
        private void initHeros(){
            for(int i = 0 ; i < 2 ; i ++){
                Hero gareen = new Hero("gareen",R.drawable.gareen);
                heroList.add(gareen);
                Hero annie = new Hero("annie",R.drawable.annie);
                heroList.add(annie);
                Hero teemo = new Hero("teemo",R.drawable.teemo);
                heroList.add(teemo);
                Hero shana = new Hero("shana",R.drawable.shana);
                heroList.add(shana);
            }
        }
    }

     initHeros()方法用于初始化所有的英雄数据。

    在Hero类的构造函数中将水果的名字和对应的图片id传入,然后把创建好的对象添加到英雄列表中。

    接着在onCreat()方法中创建了HeroAdapter对象,并将HeroAdapter作为适配器传递给ListView。

    运行程序。

     定制界面完成。

    3.5.3 提升ListView的运行效率

    getView()方法中有一个convertView参数,这个参数用于将之前加载好的布局进行缓存,以便之后可以重用。

    1.HeroAdapter的gatView()方法中每次都将布局重新加载一边,当ListView快速滚动时,就有可能成为性能的瓶颈。

    修改HeroAdapter中的代码

     @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            Hero hero = getItem(position);
            View view;
            if(convertView == null){
                view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
            }else{
                view = convertView;
            }
            ImageView heroImage = (ImageView) view.findViewById(R.id.hero_image);
            TextView heroName = (TextView)view.findViewById(R.id.hero_name);
            heroImage.setImageResource(hero.getImageId());
            heroName.setText(hero.getName());
            return view;
        }
     if(convertView == null){
                view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
            }else{
                view = convertView;
            }

    表示对convertView进行判断,如果为null,则使用LayoutInflater去加载布局,如果不为null则直接对convertView直接重用。

    2. 每次在getView()中会调用View的findViewById()方法来获取一次控件的实例。可以用ViewHolder来对这部分进行优化。

    修改HeroAdapter中的代码。

      @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            Hero hero = getItem(position);
            View view;
            ViewHolder viewHolder;
            if(convertView == null){
                view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
                viewHolder = new ViewHolder();
                viewHolder.heroImage = (ImageView)view.findViewById(R.id.hero_image);
                viewHolder.heroName = (TextView)view.findViewById(R.id.hero_name);
                view.setTag(viewHolder);
            }else{
                view = convertView;
                viewHolder = (ViewHolder)view.getTag();//重新获取ViewHolder
            }
            viewHolder.heroImage.setImageResource(hero.getImageId());
            viewHolder.heroName.setText(hero.getName());
            return view;
        }
        
        class ViewHolder{
            ImageView heroImage;
            TextView heroName;
        }
         View view;
            ViewHolder viewHolder;
            if(convertView == null){
                view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
                viewHolder = new ViewHolder();
                viewHolder.heroImage = (ImageView)view.findViewById(R.id.hero_image);
                viewHolder.heroName = (TextView)view.findViewById(R.id.hero_name);
                view.setTag(viewHolder);
            }else{
                view = convertView;
                viewHolder = (ViewHolder)view.getTag();//重新获取ViewHolder
            }
            viewHolder.heroImage.setImageResource(hero.getImageId());
            viewHolder.heroName.setText(hero.getName());
      class ViewHolder{
            ImageView heroImage;
            TextView heroName;
        }

    提供一个内部类ViewHolder,用于对控件进行缓存。当convertView为null时,创建一个ViewHolder对象,并将控件的实例都存放在ViewHolder中,然后调用setTag()方法,将ViewHolder对象储存在VIew中。当convertView不为null时,则调用View的getTag()方法,把ViewHolder重新取出。

    所有控件实例都缓存在VIewHolder中,就没有必要每次通过findViewById()方法来获取控件实例了。

    3.5.4 ListView的点击事件

    给每一个Item添加Toast,修改MainActivity中的代码。

         ListView listView = (ListView) findViewById(R.id.list_view);
            listView.setAdapter(adapter);
            listView.setOnItemClickListener(new AdapterView.OnItemClickListener(){
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    Hero hero = heroList.get(position);
                    Toast.makeText(MainActivity.this, hero.getName(), Toast.LENGTH_SHORT).show();
                }
            });

    用setOnItemClikListener()方法为ListView注册一个监听器,当用户点击了ListView中的任何一个子项时,就会回调onItemClick()方法。在该方法中即可通过position参数判断出用户点击的是哪一个子项,然后获得相应的name,通过Toast展现出来。

  • 相关阅读:
    实现h5中radio单击取消与选中
    小程序中的组件化理解
    阿里字体css代码引入方法
    前端布局心得小结
    Python学习资源汇总,转载自他人
    史上最全 原生javascript的知识总结,适合新手及查资料用!
    windows Python 3.4.3 安装图文
    PyInstaller编译python3时使用的详细参数介绍
    PyInstaller 安装方法 及简单的编译exe (python3)
    Windows 安装 GTK+ 图文说明
  • 原文地址:https://www.cnblogs.com/HarSong13/p/10658025.html
Copyright © 2020-2023  润新知