ListView的简单用法
在activtity布局文件中定义一个Listview
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
然后在activity中用ArrayAdapter获取数据,再将这个ArrayAdapter给ListView
package com.study.listView;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class MainActivity extends AppCompatActivity {
private String[] data={
"Apple","Banana","Orange","Watermelon","Pear","Grape","Pineapple","Strawberry","Cherry","Mango","Apple","Banana","Orange","Watermelon","Pear","Grape" +
"Pineapple","Strawberry","Cherry","Mango"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//将数据放到适配器中,这里的simple_list_item_1只是一个简单的Textview布局的id
ArrayAdapter<String> adapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1,data);
//将适配器中的数据回传给listView
ListView listView=(ListView)findViewById(R.id.list_View);
listView.setAdapter(adapter);
}
}
定制ListView界面
自定义子项,修改适配器(以适应子项的数据要求)。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/image_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
修改的适配器如下:
class FruitAdapter extends ArrayAdapter<Fruit>{
int sourceId;
public FruitAdapter(@NonNull Context context, int resource, @NonNull List<Fruit> objects) {
super(context, resource, objects);
//将子项布局id传进来
sourceId=resource;
}
@NonNull
@Override
//getView在每个子项滑到屏幕时会自动调用
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
//得到当前position下的fruit
Fruit fruit=getItem(position);
//LayoutInflater.from(getContext())获得一个实例对象
// 通过这个实例对象引入子项view
View view= LayoutInflater.from(getContext()).inflate(sourceId,parent,false);
//得到一个view后进行数据赋值。
ImageView imageView=view.findViewById(R.id.image_view);
TextView textView=view.findViewById(R.id.image_name);
imageView.setImageResource(fruit.getId());
textView.setText(fruit.getName());
//返回这个子项
return view;
}
}
总的代码:
package com.study.listView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import android.app.PendingIntent;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private List<Fruit> fruitList=new ArrayList<Fruit>();
private String[] data={
"Apple","Banana","Orange","Watermelon","Pear","Grape","Pineapple","Strawberry","Cherry","Mango","Apple","Banana","Orange","Watermelon","Pear","Grape" +
"Pineapple","Strawberry","Cherry","Mango"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
for(int i=0; i<2; i++){
Fruit fruit=new Fruit("Apple",R.drawable.apple_pic);
fruitList.add(fruit);
fruit=new Fruit("Banana",R.drawable.banana_pic);
fruitList.add(fruit);
fruit=new Fruit("Orange",R.drawable.orange_pic);
fruitList.add(fruit);
fruit=new Fruit("Watermelon",R.drawable.grape_pic);
fruitList.add(fruit);
fruit=new Fruit("Pear",R.drawable.pear_pic);
fruitList.add(fruit);
fruit=new Fruit("Grape",R.drawable.grape_pic);
fruitList.add(fruit);
fruit=new Fruit("Pineapple",R.drawable.pineapple_pic);
fruitList.add(fruit);
fruit=new Fruit("Strawberry",R.drawable.strawberry_pic);
fruitList.add(fruit);
fruit=new Fruit("Cherry",R.drawable.cherry_pic);
fruitList.add(fruit);
fruit=new Fruit("Mango",R.drawable.mango_pic);
fruitList.add(fruit);
}
FruitAdapter fruitAdapter=new FruitAdapter(this,R.layout.fruit_item,fruitList);
ListView listView=findViewById(R.id.list_View);
listView.setAdapter(fruitAdapter);
}
}
class Fruit{
private String name;
private int id;
public String getName() {
return name;
}
public int getId() {
return id;
}
Fruit(String name,int id){
this.name=name;
this.id=id;
}
}
class FruitAdapter extends ArrayAdapter<Fruit>{
int sourceId;
public FruitAdapter(@NonNull Context context, int resource, @NonNull List<Fruit> objects) {
super(context, resource, objects);
//将子项布局id传进来
sourceId=resource;
}
@NonNull
@Override
//getView在每个子项滑到屏幕时会自动调用
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
//得到当前position下的fruit
Fruit fruit=getItem(position);
//LayoutInflater.from(getContext())获得一个实例对象
// 通过这个实例对象引入子项view
View view= LayoutInflater.from(getContext()).inflate(sourceId,parent,false);
//得到一个view后进行数据赋值。
ImageView imageView=view.findViewById(R.id.image_view);
TextView textView=view.findViewById(R.id.image_name);
imageView.setImageResource(fruit.getId());
textView.setText(fruit.getName());
//返回这个子项
return view;
}
}
提升ListView的运行效率
通过convertView缓存
上述代码运行ListView时,每次都要加载一个View,这种方法的运行效率是比较低的,于是可以通过convertView将离开布局的子项View缓存。新的子项View就可以通过这个缓存的子项View进行数据修改然后重新添加进布局就好。
修改适配器中的getView方法。
class FruitAdapter extends ArrayAdapter<Fruit>{
int sourceId;
public FruitAdapter(@NonNull Context context, int resource, @NonNull List<Fruit> objects) {
super(context, resource, objects);
//将子项布局id传进来
sourceId=resource;
}
@NonNull
@Override
//getView在每个子项滑到屏幕时会自动调用
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
//得到当前position下的fruit
Fruit fruit=getItem(position);
//LayoutInflater.from(getContext())获得一个实例对象
// 通过这个实例对象引入子项view
//修改开始
View view;
if(convertView==null){
view= LayoutInflater.from(getContext()).inflate(sourceId,parent,false);
}else{
view=convertView;
}
//修改结束
//得到一个view后进行数据赋值。
ImageView imageView=view.findViewById(R.id.image_view);
TextView textView=view.findViewById(R.id.image_name);
imageView.setImageResource(fruit.getId());
textView.setText(fruit.getName());
//返回这个子项
return view;
}
}
通过ViewHolder来优化获取控件
通过上述代码我们发现,虽然通过convertView不用在去加载view了,但是每次还是要去加载view对应的组件,但是可以发现的是这些组件也是可以复用的。可以新建一个类ViewHolder来放这些组件。
修改代码如下:
class FruitAdapter extends ArrayAdapter<Fruit>{
int sourceId;
public FruitAdapter(@NonNull Context context, int resource, @NonNull List<Fruit> objects) {
super(context, resource, objects);
//将子项布局id传进来
sourceId=resource;
}
@NonNull
@Override
//getView在每个子项滑到屏幕时会自动调用
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
//得到当前position下的fruit
Fruit fruit=getItem(position);
//LayoutInflater.from(getContext())获得一个实例对象
// 通过这个实例对象引入子项view
View view;
ViewHolder viewHolder;
if(convertView==null){
view= LayoutInflater.from(getContext()).inflate(sourceId,parent,false);
viewHolder=new ViewHolder();
viewHolder.imageView=view.findViewById(R.id.image_view);
viewHolder.textView=view.findViewById(R.id.image_name);
view.setTag(viewHolder);
}else{
view=convertView;
viewHolder=(ViewHolder)view.getTag();
}
//得到一个view后进行数据赋值。
ImageView imageView=viewHolder.imageView;
TextView textView=viewHolder.textView;
imageView.setImageResource(fruit.getId());
textView.setText(fruit.getName());
//返回这个子项
return view;
}
class ViewHolder{
ImageView imageView;
TextView textView;
}
}
ListView的点击事件
为listView的子项添加绑定事件就行了。
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Fruit fruit=fruitList.get(position);
Toast.makeText(MainActivity.this,fruit.getName(),Toast.LENGTH_SHORT).show();
}
});