一、ListView的简介
<ListView>
:用于展示大量数据的一种列表视图,通过上下滑动的方式将屏幕外的数据滚动到屏幕内。
数据无法直接传递给ListView,需要适配器
Adapter:作用是将各种数据以合适的形式展示到View上。
说白了,就是ListView是一个框架,然后在Adapter中创建视图,再把Adapter放到ListView中。
二、实例:购物商城
构建过程:
1.activity_main.xml中的布局
就两个布局,最上面的购物商城是一个TextView,下面是一个ListView
<?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.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="购物商城"
android:background="#FF9100"
android:gravity="center"
android:textSize="40dp"
/>
<ListView
android:id="@+id/mylist"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#D3C5C5"
android:dividerHeight="2dp"/>
</LinearLayout>
效果如图所示:
2.创建第二个布局,即每一个ltem中的布局
这个布局写的是每一列中的布局
注意:由于在ListView中,每一行的View会将元素压缩在中间,所以在写LitemLayout的时候,要将元素放在视图的居中位置。
布局代码:itemLayout.xml
使用的是相对布局,三个TexsView贴着ImageView
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ImageView
android:layout_width="130dp"
android:layout_height="80dp"
android:layout_centerVertical="true"
android:layout_marginLeft="30dp"
android:id="@+id/iv"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/iv"
android:layout_alignTop="@+id/iv"
android:layout_marginTop="20dp"
android:layout_marginLeft="10dp"
android:id="@+id/title1"
android:text="标题"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/iv"
android:layout_alignTop="@+id/iv"
android:layout_marginTop="50dp"
android:layout_marginLeft="10dp"
android:textColor="#F4B977"
android:id="@+id/price1"
android:text="价格:"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/price1"
android:layout_alignTop="@+id/price1"
android:layout_marginLeft="10dp"
android:textColor="#F4B977"
android:id="@+id/price"
android:text="多少钱"
/>
</RelativeLayout>
呈现效果:
3.构建Adapter
构建MyAdapter用来处理每一列的视图,这里的MyAdapter是自己写的一个适配器,继承于BaseAdapter。
BaseAdapter中有四个方法需要复写:
(1)getCount() 获取item的数量,即这个ListView中一共要展示多少行
(2)getItem(int i) i表示当前item的序号,序号从0开始编写,getIte用于获取某个item
(3)getItemId(int i) 获取选中的item的编号
(4)getView(int i, View view, ViewGroup viewGroup) 这个方法是核心,用于配置listview要加载的内容,包括视图和数据,在Adapter中,它会遍历需要展示的数据,一般我们将数据封装放在ArrayList中,然后它就会去遍历这个ArrayList,i表示遍历到的数据号,可以根据i来拿数据。View的话是用来临时储存页面,初始时为空。
private class MyAdapter extends BaseAdapter {
@Override
public int getCount() {//获取item的数量
return foods.size();
}
@Override
public Object getItem(int i) {//i表示当前item的序号,序号从0开始编写,getIte用于获取某个item
return foods.get(i);
}
@Override
public long getItemId(int i) {//获取选中的item的编号
return i;
}
@Override//用于配置listview要加载的内容,包括视图和数据
public View getView(int i, View view, ViewGroup viewGroup) {
// 这种写法,每次调用都要生成一个新的View,那么当数据多了,那就要生成很多个view,
// 这样会造成资源浪费
// View view1 = View.inflate(MainActivity.this,R.layout.itemlayout,null);
// title1 = view1.findViewById(R.id.title1);
// iv = view1.findViewById(R.id.iv);
// price = view1.findViewById(R.id.price);
// title1.setText(foods.get(i).getTitle());
// iv.setBackgroundResource(foods.get(i).getIcon());
// price.setText(foods.get(i).getPrice());
// 优化写法
ViewHolder holder = null;
if(view == null){
//这里是将item视图与view绑定起来
view = View.inflate(MainActivity.this,R.layout.itemlayout,null);
holder = new ViewHolder();
// 注意,这里是去view的视图里面拿id
holder.title = view.findViewById(R.id.title1);
holder.iv = view.findViewById(R.id.iv);
holder.price = view.findViewById(R.id.price);
holder.title.setText(foods.get(i).getTitle());
holder.iv.setBackgroundResource(foods.get(i).getIcon());
holder.price.setText(foods.get(i).getPrice());
view.setTag(holder);
}else {
holder = (ViewHolder) view.getTag();
holder.title.setText(foods.get(i).getTitle());
holder.iv.setBackgroundResource(foods.get(i).getIcon());
holder.price.setText(foods.get(i).getPrice());
}
return view;
}
}
4.对数据封装和对页面标签封装
对页面数据进行封装:
public class Food {
private int icon;
private String title;
private String price;
public Food(int icon, String title, String price) {
this.icon = icon;
this.title = title;
this.price = price;
}
public int getIcon() {
return icon;
}
public void setIcon(int icon) {
this.icon = icon;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getPrice() {
return price;
}
public void setPrivce(String price) {
this.price = price;
}
}
在MainActivity中生成数据
//数据生成:
private ArrayList<Food> inData(){
ArrayList<Food> foods = new ArrayList<>();
foods.add(new Food(R.drawable.one,"小笼包","10元"));
foods.add(new Food(R.drawable.two,"草莓蛋糕","20元"));
foods.add(new Food(R.drawable.three,"龙虾","200元"));
foods.add(new Food(R.drawable.four,"火锅","150元"));
foods.add(new Food(R.drawable.five,"披萨","60元"));
foods.add(new Food(R.drawable.six,"鳗鱼饭","40元"));
foods.add(new Food(R.drawable.one,"小笼包","10元"));
foods.add(new Food(R.drawable.two,"草莓蛋糕","20元"));
foods.add(new Food(R.drawable.three,"龙虾","200元"));
foods.add(new Food(R.drawable.four,"火锅","150元"));
foods.add(new Food(R.drawable.five,"披萨","60元"));
return foods;
}
对页面标签进行分装:
因为在Adapter的getView中,如果每遍历一次数据就生成一个View的话,就造成资源的浪费,于是我们采用一个优化写法:对View控件中的代码进行封装,那么每次便不需要再次生成一个View
// 对view中的控件进行封装
static class ViewHolder{
TextView title;
ImageView iv;
TextView price;
}
MianActivity完整代码
package com.edu.nchu.listview1;
import androidx.appcompat.app.AppCompatActivity;
import android.hardware.lights.LightState;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
ListView myList = null;
ArrayList<Food> foods;
TextView title1;
ImageView iv;
TextView price;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myList = findViewById(R.id.mylist);
foods = inData();
MyAdapter myAdapter = new MyAdapter();
myList.setAdapter(myAdapter);
}
private class MyAdapter extends BaseAdapter {
@Override
public int getCount() {//获取item的数量
return foods.size();
}
@Override
public Object getItem(int i) {//i表示当前item的序号,序号从0开始编写,getIte用于获取某个item
return foods.get(i);
}
@Override
public long getItemId(int i) {//获取选中的item的编号
return i;
}
@Override//用于配置listview要加载的内容,包括视图和数据
public View getView(int i, View view, ViewGroup viewGroup) {
// 这种写法,每次调用都要生成一个新的View,那么当数据多了,那就要生成很多个view,
// 这样会造成资源浪费
// View view1 = View.inflate(MainActivity.this,R.layout.itemlayout,null);
// title1 = view1.findViewById(R.id.title1);
// iv = view1.findViewById(R.id.iv);
// price = view1.findViewById(R.id.price);
// title1.setText(foods.get(i).getTitle());
// iv.setBackgroundResource(foods.get(i).getIcon());
// price.setText(foods.get(i).getPrice());
// 优化写法
ViewHolder holder = null;
if(view == null){
//这里是将item视图与view绑定起来
view = View.inflate(MainActivity.this,R.layout.itemlayout,null);
holder = new ViewHolder();
// 注意,这里是去view的视图里面拿id
holder.title = view.findViewById(R.id.title1);
holder.iv = view.findViewById(R.id.iv);
holder.price = view.findViewById(R.id.price);
holder.title.setText(foods.get(i).getTitle());
holder.iv.setBackgroundResource(foods.get(i).getIcon());
holder.price.setText(foods.get(i).getPrice());
view.setTag(holder);
}else {
holder = (ViewHolder) view.getTag();
holder.title.setText(foods.get(i).getTitle());
holder.iv.setBackgroundResource(foods.get(i).getIcon());
holder.price.setText(foods.get(i).getPrice());
}
return view;
}
}
//数据生成:
private ArrayList<Food> inData(){
ArrayList<Food> foods = new ArrayList<>();
foods.add(new Food(R.drawable.one,"小笼包","10元"));
foods.add(new Food(R.drawable.two,"草莓蛋糕","20元"));
foods.add(new Food(R.drawable.three,"龙虾","200元"));
foods.add(new Food(R.drawable.four,"火锅","150元"));
foods.add(new Food(R.drawable.five,"披萨","60元"));
foods.add(new Food(R.drawable.six,"鳗鱼饭","40元"));
foods.add(new Food(R.drawable.one,"小笼包","10元"));
foods.add(new Food(R.drawable.two,"草莓蛋糕","20元"));
foods.add(new Food(R.drawable.three,"龙虾","200元"));
foods.add(new Food(R.drawable.four,"火锅","150元"));
foods.add(new Food(R.drawable.five,"披萨","60元"));
return foods;
}
// 对view中的控件进行封装
static class ViewHolder{
TextView title;
ImageView iv;
TextView price;
}
}