ListView相关知识点

来源:互联网 发布:python中的join函数 编辑:程序博客网 时间:2024/06/06 21:06

(1)BaseAdapterArrayAdapter的区别,应用场合区别。

个人理解:但凡需求需要重写ArrayAdaptergetView方法的。都不如用BaseAdapter简洁(注意不是BaseAdapter更好,要分场合,如果ListView的内容很多条,好几十条,上百条,据说用ArrayAdapter更好,没看源码。).

如果能MyExtendsArrayAdaptermAdapter=

newMyExtendsArrayAdapter(this,R.layout.simple_list_item_1,data);

如果能用系统的,而不是自定义的View。一步到位的,就优先用ArrayAdapter.

而且用BaseAdapter更省资源,因为ArrayAdapter继承于BaseAdapter.

如果ListView,GridView中的part,也就是自定义View涉及到的组件比较多,比较复杂的时候。用ArrayAdapter层次感个人感觉更好点。用BaseAdapter也可以。

Publicclass TestAdapter extends BaseAdapter{

//在构造方法中传入你需要的参数,自己随意定义类型和个数。

publicTestAdapter(x1,x2,x3....)

{

.

}

//继承BaseAdapter需要重写四个方法。比较重要的是getCount(),get

Publicint getCount(){

returnnum;//ListView,GridView等的内容的个数。num<=内容的个数。小于的话就显示不全

}

publicobject getItem(int positon){

//getItem方法不是在Baseadapter类中被调用的,而是在Adapterview.getItemAtPosition(position) 中被调用的。getItemAtPosition(position)是在setOnItemClickListenersetOnItemLongClickListenersetOnItemSelectedListener的点击选择处理事件中方便地调用来获取当前行数据的。

returnpositon;

}

publiclong getItemId(int position){

//该方法的返回值决定position处的列表项的ID,某些方法(如onclicklisteneronclick方法)有id这个参数,而这个id参数就是取决于getItemId()这个返回值的。如:publicvoid onItemClick(AdapterView<?> parent, View view,intposition, longid) 

returnposition;

}

publicView getView(int position,ViewconvertView,ViewGroup parent){

//根据构造方法传入的参数来获取到ListView,GridView中的内容。并根据positon的不同。用switch(position)来给每个内容赋予不同的属性。最后返回你的自定义View就可以了。

returnurView;

}

}

(2)ListView添加页眉,页脚

添加页脚:addFooterView

添加页眉:addHeaderView

方法两种:

//添加的view要从一个xml文件中解析出来,而不是当前的xml文件中的一个组件。

LayoutInflatermInflater=getLayoutInflater();

ViewmView=mInflater.inflate(R.layout.footer, null);

//两个方法的区别,前一种是可以选中的,后一种把boolean设置成false,就表示不可以选中。

mListView.addFooterView(mView);

mListView.addFooterView(mView,null,false);

//添加页眉页脚要在setAdapter

mListView.setAdapter(adapter);

//因为是添加到listView中,所以页眉页脚相当于listview的一部分,是可以跟随手指一起滑动的。

而且会影响到listViewitemposition。这个在处理点击事件时要注意一下,而且listview.getCount()也会发生变化。详细用到时候再深究

(3)缓存的使用ListViewconvertViewViewHolder,优化效率

View类的setTaggetTag

源码如下:

protectedObjectmTag;

publicObject getTag() {

returnmTag;

}

publicvoidsetTag(finalObject tag) {

mTag= tag;

}

说白了就是存取一个任意对象(因为Object是所有类的父类)。
为什么是final Object tag,final的意义是什么?
在方法参数前面加final关键字就是为了防止数据在方法体重被修改。 
主要分为两种情况:第一,用final修饰基本数据类型;第二,用final修饰引用数据类型。 
第一种情况,修饰基本数据类型,这时参数的值在方法体内是不能被修改的,即不能被重新赋值。否则编译就不通过。 
第二种情况,修饰引用类型。这时参数变量所引用的对象是不能被改变的。但是对于引用数据类型,如果修改其属性的话是完全可以的。 
所以,final这个关键字,想用的话就用基本数据类型,还是很有作用的。
比如下例中ViewHolder类对象给到View中的mTag,那么View中是不能出现mTag=viewHolder2.(也就是getView中不能出现view.setTag(viewHolder2),因为之前已经view.setTag(viewHolder)了,此时mTag已经是一个final对象了,不能第二次赋值或改变引用),但是view中是可以对mTag也就是viewHolder对象的属性进行操作的,比如mTag. fruitImage=xxx;(因为这样是没改变mTag这个final对象的引用的)。
说白了这么设计原因有个原因就是防止外面多次调用view.setTag方法。
当然,也考虑到多个参数的保存和获取。
   public void setTag(int key, final Object tag) 
这个方法是用来存多个对象的,key要求唯一,需要在res/values xml文件<item type="id" name="tag_first"> 
引用是R.id.tag_first.

详细怎么用回头用到的时候再深究。

publicclass FruitAdapter extends ArrayAdapter<Fruit> {

......

@Override

publicView getView(int position, View convertView,ViewGroup parent) {

Fruitfruit = getItem(position);

Viewview;

ViewHolderviewHolder;

if(convertView == null) {

view= LayoutInflater.from(getContext()).inflate(resourceId, null);

viewHolder= new ViewHolder();

viewHolder.fruitImage= (ImageView) view.findViewById

(R.id.fruit_image);

viewHolder.fruitName= (TextView) view.findViewById

(R.id.fruit_name);

view.setTag(viewHolder);//ViewHolder存储在View

}else {

view= convertView;

viewHolder= (ViewHolder) view.getTag(); // 重新获取ViewHolder,注意类型要转换

}

viewHolder.fruitImage.setImageResource(fruit.getImageId());

viewHolder.fruitName.setText(fruit.getName());

returnview;

}

classViewHolder {

ImageViewfruitImage;

TextViewfruitName;

}

}

因为在FruitAdaptergetView()方法中每次都将布局重新加载了一遍,并且通过findViewById()方法来获取控件实例。

优化后,布局之加载一次,获取控件实例也只进行一次。以后每次就是view.setText()api来反复修改控件实例的属性。ViewHolder类是自己创建的内部类。

(4)屏蔽掉ListViewItem的点击效果

xml文件中ListView控件增加如下属性。

android:listSelector="@android:color/transparent"

这样ListViewItem依然可以响应点击事件,但是没有点击效果。

(5)ListView小技巧

设置单项高度

android:height是无效的。

正确的做法是在itemlayout文件中,给item设定minHeight

隐藏ListView每个Item的分割线
ListView中每个Item项之间都有分割线,设置Android:footerDividersEnabled表示是否显示分割线,此属性默认为true
1.不显示分割线只要在ListView控件中添加android:footerDividersEnabled="false"即可。
<ListView
android:id="@+id/local_groups_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"   
android:footerDividersEnabled="false"/>
改变分割线颜色和宽度 
2.改变ListView的分割线颜色和宽度,需要在布局中定义android:dividerandroid:dividerHeight属性。
<ListView android:id="@+id/local_groups_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="@color/divider_color"
android:dividerHeight="1px"/>  
自定义分割线(主要是控制分割线的左右padding
创建分割线的布局文件:
list_item_divider.xml
<?xmlversion="1.0" encoding="UTF-8"?> 
<insetxmlns:android="http://schemas.android.com/apk/res/android"   
android:insetLeft="15dp" 
android:insetRight="15dp"
android:drawable="@color/line_gray">
</inset>
listviewdivider属性中引用这个布局
<ListView 
android:id="@+id/listView1"   
android:divider="@drawable/list_item_divider"    
android:dividerHeight="1px"   
android:layout_width="match_parent"  
android:layout_height="wrap_content"/>

(6)ListView部分属性

可以做到消除上下拖动的阴影,自定义分割线高度,宽度,颜色(or图片)。自定义item选中的样式,也可以设置为透明,就看不到点击效果,但是依然响应事件。

android:fadingEdge

上边和下边有黑色的阴影android:fadingEdge="none"设置后没有阴影了。

android:divider

android:dividerHeight

android:listSelector="@color/pink"listView item 选中时的颜色。默认为橙黄底色。

android:cacheColorHint

如果你只是换背景的颜色的话,可以直接指定android:cacheColorHint为你所要的颜色;如果你是用图片做背景的话,那也只要将android:cacheColorHint指定为透明(#00000000)就可以了,当然为了美化是要牺牲一些效率的

(7)ListViewsetOnItemLongClickListenersetOnItemClickListener冲突

Item长按后,拿开手指依然会触发Item单击事件。

解决方法:setOnItemLongClickListenerreturnfalse(默认)修改成returntrue.

(8)GridView,ListViewandroid:descendantFocusability属性

android:descendantFocusability=“xxx”

xxx可以为:

beforeDescendantsviewgroup会优先其子类控件而获取到焦点

afterDescendantsviewgroup只有当其子类控件不需要获取焦点时才获取焦点

blocksDescendantsviewgroup会覆盖子类控件而直接获得焦点

项目中的listview不仅仅是简单的文字,常常需要自己定义listview,自己的Adapter去继承BaseAdapter,在adapter中按照需求进行编写,问题就出现了,可能会发生点击每一个item的时候没有反应,无法获取的焦点。原因多半是由于在你自己定义的Item中存在诸如ImageButtonButtonCheckBox等子控件(也可以说是Button或者Checkable的子类控件),此时这些子控件会将焦点获取到,所以常常当点击item时变化的是子控件,item本身的点击没有响应。

找时间写个demo三个都试试。一般应该第一个和第三个用的多。应该就是与事件分发有关,之前解决过GridView的点击问题的。

实测,这个属性并不是写在listView控件中的,而是ListView对应的item.xml的容器中的。切记

(9)setTextFilterEnabled

AbsListView.setTextFilterEnabled(true);

这个方法的作用是用来过滤选项的.

例如在软键盘上打出一个a,则会过滤掉除了a开头的所有选项.


原创粉丝点击