现如今的andorid应用早已离不开listView的使用,但是ListView可以说是所有基础控件中比较复杂和繁琐的控件了。今天花了一天的时间来学习了listView的基础知识和最简单的使用。
使用ListView的第一步,新建一个layout页面,拖入一个ListView控件,并设置长宽为match_parent。设置id为list_text。
2、新建一个对应页面的java文件。
3、新建一个item布局文件。用来设置每个item的布局。未来方便起见,在这里我就使用一个最基础的图片加文字类型布局。之后新建一个水果fruit类,用于存放数据,同时设置好get和set方法。
public class Fruit { String name; int imageID; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getImageID() { return imageID; } public void setImageID(int imageID) { this.imageID = imageID; } public Fruit(String name, int imageID){ this.name = name; this.imageID = imageID; } }
4、接下来,我们需要设置一个适配器用来储存这个界面的布局。我使用的是ArrayAdapter适配器。
public View getView(int position, View convertView, ViewGroup parent){ Fruit fruit = getItem(position); View view = LayoutInflater.from(getContext()).inflate(ResourceID,parent,false); ImageView fruitImage = view.findViewById(R.id.fruitImage); TextView fruitName = view.findViewById(R.id.fruitName); fruitImage.setImageResource(fruit.getImageID()); fruitName.setText(fruit.getName()); return view; }
但是这样的ListView执行效率并不高。我们每次创建一个item都会执行一边getView的所有代码,那么有什么办法可以解决呢?
5、写好适配器后,我们需要在ListViewActivity中对适配器进行调用。
public class ListViewActivity extends AppCompatActivity { private List<Fruit> fruitList = new ArrayList<>(); @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.listview_text); initFruit(); FruitAdapt adapt = new FruitAdapt(ListViewActivity.this,R.layout.fruit_layout,fruitList); ListView listView = findViewById(R.id.list_text); listView.setAdapter(adapt); } private void initFruit(){ for (int i=0;i<20;i++){ Fruit fruit = new Fruit("fruit"+i,R.mipmap.ic_launcher); fruitList.add(fruit); } } }
绑定好适配器后,即可运行程序啦。
6、ListView的优化。
我们能在getView的构造函数中有convertView这个参数,这个参数即是缓存布局的参数。没有调用convertView时,每次刷新都会执行一次getView方法,拖慢了运行效率。在getView方法中用if判断是否为空,空则创建fruit对象,否则直接调用convertView。
这之后,虽然已经可以不用重复调用布局,但是每次执行时依然要重复调用finviewbyid的方法啦获取控件实例,所以我们新建了一个viewHolder类来存储控件实例。用setTag的方法来储存,再用getTag方法在调用。
public class FruitAdapt extends ArrayAdapter<Fruit> { private int ResourceID; public FruitAdapt(@NonNull Context context, int textViewResourceId, @NonNull List<Fruit> objects) { super(context, textViewResourceId, objects); ResourceID = textViewResourceId; } /** * * @param position 传入ListView主界面的context * @param convertView 用于缓存View布局,当view多次调用时,只需调用缓存即可 * @param parent 传入listView * @return 返回一个view布局 */ public View getView(int position, View convertView, ViewGroup parent){ Fruit fruit = getItem(position); 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.fruitImage); viewHolder.fruitName = (TextView) view.findViewById(R.id.fruitName); view.setTag(viewHolder); //用setTag方法储存viewHoder }else { view = convertView; viewHolder =(ViewHolder) view.getTag(); } viewHolder.fruitImage.setImageResource(fruit.getImageID()); viewHolder.fruitName.setText(fruit.getName()); return view; } class ViewHolder{ ImageView fruitImage; TextView fruitName; } }
7、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(ListViewActivity.this, fruit.getName(), Toast.LENGTH_SHORT).show(); } });