ListView使用技巧-更新中

来源:互联网 发布:工业4.0软件 编辑:程序博客网 时间:2024/04/30 21:11

虽然在Android5.X中,RecyclerView在很多地方组件取代了ListView,但是ListView的使用依然是分广泛。

本博文将对以下两方面的内容进行介绍
1. ListView常用技巧
2. ListView常用拓展

具体代码请移步GitHub


ListView常用优化技巧

1. 使用ViewHolder模式提高效率

1. 使用ViewHolder模式提高效率
ViewHolder模式充分利用了ListView的视图缓存机制,避免了每次在getView()时重复的调用findViewById().
使用ViewHoder的步骤:
1. 在自定义的Adapter中定义一个内部类ViewHolder,并将Item布局中的控件作为成员变量
2. 接下来只要在getView()方法中通过视图缓存机制来重用以缓存即可。

public class MainMenuListAdapter extends BaseAdapter {    private List<MainMenuListItemBean> mDataList;    private Context mContext;    private LayoutInflater mInflate;    public MainMenuListAdapter(Context context, List<? extends Object> dataList) {        this.mContext = context;        this.mDataList = (List<MainMenuListItemBean>) dataList;        this.mInflate = LayoutInflater.from(context);    }    //数据源中的数据对象个数    @Override    public int getCount() {        return mDataList.size();    }    //指定位置处的数据源对象    @Override    public Object getItem(int position) {        return mDataList.get(position);    }    //数据源对象的Id,如果有的话    //如果数据源对象自己没有定义Id,则可以简单地返回其在数据源中的位置    @Override    public long getItemId(int position) {        return position;    }    //每当Android ListView需要显示一行时,它会调用此方法    @Override    public View getView(int position, View convertView, ViewGroup parent) {        ViewHolder holder = null;        //判断是否缓存        if (convertView == null) {            holder = new ViewHolder();            // 通过LayoutInflater实例化布局            convertView = mInflate.inflate(R.layout.activity_main_menu_list_item, null);            //获取用于显示内容的控件的引用            holder.idivpic = (ImageView) convertView.findViewById(R.id.id_iv_pic);            holder.idtvcontent = (TextView) convertView.findViewById(R.id.id_tv_content);            convertView.setTag(holder);        } else {            //通过tag找到缓存的布局            holder = (ViewHolder) convertView.getTag();        }        //依据位置提取相应的数据源对象        MainMenuListItemBean bean = mDataList.get(position);        //设置显示内容        holder.idivpic.setImageResource(R.drawable.flag_mark_blue);        holder.idtvcontent.setText(bean.getContent());        return convertView;    }    /**     * 创建一个内部类ViewHolder保存控件。只加载View的时候使用findViewById()方法。     * 使用View的setTag()方法保存ViewHolder。当convertView不为空的时候,直接取出来即可     */    public class ViewHolder {        public TextView idtvcontent;        public ImageView idivpic;        }    }

2. 设置项目间分割符

2.设置项目间分隔线

ListView各个项目之间,可以通过设置分隔线来进行区分,系统提供了dividerdividerHeight这两个属性来帮我们实现这一功能。
通过这两个属性可以控制他们之间的分隔线和分隔线的高度。
当然,分隔线不仅仅可以设置为一个颜色,也可以设置为图片资源,分隔线的使用代码如下:

     android:divider="@android:color/holo_green_light"     android:dividerHeight="3dp"

或者动态设置,必须先setDivider ,然后在setDiveiderHeight,否则不生效

  listView.setDivider(new ColorDrawable(Color.GREEN));  listView.setDividerHeight(3);

原因:
源码如下

public void setDivider(Drawable divider) {      if (divider != null) {          mDividerHeight = divider.getIntrinsicHeight();      } else {          mDividerHeight = 0;      }      mDivider = divider;      mDividerIsOpaque = divider == null || divider.getOpacity() == PixelFormat.OPAQUE;      requestLayout();      invalidate();  }  

注意:

if (divider != null) {      mDividerHeight = divider.getIntrinsicHeight(); 
public int getIntrinsicHeight() {      return -1;  }  

如果想要将分隔线设置为透明:

listView.setDivider(null);
或者
android:divider=”@null”

  case 1:// 设置项目间分隔线                LogUtils.d(position);                // 设置分隔线 ,必须先setDivider,然后setivederHeight                listView.setDivider(new ColorDrawable(Color.GREEN));                listView.setDividerHeight(3);                // 取消分隔线                // listView.setDivider(null);                showInfo();                break;

3. 隐藏ListView的滚动条

3.隐藏ListView的滚动条
默认的ListView在滚动时,在右边会显示滚动条,指定当前滚定的位置。我们可以通过scrollbars属性来控制ListView的滚动状态。特别的,当scrollbars设置为none时,ListView无论滚动还是不滚动,就都不会出现滚动条了。

 case 2:// 隐藏ListView的滚动条                LogUtils.d(position);                // false-一直都显示  true-不活动时隐藏,活动时显示                //listView.setScrollbarFadingEnabled(true);                //false 不活动的时候隐藏,活动的时候也隐藏  true-不活动时隐藏,活动时显示                listView.setVerticalScrollBarEnabled(false);                // 或者在xml中 android:scrollbars="none"  ---->  不活动的时候隐藏,活动的时候也隐藏                showInfo();                break;

4. 取消ListView的Item点击效果

4. 取消ListView的Item点击效果
当点击ListView的某一项Item时,系统默认会出现一个点击效果,在Android5.X上是一个波纹的效果,而在5.X以下是一个改变背景颜色的效果,但是我们可以通过修改listSelector属性来取消点击后的回馈效果。

android:listSelector="#00000000"

当然也可以是用Android系统自带的透明色来实现这个效果

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

或者在代码中

  listView.setSelector(new ColorDrawable(Color.TRANSPARENT));

5. 设置ListView需要显示在第几行

ListView以Item为单位进行显示,默认显示第一个Item,当需要指定具体的Item时,可以通过如下代码来实现

ListView.setSelection(N);

其中N就是要显示的第N个Item。

当然,这个方法类似于scrollTo,是瞬间完成的移动。

如果想实现平滑移动:

listView.smoothScrollBy(distance,duration);listView.smoothScrollBy(offset);listView.smoothScrollToPostion(index);

6. 动态修改ListView-notifyDataSetChanged

notifyDataSetChanged

mData.add("new");notifyDataSetChanged();

当修改了传递给Adapter的映射List之后,只需要通过调用Adapter的notifyDataSetChanged方法,通知ListView更改数据源即可完成对ListView的动态修改。

注意:在使用mAdapter.notifyDataSetChanged方法时,必须保证传进Adapter的数据List是同一个List而不能是其他对象,否则将无法实现改效果。

NotifyTest.java

import android.app.Activity;import android.os.Bundle;import android.view.View;import android.widget.ListView;import java.util.ArrayList;import java.util.List;public class NotifyTest extends Activity {    private List<String> mData;    private ListView mListView;    private NotifyAdapter mAdapter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.notify);        mData = new ArrayList<String>();        for (int i = 0; i < 20; i++) {            mData.add("" + i);        }        mListView = (ListView) findViewById(R.id.listView);        mAdapter = new NotifyAdapter(this, mData);        mListView.setAdapter(mAdapter);        for (int i = 0; i < mListView.getChildCount(); i++) {            View view = mListView.getChildAt(i);        }    }    public void btnAdd(View view) {        mData.add("new");        mAdapter.notifyDataSetChanged();        mListView.setSelection(mData.size() - 1);    }}

notify.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context=".MainActivity">    <ListView        android:id="@+id/listView"        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_alignParentStart="true"        android:layout_alignParentTop="true"        android:layout_weight="9"        android:fastScrollEnabled="true" />    <Button        android:id="@+id/button"        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_alignEnd="@+id/listView"        android:layout_alignParentBottom="true"        android:layout_alignParentStart="true"        android:layout_weight="1"        android:onClick="btnAdd"        android:text="Add" /></LinearLayout>

NotifyAdapter.java

import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.TextView;import java.util.List;public class NotifyAdapter extends BaseAdapter {    private List<String> mData;    private LayoutInflater mInflater;    public NotifyAdapter(Context context, List<String> data) {        this.mData = data;        mInflater = LayoutInflater.from(context);    }    @Override    public int getCount() {        return mData.size();    }    @Override    public Object getItem(int position) {        return mData.get(position);    }    @Override    public long getItemId(int position) {        return position;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {        ViewHolder holder = null;        // 判断是否缓存        if (convertView == null) {            holder = new ViewHolder();            // 通过LayoutInflater实例化布局            convertView = mInflater.inflate(R.layout.notify_item, null);            holder.img = (ImageView) convertView.findViewById(R.id.imageView);            holder.title = (TextView) convertView.findViewById(R.id.textView);            convertView.setTag(holder);        } else {            // 通过tag找到缓存的布局            holder = (ViewHolder) convertView.getTag();        }        // 设置布局中控件要显示的视图        holder.img.setBackgroundResource(R.drawable.ic_launcher);        holder.title.setText(mData.get(position));        return convertView;    }    public final class ViewHolder {        public ImageView img;        public TextView title;    }}

notify_item.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="horizontal">    <ImageView        android:id="@+id/imageView"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:src="@drawable/ic_launcher" />    <TextView        android:id="@+id/textView"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="Large Text"        android:textAppearance="?android:attr/textAppearanceLarge" /></LinearLayout>

7. 遍历ListView中所有的Item

ListView作为一个ViewGroup,为我们提供了操作子View的各种方法,最常见的就是通过getChildAt()来获取第i个子View,代码如下:

    for (int i = 0; i < mListView.getChildCount(); i++) {       View view = mListView.getChildAt(i);        }

8. 处理空ListView


9. ListView的滑动监听

ListView常用扩展

1. 具有弹性的ListView

2. 自动隐藏、显示布局的ListView

3. 聊天ListView

4. 动态改变ListView布局


1 0
原创粉丝点击