深入ListView
16lz
2022-08-04
深入ListView
我们接着上一篇博客,对ListView进行更加深入的了解。
属性
android:cacheColorHint=”@color/white” 设置ListView滚动时的背景色
android:divider=”@color/red” 设置ListView分割线的颜色
android:dividerHeight=”1dp” 设置ListView分割线的高度
设置点击列表的背景
更改listview点击背景与更改Button点击背景和RadioButton选择图标的方法类似。
①在drawable文件夹下新建xml文档list_background.xml
<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android" > <item android:drawable="@color/red" android:state_pressed="true"/> <item android:drawable="@color/white"/></selector>
②在自定义的布局中加入属性background
android:background="@drawable/list_background"
提升ListView的运行效率
- 在上一篇博客中,StudentAdapter的getView()方法,每次都将布局重新加载了一遍,当ListView快速滚动的时候这就会成为性能的瓶颈。我们注意到getView()方法中还有一个参数convertView,这个参数用于将之前加载好的布局进行缓存,以便之后可以进行重用。
我们在getView()方法中进行了判断,如果convertView为空,则使用inflater去加载布局,如果不为空则直接对convertView进行重用。 - 我们每次在getView()方法中还是会调用View的findViewById()方法来获取一次控件的实例。此时可以借助一个ViewHolder来对这部分性能进行优化。
新增一个内部类ViewHolder,用于对控件的实例进行缓存。当convertView为空,创建一个ViewHolder对象,并将控件的实例都存放在ViewHolder里,然后调用View的setTag()方法,将ViewHolder对象存储在View中。当convertView不为空时则调用View的getTag()方法,将ViewHolder重新取出。
优化后的代码:
@Overridepublic View getView(int position, View convertView, ViewGroup parent) { Stuent student = arraylist.get(position); View view; ViewHolder viewHolder; if (convertView == null) { view = inflater.inflate(R.layout.simpleadapter_layout, null); viewHolder=new ViewHolder(); viewHolder.image = (ImageView) view.findViewById(R.id.imageview); viewHolder.textview_name = (TextView) view.findViewById(R.id.textview_name); viewHolder.textview_age = (TextView) view.findViewById(R.id.textview_age); viewHolder.textview_sex = (TextView) view.findViewById(R.id.textview_sex); viewHolder.textview_hobby = (TextView) view.findViewById(R.id.textview_hobby); view.setTag(viewHolder);//将viewHolder存储在view中 }else{ view=convertView; viewHolder=(ViewHolder) view.getTag();//重新获取viewHolder } viewHolder.textview_name.setText(student.getName()); viewHolder.textview_age.setText(student.getAge()); viewHolder.textview_sex.setText(student.getSex()); viewHolder.textview_hobby.setText(student.getHobby()); viewHolder.image.setImageResource(student.getImage()); return view;}class ViewHolder{ ImageView image; TextView textview_name; TextView textview_age; TextView textview_sex; TextView textview_hobby;}
ListView其他常见的用法
在ListView加入其他点击控件
当我们在ListView中加入了其他的点击控件,如CheckBox,Button,RadioButton等,就会抢夺ListView的焦点,这时我们点击ListView就没有反应。
我们有两种办法可以解决这个问题:
①在ListView中设置屏蔽子控件抢夺ListView的焦点
android:descendantFocusability="blocksDescendants"
②在子控件本身设置焦点属性为false。
android:focusable="false"
添加HeaderView和FooterView
- 首先我们要新建HeaderView或FooterView的布局xml文件
- 然后用LayoutInflater加载布局,生成View对象
- 最后调用addHeaderView()或addFooterView(),传入View对象即可。
注意:当我们在ListView中添加了HeaderView之后,使用ListView点击事件时,ListView中item的索引要减1。
综合的代码示例
定义一个实体类 Fruit
public class Fruit { private int image; private String name; private boolean isChecked; public Fruit(int image, String name) { this.image = image; this.name = name; } public int getImage() { return image; } public void setImage(int image) { this.image = image; } public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean isChecked() { return isChecked; } public void setChecked(boolean isChecked) { this.isChecked = isChecked; } }
为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" android:orientation="horizontal" > <CheckBox android:id="@+id/checkbox" android:layout_width="wrap_content" android:layout_height="wrap_content" android:focusable="false" android:text="选择水果"/> <ImageView android:id="@+id/fruit" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:id="@+id/textview" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout>
自定义适配器FruitAdapter.java
mport java.util.ArrayList;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.CheckBox;import android.widget.CompoundButton;import android.widget.CompoundButton.OnCheckedChangeListener;import android.widget.ImageView;import android.widget.TextView;public class FruitAdapter extends BaseAdapter { private LayoutInflater inflater; private ArrayList<Fruit> list; public FruitAdapter(LayoutInflater inflater, ArrayList<Fruit> list) { this.inflater = inflater; this.list = list; } /** * 全选 */ public void checkAll() { for (int i = 0; i < list.size(); i++) { list.get(i).setChecked(true); } notifyDataSetChanged(); } /** * 反选 */ public void reverse() { for (int i = 0; i < list.size(); i++) { selectItem(i); } } /** * 点击ListView可以勾选住CheckBox * * @param position 当前ListView的位置 */ public void selectItem(int position) { boolean isChecked = list.get(position).isChecked(); isChecked = !isChecked; list.get(position).setChecked(isChecked); notifyDataSetChanged();// 刷新界面 } @Override public int getCount() { return list.size(); } @Override public Object getItem(int arg0) { return arg0; } @Override public long getItemId(int arg0) { return arg0; } @Override public View getView(final int position, View convertView, ViewGroup arg2) { Fruit fruit = list.get(position); View view; ViewHolder viewHolder; if (convertView == null) { view = inflater.inflate(R.layout.fruit_layout, null); viewHolder = new ViewHolder(); viewHolder.checkbox = (CheckBox) view.findViewById(R.id.checkbox); viewHolder.image = (ImageView) view.findViewById(R.id.fruit); viewHolder.name = (TextView) view.findViewById(R.id.textview); view.setTag(viewHolder); } else { view = convertView; viewHolder = (ViewHolder) view.getTag(); } viewHolder.image.setImageResource(fruit.getImage()); viewHolder.name.setText(fruit.getName()); viewHolder.checkbox .setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { list.get(position).setChecked(isChecked);//如果勾选,将该项设为true } }); viewHolder.checkbox.setChecked(fruit.isChecked());//将ViewHolder中的实例重新设置为false return view; } class ViewHolder { CheckBox checkbox; ImageView image; TextView name; }}
HeaderView和FooterView的布局文件
<?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" android:orientation="vertical" > <Button android:id="@+id/button_quan" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="全选"/></LinearLayout>
<?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" android:orientation="vertical" > <Button android:id="@+id/button_fan" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="反选"/></LinearLayout>
MainActivity
import java.util.ArrayList;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.view.View.OnClickListener;import android.widget.AdapterView;import android.widget.Button;import android.widget.Toast;import android.widget.AdapterView.OnItemClickListener;import android.widget.ListView;import android.app.Activity;public class MainActivity extends Activity { private LayoutInflater inflater; private FruitAdapter adapter; private ArrayList<Fruit> list; private View fruitHeaderView; private View fruitFooterView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); list = new ArrayList<Fruit>(); for (int i = 0; i < 5; i++) { Fruit apple = new Fruit(R.drawable.apple, "苹果"); Fruit banana = new Fruit(R.drawable.banana, "香蕉"); Fruit grape = new Fruit(R.drawable.grape, "葡萄"); Fruit strawberry = new Fruit(R.drawable.strawberry, "草莓"); list.add(apple); list.add(banana); list.add(grape); list.add(strawberry); } inflater = getLayoutInflater(); adapter = new FruitAdapter(inflater, list); ListView listView = (ListView) findViewById(R.id.listview_fruit); fruitHeaderView = inflater.inflate(R.layout.fruit_header, null); listView.addHeaderView(fruitHeaderView); Button button_quan = (Button) fruitHeaderView .findViewById(R.id.button_quan); button_quan.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { adapter.checkAll();// 全选 } }); fruitFooterView = inflater.inflate(R.layout.fruit_footer, null); listView.addFooterView(fruitFooterView); Button button_fan = (Button) fruitFooterView .findViewById(R.id.button_fan); button_fan.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { adapter.reverse();// 反选 } }); listView.setAdapter(adapter); //点击listview,勾选中当前checkbox listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View view, int position, long id) { // 因为加了HeaderView,所以索引要减1 adapter.selectItem(position - 1);// 调用点击lsitview选择checkbox的方法 Toast.makeText(MainActivity.this, "选择的水果为:" + list.get(position - 1).getName(), Toast.LENGTH_SHORT).show(); } }); }}
运行结果:
点击ListView,会勾选CheckBox
点击全选,则全部选中
点击反选,则去掉之前选中的其余部分
更多相关文章
- 浅谈Java中Collections.sort对List排序的两种方法
- Python list sort方法的具体使用
- python list.sort()根据多个关键字排序的方法实现
- android上一些方法的区别和用法的注意事项
- 三、安卓UI学习(1)
- Android(安卓)环境搭建
- android实现字体闪烁动画的方法
- android studio调试c/c++代码
- Android中dispatchDraw分析