ListView
由于屏幕的有限,若是想看到全部内容则需要把屏幕外的数据滚到屏幕内,同时已经在屏幕上的信息会滚动出屏幕外。ListView就是可以实现这种功能的控件。
1、简单的用法
先在布局文件里添加一个ListView控件;
然后在Mainactivity中将数据与控件联系起来。首先呢是使用ArrayAdapter泛型指定数据类型是String,然后在ArrayAdapter构造函数里依次传入上下文,以及ListView子项布局,以及要适配的数据(可以来自数据库,简单定义可以是一个数组)。其中我们的子项布局使用android.R.layout.simple_list_item_1(这是一个Android内置的布局文件,里面只有一个简单的TextView显示数据)。
最后,还需要调用ListView的setAdapter()方法,将搭建好的适配器对象传递进去。
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);
ArrayAdapter<String> adapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1,data);
ListView listView=findViewById(R.id.list_view);
listView.setAdapter(adapter);
}
}
2、定制ListView的界面
实现一组能实现图片的ListView。
1)首先定义一个水果类,创建构造函数。
public class Fruit {
private String name;
private int imageid;
public Fruit(String name,int imageid){
this.name=name;
this.imageid=imageid;
}
public String getName(){
return name;
}
public int getImageid(){
return imageid;
}
}
2)然后,要为ListView的子项指定一个我们自定义的布局,在layout目录下新建一个fruit_item.xml。一个imageview显示水果图片,一个显示水果名称。
<ImageView
android:layout_width="80dp"
android:layout_height="80dp"
android:scaleType="fitStart"
android:maxHeight="30dp"
android:maxWidth="30dp"
android:id="@+id/fruit_image"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/fruit_name"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"/>
3)创建一个自定义的适配器FruitAdapter,这个适配器继承自ArrayAdapter,并将泛型指定为Fruit类。在FruitAdapter中重写构造函数和getview方法。getView方法在每个子项被滚动到屏幕内的时候会被调用,首先通过getItem()方法得到当前Fruit实例,然后会使用LayoutInflate来为这个子项加载我们传入的布局。
在LayoutInflate的inflate()方法接收三个参数,第三个是false表示只让我们在父布局中声明的layout属性生效,但不会为这个view添加父布局,因为一旦view有了父布局之后,他就不能再添加到ListView中。调用View的findViewById()方法分别获得Imageview和TextView的实例,并分别调用他们的setImageResource()和setText()方法来显示图片和文字,最后将布局返回。
public class FruitAdapter extends ArrayAdapter<Fruit>{
private int resoureid;
//重写父类的一组构造函数 将上下文和ListView的子项布局和数据传递进来。
public FruitAdapter(Context context, int textViewResouceid, List<Fruit> objects){
super(context,textViewResouceid,objects);
resoureid=textViewResouceid;
}
//重写getview方法 这个方法在每个子项滚动到屏幕内的时候会被调用
public View getView(int position, View convertView, ViewGroup parent){
Fruit fruit=getItem(position);//获取当前项的Fruit实例
View view=LayoutInflater.from(getContext()).inflate(resoureid,parent,false);
//调用View的findViewById()方法分别获得Imageview和TextView的实例,并分别调用他们的setImageResource()和setText()方法来显示图片和文字,最后将布局返回。
ImageView fruitImage=view.findViewById(R.id.fruit_image);
TextView fruitname=view.findViewById(R.id.fruit_name);
fruitImage.setImageResource(fruit.getImageid());
fruitname.setText(fruit.getName());
return view;
}
}
4)接下来初始化水果的数据,在Fruit类的构造函数中将水果的名字和对应的图片的ID传入,然后把建好的对象添加进水果列表中。利用for循环是来添加两遍,让数据占满整个屏幕实现滚动的效果。接着在on
creat()方法中创建了FruitAdapter()对象,并将他作为适配器传给ListView。
initFruits();//初始化水果
//创建适配器
FruitAdapter adapter=new FruitAdapter(MainActivity.this,R.layout.fruit_item,fruitList);
ListView listView=findViewById(R.id.list_view);
listView.setAdapter(adapter);
private void initFruits(){
for(int i=0;i<2;i++){
Fruit apple=new Fruit("Apple",R.drawable.apple);
fruitList.add(apple);
}//其余水果类似
效果如图:
3、提升ListView的运行效率
因为在FruitAdapter的getview方法中,每次都是将布局重新加载一遍,当ListView快速滚动时会成为性能的瓶颈。在getview方法中还有一个conerView参数,这个参数将之前加载好的布局缓存,可以对其判断,若是null,则使用LayoutInflater加载布局,不为null则直接对convertView进行重用。修改FruitAdapter中的代码。
View view;
if(convertView==null){
view=LayoutInflater.from(getContext()).inflate(resoureid,parent,false);
}else {
view=convertView;
}
4、ListView的点击事件
利用setOnItemClickListener()方法为ListView注册一个监听器,用户点击任何一个子项时回调onItemClick()方法,根据position判断是哪一个子项然后输出。在MainActivity里修改。
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();
}
});