ListView
- 一、ListView简单用法
- 1、新建ListView布局
- 2、ListView实现
- 3、效果图
- 二、定制ListView的界面
- 1、自定义实体类:
- 2、自定义布局:
- 3、自定义适配器:
- 4、优化ListView运行效率
- 5、自定义ListView界面实现并设置ListView点击事件:
- 6、自定义界面效果图
一、ListView简单用法
由于手机屏幕空间都比较有限,能够一次性在屏幕上面显示的内容不多,当我们的程序有大量数据需要展示时,就可以借助ListView来实现。ListView允许用户通过手指上下滑动的方式将屏幕外的数据滚动到屏幕内,同时屏幕上原有的数据则会滚出屏幕。如查看QQ聊天记录等都是用的这个控件。
用法:
1、新建ListView布局
<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/listview_1"
android:layout_width="match_parent" //占据整个屏幕
android:layout_height="match_parent" />
</LinearLayout>
2、ListView实现
数组中的数据不能直接传递给ListView,我们需要通过适配器来完成。ArrayAdapter可以通过泛型来指定要适配的数据类型,ArrayAdapter有多个构造函数的重载,应该根据实际情况去选择。这里将泛型指定为String,然后在ArrayAdapte的构造函数中依次传入当前上下文、ListView子项id以及要适配的数据。注意:使用android.R.layout.simple_list_item_1作为子项布局id,这是一个Android内置的布局文件,里面只有一个TextView,可用于简单的显示一段文本。
public class ListViewActivity extends Activity {
private String[] data={"Apple","Banana","Orange","Red","Color","blue","yellow",
"Apple","Banana","Orange","Red","Color","blue","yellow"};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_listview); //设置布局
ArrayAdapter<String> adapter=new ArrayAdapter<String>(ListViewActivity.this,android.R.layout.simple_list_item_1,data);
ListView listView=findViewById(R.id.listview_1);
listView.setAdapter(adapter);
}
}
3、效果图
二、定制ListView的界面
1、自定义实体类:
//自定义类MyType
//name表示名字,imageId表示名字对应的图片的资源id
public class MyType {
private String name;
private int imageId;
public MyType(String name,int imageId){
this.name=name;
this.imageId=imageId;
}
public String getName()
{
return name;
}
public int getImageId()
{
return imageId;
}
}
2、自定义布局:
这里是图片+文字布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/mytype_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/mytype_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp" />
</LinearLayout>
3、自定义适配器:
MyTypeAdapter 重写了父类的一组构造方法,用于将上下文、ListView子项布局的id和数据传递进来。然后又重写了getView()方法,这个方法在每个子项被滑动到屏幕的时候会被调用。在getView()方法中使用getItem()方法获得当前项MyType的实例,然后用LayoutInflater为这个子项加载我们传入的布局。
public class MyTypeAdapter extends ArrayAdapter {
private int resourceId;
public MyTypeAdapter(Context context, int textViewResourceId, List<MyType>object)
{
super(context,textViewResourceId,object);
resourceId=textViewResourceId;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
MyType myType= (MyType) getItem(position); //获取当前项的MyType实例
View view= LayoutInflater.from(getContext()).inflate(resourceId,parent,false);//加载布局
//获取控件实例
TextView mytypeName=(TextView) view.findViewById(R.id.mytype_name);
ImageView mytypeImage=(ImageView)view.findViewById(R.id.mytype_image);
mytypeImage.setImageResource(myType.getImageId());
mytypeName.setText(myType.getName());
return view;
}
}
4、优化ListView运行效率
因为getvVew()中,每次都会将布局重新加载一遍,当ListView快速滚动时,就会成为性能瓶颈。
getView()方法中的参数convertView用于将之前加载好的布局进行缓存,以便可以重用。为了避免重复加载控件实例,可以借助一个自定义ViewHolder来对这部分进行优化
public class MyTypeAdapter extends ArrayAdapter {
private int resourceId;
public MyTypeAdapter(Context context, int textViewResourceId, List<MyType>object)
{
super(context,textViewResourceId,object);
resourceId=textViewResourceId;
}
//创建一个ViewHolder,用于对控件的实例进行缓存,提高性能
public class ViewHolder
{
public ImageView fruitImage;
public TextView fruitname;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
MyType myType= (MyType) getItem(position); //获取当前项的MyType实例
//convertView用于将之前加载好的布局进行缓存,提高性能
View view;
ViewHolder viewHolder;
if(convertView==null){
view= LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
viewHolder=new ViewHolder();
viewHolder.fruitImage=(ImageView)view.findViewById(R.id.mytype_image);
viewHolder.fruitname=(TextView) view.findViewById(R.id.mytype_name);
view.setTag(viewHolder); //将viewHolder存储在view中
}
else{
view=convertView;
viewHolder=(ViewHolder)view.getTag(); //重新获取ViewHolder
}
viewHolder.fruitImage.setImageResource(myType.getImageId());
viewHolder.fruitname.setText(myType.getName());
return view;
}
}
5、自定义ListView界面实现并设置ListView点击事件:
public class ListViewActivity extends Activity {
private List<MyType> fruitList=new ArrayList<>();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_listview); //设置布局
//自定义adapter
initFruits(); //初始化数据
MyTypeAdapter adapter=new MyTypeAdapter(ListViewActivity.this,R.layout.mytype_item,fruitList);
ListView listView=(ListView)findViewById(R.id.listview_1);
listView.setAdapter(adapter);
/*设置listview点击事件*/
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
MyType fruit=fruitList.get(position);
Toast.makeText(ListViewActivity.this, fruit.getName(), Toast.LENGTH_SHORT).show();
}
});
}
private void initFruits(){
for (int i=0;i<10;i++)
{
MyType first=new MyType("星空画具",R.drawable.first);
fruitList.add(first);
MyType second=new MyType("星空连体衣",R.drawable.second);
fruitList.add(second);
MyType three=new MyType("星空棉花",R.drawable.three);
fruitList.add(three);
MyType four=new MyType("星空奶瓶",R.drawable.four);
fruitList.add(four);
MyType five=new MyType("星空拼图",R.drawable.five);
fruitList.add(five);
MyType six=new MyType("星空温度计",R.drawable.six);
fruitList.add(six);
}
}
}
6、自定义界面效果图