Android最常用的控件ListView(详解)

Android最常用的控件ListView(详解)

一.ListView简介

在Android开发中,ListView是一个比较常用的控件。它以列表的形式 展示具体数据内容,并且能够根据数据的长度自适应屏幕显示。

二.ListView简单用法

代码部分

1.布局界面 activity_main.xml 代码:

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity">

android:id="@+id/list_view"

android:layout_width="match_parent"

android:layout_height="match_parent"/>

2.类文件 MainActivity.java 代码:

package com.example.listview1;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import android.view.View;

import android.widget.AdapterView;

import android.widget.ArrayAdapter;

import android.widget.ListView;

import android.widget.TextView;

import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

//1、定义对象

ListView listView;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

//2、绑定控件

listView=(ListView) findViewById(R.id.list_view);

//3、准备数据

String[] data={"菠萝","芒果","石榴","葡萄", "苹果", "橙子", "西瓜","菠萝","芒果","石榴","葡萄", "苹果", "橙子", "西瓜","菠萝","芒果","石榴","葡萄", "苹果", "橙子", "西瓜"};

//4、创建适配器 连接数据源和控件的桥梁

//参数 1:当前的上下文环境

//参数 2:当前列表项所加载的布局文件

//(android.R.layout.simple_list_item_1)这里的布局文件是Android内置的,里面只有一个textview控件用来显示简单的文本内容

//参数 3:数据源

ArrayAdapter adapter=new ArrayAdapter<>(MainActivity.this,android.R.layout.simple_list_item_1,data);

//5、将适配器加载到控件中

listView.setAdapter(adapter);

//6、为列表中选中的项添加单击响应事件

listView.setOnItemClickListener(new AdapterView.OnItemClickListener()

{

@Override

public void onItemClick(AdapterView parent, View view, int i, long l) {

String result=((TextView)view).getText().toString();

Toast.makeText(MainActivity.this,"您选择的水果是:"+result,Toast.LENGTH_LONG).show();

}

});

}

}

代码解析

1.ArrayAdapter适配器

1、ArrayAdapter适用亍数组或数据ArrayList(动态数组)。

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

3、ArrayAdapter有多个构造函数的重载,可以根据实际情况选择最合适的一种。

2.点击事件响应

Parent: 指定哪个AdapterView(可能会有多个ListView,区分多个ListView)

View: 为你点击的Listview的某一项的内容,来源于adapter。如用((TextView)view).getText().toString(),可以取出点击的这一项的内容,转为string 类型。

Position: 指的是adapter的某一项的位置,如点击了listview第2项,而第2项对应 的是adapter的第2个数值,那此时position的值就为1了。注:这些数值都是从0开 始的。

Id:id的值为点击了Listview的哪一项对应的数值,点击了listview第2项,那id就等于1。一般和position相同。

三.定制 ListView 界面

只能显示一段文本的listview太单调了,我们现在就来对listview的界面进行定制,让其丰富内容。

代码部分

1.布局界面 activity_main.xml 代码:

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity">

android:id="@+id/list_view"

android:layout_width="match_parent"

android:layout_height="match_parent"/>

2.类文件 MainActivity.java 代码:

package com.example.listview2;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import android.widget.ListView;

import java.util.ArrayList;

import java.util.List;

public class MainActivity extends AppCompatActivity {

//第一步:定义对象

ListView listView;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

//第二步:绑定控件

listView = (ListView) findViewById(R.id.list_view);

//第三步:准备数据

List fruitlist = new ArrayList<>();

for (int i = 0; i <2 ; i++) {

Fruit pineapple=new Fruit(R.drawable.pineapple,"菠萝","¥16.9 元/KG");

fruitlist.add(pineapple);

Fruit mango = new Fruit(R.drawable.mango, "芒果","¥29.9 元/kg");

fruitlist.add(mango);

Fruit pomegranate = new Fruit(R.drawable.pomegranate, "石榴","¥15元/kg");

fruitlist.add(pomegranate);

Fruit grape = new Fruit(R.drawable.grape, "葡萄","¥19.9 元/kg");

fruitlist.add(grape);

Fruit apple = new Fruit(R.drawable.apple, "苹果","¥20 元/kg");

fruitlist.add(apple);

Fruit orange = new Fruit(R.drawable.orange, "橙子","¥18.8 元/kg");

fruitlist.add(orange);

Fruit watermelon = new Fruit(R.drawable.watermelon, "西瓜","¥28.8元/kg");

fruitlist.add(watermelon);

}

//第四步:设计每一个列表项的子布局

//第五步:定义适配器 控件 -桥梁-数据

FruitAdapter adapter=new FruitAdapter(MainActivity.this,R.layout.fruit_item,fruitlist);

listView.setAdapter(adapter);

}

}

3.类文件 Fruit.java 代码:

package com.example.listview2;

public class Fruit {

private int imageID;

private String name;

private String price;

public int getImageID() {

return imageID;

}

public String getName() {

return name;

}

public String getPrice() {

return price;

}

public Fruit(int imageID, String name, String price) {

this.imageID = imageID;

this.name = name;

this.price = price;

}

}

4.类文件 FruitAdapter.java 代码:

package com.example.listview2;

import android.content.Context;

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;

import androidx.annotation.NonNull;

import androidx.annotation.Nullable;

//用于将上下文、listview 子项布局的 id 和数据都传递过来

public class FruitAdapter extends ArrayAdapter {

public FruitAdapter(@NonNull Context context, int resource, @NonNull List objects) {

super(context, resource, objects);

}

//每个子项被滚动到屏幕内的时候会被调用

@NonNull

@Override

public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {

Fruit fruit=getItem(position);//得到当前项的 Fruit 实例

//为每一个子项加载设定的布局

View view=LayoutInflater.from(getContext()).inflate(R.layout.fruit_item,parent,false);

//分别获取 image view 和 textview 的实例

ImageView fruitimage =view.findViewById(R.id.fruit_image);

TextView fruitname =view.findViewById(R.id.fruit_name);

TextView fruitprice=view.findViewById(R.id.fruit_price);

// 设置要显示的图片和文字

fruitimage.setImageResource(fruit.getImageID());

fruitname.setText(fruit.getName());

fruitprice.setText(fruit.getPrice());

return view;

}

}

5.布局界面 fruit_item.xml 代码:

android:layout_width="match_parent"

android:orientation="horizontal"

android:layout_height="wrap_content">

android:id="@+id/fruit_image"

android:src="@drawable/apple"

android:layout_width="100dp"

android:layout_height="80dp"/>

android:id="@+id/fruit_name"

android:layout_gravity="center_vertical"

android:textSize="30sp"

android:textColor="#000000"

android:text="name"

android:layout_marginLeft="10dp"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>

android:id="@+id/fruit_price"

android:layout_gravity="center_vertical"

android:textColor="#ff0000"

android:text="price"

android:textSize="30sp"

android:layout_marginLeft="10dp"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>

代码解析

1.引入动态数组ArrayList

数组的缺点

(1)数组长度固定

(2)定义数组只能指定一种数据类型

ArrayList:可以动态增加和缩减的索引序列,它是基于数组实现的list类

List fruitlist = new ArrayList<>();

List泛型里面既包括图片又包含文本,因此我们要定义一个Fruit类

2.Fruit类

public class Fruit {

private int imageID;

private String name;

private String price;

}

在里面添加图片的id,名称和价格

然后按下Alt+Insert键添加构造方法(Constructor)和Get方法(Getter)

3.自定义适配器 控件 -桥梁-数据

为什么要自定义适配器?

原因在于,当我们想用一些其他的展现方式,或者是本案例我们需要的图文混排的呈现方式,这就需要DIY了。

1.我们定义一个自定义适配器 FruitAdapter继承ArrayAdapter。

2.自定义适配器中常用的方法:getCount、getView、getItem、getItemId。

(1)创建好后需要添加泛型(也就是我们创建的Fruit类)

(2)按下键盘上的Alt+Enter键创建构造方法(倒数第二个list

(3)重写getView方法

4.inflate()方法

inflate()方法的三个参数

inflate(R.layout.fruit_item,parent,false)

1、第一个参数是布局;(自己写的)

2、第二个参数是父容器控件;

3、第三个布尔值参数表明是否连接该布局和其父容器控件,在这里的情况设置 为false,因为系统已经插入了这个布局到父控件,设置为true将会产生多余的一 个View Group。

四.提升ListView的运行效率

目前我们ListView的运行效率是很低的,因为在FruitAdapter的 getView()方法中,每次都将布局重 新加载了一遍,将快速滚动的时候, 这将会成为性能的瓶颈。

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

优化方法一:

优化方法二:

代码:

package com.example.listview3;

import android.content.Context;

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;

import androidx.annotation.NonNull;

import androidx.annotation.Nullable;

//用于将上下文、listview 子项布局的 id 和数据都传递过来

public class FruitAdapter extends ArrayAdapter {

public FruitAdapter(@NonNull Context context, int resource, @NonNull List objects) {

super(context, resource, objects);

}

@NonNull

@Override

public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {

Fruit fruit=getItem(position);//获取当前项的 Fruit 实例

View view;

//新增一个内部类 ViewHolder,用于对控件的实例进行缓存

ViewHolder viewHolder;

if (convertView==null){

//为每一个子项加载设定的布局

view= LayoutInflater.from(getContext()).inflate(R.layout.fruit_item,parent,false);

viewHolder=new ViewHolder();

//分别获取 imageview 和 textview 的实例

viewHolder.fruitimage =view.findViewById(R.id.fruit_image);

viewHolder.fruitname =view.findViewById(R.id.fruit_name);

viewHolder.fruitprice=view.findViewById(R.id.fruit_price);

view.setTag(viewHolder);//将 viewHolder 存储在 view 中

}else {

view=convertView;

viewHolder= (ViewHolder) view.getTag();//重新获取 viewHolder

}

// 设置要显示的图片和文字

viewHolder.fruitimage.setImageResource(fruit.getImageID());

viewHolder.fruitname.setText(fruit.getName());

viewHolder.fruitprice.setText(fruit.getPrice());

return view;

}

private class ViewHolder {

ImageView fruitimage;

TextView fruitname;

TextView fruitprice;

}

}

五.ListView的点击事件

ListView的滚动毕竟只是满足 了我们视觉上的效果,下面我们来学习ListView如何才能响 应用户的点击事件。

代码:

//第六步:listview 的点击事件

listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

@Override

public void onItemClick(AdapterView adapterView, View view, int position, long id) {

Fruit fruit= fruitlist.get(position) ;

Toast.makeText(MainActivity.this,"您选择的水果是:"+fruit.getName(),Toast.LENGTH_LONG).show();

}

});

六.总结

七.参考资料

点击免费下载

相关推荐

YSL恒久粉底液真实使用感受
365沙巴体育入口

YSL恒久粉底液真实使用感受

📅 07-22 👁️ 757
日本十大禁动漫(被禁止的10部神级动漫)
365沙巴体育入口

日本十大禁动漫(被禁止的10部神级动漫)

📅 06-28 👁️ 4240
怡美达书柜
365速发国际平台app下载

怡美达书柜

📅 07-19 👁️ 691
7.3德鲁伊职业大厅 追随者选择思路及装备的取舍
365速发国际平台app下载

7.3德鲁伊职业大厅 追随者选择思路及装备的取舍

📅 07-10 👁️ 4362
曲高和寡典故故事|曲高和寡释义
365彩票下载1.0.0老版本

曲高和寡典故故事|曲高和寡释义

📅 07-31 👁️ 3779
卷曲海浪冲浪模拟器(FlowCurl)
365彩票下载1.0.0老版本

卷曲海浪冲浪模拟器(FlowCurl)

📅 08-04 👁️ 9398
纽曼C18(电信2G)参数及手机配置介绍
365沙巴体育入口

纽曼C18(电信2G)参数及手机配置介绍

📅 07-16 👁️ 5535
LOL:为什么越来越多的人不玩VN了?五个原因导致的
365沙巴体育入口

LOL:为什么越来越多的人不玩VN了?五个原因导致的

📅 07-15 👁️ 7251
酒店销售待遇(星级酒店销售工资一般多少)
365沙巴体育入口

酒店销售待遇(星级酒店销售工资一般多少)

📅 07-30 👁️ 2503