ListView学习(一)

使用 ViewHolder 的模式提高ListView的效率

ViewHolder模式充分利用了ListView的缓存机制

MyListViewAdapter

    public class MyListViewAdapter extends BaseAdapter {

    private List<String> mData;
    private LayoutInflater mInflater;

    public MyListViewAdapter(Context context,List<String> data){
        this.mData = data;
        this.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();

            //实例化布局
            convertView = mInflater.inflate(R.layout.viewholder_item,null);
            holder.img = (ImageView) convertView.findViewById(R.id.imageView);
            holder.title = (TextView) convertView.findViewById(R.id.textView);
            convertView.setTag(holder);
        }else{
            holder = (ViewHolder) convertView.getTag();
        }
        //填充数据
        holder.title.setText(mData.get(position));
        return convertView;
    }

    public final class ViewHolder{
        public ImageView img;
        public TextView title;
    }
}

vieholder_item


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="@mipmap/ic_launcher"/>

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:text="title"/>

</LinearLayout>

Activity


public class MainActivity extends AppCompatActivity {

    private ListView mListView;
    private MyListViewAdapter mAdapter;
    private List<String> mData;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mData = new ArrayList<>();
        for(int i=0;i<20;i++){
            mData.add("Title"+i);
        }

        mAdapter = new MyListViewAdapter(this,mData);
        mListView = (ListView) findViewById(R.id.listView);
        mListView.setAdapter(mAdapter);
    }
}

效果图:

ListView的缓存机制

ListView设置项目之间的分隔线

隐藏ListView的滚动条

默认的ListView在滚动的时候是有滚动条的,我们可以设置 scrollbars 属性控制ListView的滚动条状态。

android:scrollbars=”none”

取消ListView的Item点击效果

当点击ListView中的一项时,系统默认会给一个点击效果,Android 5.X上是一个波纹效果,在这个版本下面则是一个改变背景颜色的效果。我们可以通过修改listSelector属性来取消掉点击后的回馈效果

android:listSelector=”#000000000”

我们也可以使用Android自带的透明色来实现这个效果

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

设置ListView需要显示在第几项

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

listView.setSelection(position);

当然,这个方法类似 scrollTo ,是瞬间完成的移动。除此之外,我们可以通过如下代码实现平滑移动:

mListView.smoothScrollBy(distance,duration); distance 是像素、duration 是持续时间

mListView.smoothScrollByOffset(offset); 是偏移多少个item,正值向上滚动,负值向下滚动

mListView.smoothScrollToPosition(index); 这个方法会将 下标为 index 的 item 条目滚动到屏幕内,如果该条目已经在屏幕内就不会滚动

以上三个方法需要通过 post 方法去更新,如果我们直接去更新的话,listView 可能刚添加好条目,ui还在更新中,所以我们可以给 listView 一个延迟去更新


mListView.postDelayed(new Runnable{

    mListView.smoothScrollBy(distance,duration);
    mListView.smoothScrollByOffset(offset);
    mListView.smoothScrollToPosition(index);

},1000);


mListView.post(new Runnable{

    mListView.smoothScrollBy(distance,duration);
    mListView.smoothScrollByOffset(offset);
    mListView.smoothScrollToPosition(index);

});

动态修改ListView

使用如下方法需要注意的是传递到 Adapter 中的集合必须是同一个集合


mData.add("New");
mAdapter.notifyDataSetChanged();

另外这个方法会导致界面的重新绘制,虽然比较重新创建 Adapter 和重新 set比起来工作量要小的多,但当我们需要的只是更新某一条数据,就可以通过自己创建的方法实现:


public MyAdapter extends BaseAdapter{

    ..............

   /**
     * @param position 要更新条目的位置
     * @param listView 要更新的ListView
     */
    public void updateView(int position,ListView listView){
        int visibleFirstPosition = listView.getFirstVisiblePosition();
        int visibleLastPosition = listView.getLastVisiblePosition();

        //如果该条目是正在显示的话就找到改条目并且更新数据
        if(position >= visibleFirstPosition && position <= visibleLastPosition){
            View view = listView.getChildAt(position - visibleFirstPosition);
            ViewHolder viewHolder = (ViewHolder) view.getTag();

            viewHolder.title.setText("new");

        }else{//如果要更新的条目不是在屏幕中显示的话直接更新下数据源即可
            mData.set(position,"new");
        }
    }


    ..........

}

需要注意的是:listView 的 getChildAt() 是对于 listView 目前可见范围内的条目,就是正在屏幕上展示的哪些条目

有的同学可能调试的出现没有更新的结果是因为 listView 还没有初始化完毕, visibleLastPosition 会返回-1,故而需要一定的延时策略,正常情况下也是在 listView 加载完毕后用户才需要更新某个条目

### 遍历 LivtView 的 item

getChildCount() 获取的是屏幕上展示的 item 的个数

getCount() 获取的是 listView 中的所有 item 的个数

getChildAt(position) 获取的是屏幕上展示的 item 中的某一个下标是从 0 开始的

“`java

for(int i=0;i < mListView.getChildCount();i++){
View view = mListView.getChildAt(i);//其实这个就是convertView
}

“`

### 处理空的 ListView

ListView 用于展示列表数据,但当列表中没有数据的时候, ListView 不会显示任何的数据或提示,为了更好的用户体验,这里应该给以无数据的显示。ListView 提供了一个方法——setEmptyView(),通过这个方法我们可以给 ListView 设置一个在空数据下显示的默认提示。

但是 setEmptyView()是有一些限制的,就是设置的 View 必须在当前的 View hierarchy中,亦即这个 View 需要被 add 到当前 View hierarchy 的一个节点上面,如果没有添加到节点上的话,调用 setEmpty()方法是没有任何效果的。

“`java

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值