<Android基础>(五) UI开发 Part 2

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展现出来。

原文地址:https://www.cnblogs.com/HarSong13/p/10658025.html

时间: 2024-10-30 00:21:06

<Android基础>(五) UI开发 Part 2的相关文章

&lt;Android基础&gt;(四) UI开发 Part 1

1.常用控件 1)TextView 2)Button 3)EditText 4)ImageView 5)ProgressBar 6)AlertDialog 7)ProgressDialog 2.四种布局 1)LinearLayout 2)RelativeLayout 3)FrameLayout 4)百分比布局 3.自定义控件 1)引入布局 2)创建自定义控件 先占个坑,word发布图片出现了问题,后续补上. 不管有没有人看,也算是兜兜转转终于做到了自己想做的东西,继续加油吧! 原文地址:http

Android基础(五) Service全解析----看不见的Activity

一.服务的介绍: 作为Android四大组件之中的一个,Service(服务)也常常运用于我们的日常使用中,它与Activity的差别在于:Service一直在后台执行.没实用户界面.所以绝不会到前台来.但Service被启动起来之后.它就和Activity一样.全然具有自己的生命周期. 在关于程序中是选择用Activity还是Service的一个选择标准就是:假设某个程序组件须要执行时向用户呈现某种用户界面.或者该程序须要与用户交互,就须要使用Activity,否则就该考虑使用Service.

&lt;Android基础&gt;(五) 广播机制 Part 1

1)接收系统广播:a.动态注册监听网络变化 b.静态注册实现开机启动 2)发送自定义广播:a.发送标准广播 b.发送有序广播 3)使用本地广播 第五章 5.1 广播机制 Android中的每个程序都可以对自己感兴趣的广播进行注册.发送广播的方法借助Intent,接收广播的方法则为广播接收器(Broadcast Receiver). 广播可分为两种. 1.标准广播 (Normal broadcasts):完全异步执行的广播,在广播发出之后,所有广播几乎会在同一时刻接收到这条广播信息,没有任何先后顺

Android基础——基本UI控件:

两种文本框:EditText,TextView, 两种按钮:Button,ImageButton, 单选按钮/单选按钮组:RadioButton,RadioGroup 复选框:CheckBox <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:a

Android基础——高级UI组件:图像视图和图片切换器

layout代码 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.

Android基础——高级UI组件:下拉框,列表,滚动条视图

布局文件 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.andr

Android基础——高级UI组件:选项卡

布局文件 <?xml version="1.0" encoding="utf-8"?> <TabHost xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.c

Android与Swift iOS开发:语言与框架对比

Swift是现在Apple主推的语言,2014年新推出的语言,比Scala等“新”语言还要年轻10岁.2015年秋已经开源.目前在linux上可用,最近已经支持Android NDK:在树莓派上有SwiftyGPIO库,可以通过GPIO控制一些硬件. Object C is old and ugly,oc是1983年苹果推出的,过于陈旧和臃肿. Swift语法类似Scala,Javascript ES6, Java,OC, C++, Python 这是tiobe发布的编程语言排行 Swift支持

Android基础之五:四大组件(Broadcast Receiver)

Broadcast Receiver作为Android四大组件之一,在整个系统中广泛运用,系统中存在各种各样的广播机制,例如下载,网络等都有具体的广播接收器 广播在很大程度上简化了开发,可以通过广播监听系统状态变化,监听另一App中事件传递,可以接收当前App中不同组件,不同UI.不同线程之间的消息传递 广播的创建与使用 创建一个继承自BroadcastReceiver类的子类,重写onReceiver方法 public class MReceiver extends BroadcastRece