美文网首页
解析一个Github上的项目ListViewFilter之一

解析一个Github上的项目ListViewFilter之一

作者: 二七头头 | 来源:发表于2016-03-19 01:25 被阅读207次

    项目链接 in Github

    项目概要

    这是一个关于listview开发的项目,主要有以下特点:

    • 分组功能
    • 搜索功能
    • 附带类似iOS通讯录上的过滤索引条

    项目的运行界面如下:


    项目模块

    • 自定义ListView
    • 自定义BaseAdapter
    • 自定义左边的索引条
    • 顶部搜索框
    • 用于建立自定义View之间联系的相关接口

    代码解析

    BaseAdapter

    该Adapter的设计目的主要是实现ListView的分组功能和处理屏幕滚动事件。代码的解析如下:

    // Customized adaptor to populate data in PinnedHeaderListView
    
    public class PinnedHeaderAdapter extends BaseAdapter implements OnScrollListener, IPinnedHeader, Filterable {
    
    //定义代表listview中全局静态变量
    //@TYPE_ITEM代表ListView中用户输入的内容
    private static final int TYPE_ITEM = 0;
    //@TYPE_SECTION代表ListView中每个分组的标头
    private static final int TYPE_SECTION = 1;
    
    private static final int TYPE_MAX_COUNT = TYPE_SECTION + 1;
    //@mLayoutInflater用于动态载入组件
    LayoutInflater mLayoutInflater;
    //@mCurrentSectionPosition代表最顶部的标头在@mListItems中的位置
    int mCurrentSectionPosition = 0,
    //@mCurrentSectionPosition代表屏幕上第二个标头在@mListItems中的位置
     mNextSectionPostion = 0;
    
    // array list to store section positions存储标头位置的数组
    ArrayList<Integer> mListSectionPos;
    
    // array list to store list view data存储ListView内容的数组
    ArrayList<String> mListItems;
    
    // context object上下文
    Context mContext;
    
    //利用构造方法初始化全局变量
    public PinnedHeaderAdapter(Context context, ArrayList<String> listItems,ArrayList<Integer> listSectionPos) {
    
    this.mContext = context;
    
    this.mListItems = listItems;
    
    this.mListSectionPos = listSectionPos;
    
    mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    
    }
    
    //重写getCount以获得ListView中元素的数量
    @Override
    public int getCount() {
    
    return mListItems.size();
    
    }
    //ListView中的每个元素不是都可以选择和点击的,所以返回false。
    @Override
    public boolean areAllItemsEnabled() {
    
    return false;
    
    }
    //所有非标头元素都可以选择和点击
    @Override
    
    public boolean isEnabled(int position) {
    
    return !mListSectionPos.contains(position);
    
    }
    //获得ListView中元素的种类数量
    @Override
    
    public int getViewTypeCount() {
    
    return TYPE_MAX_COUNT;
    
    }
    //获取某个位置的视图类型
    @Override
    
    public int getItemViewType(int position) {
    
    return mListSectionPos.contains(position) ? TYPE_SECTION : TYPE_ITEM;
    
    }
    //获取ListView中某个位置的元素
    @Override
    
    public Object getItem(int position) {
    
    return mListItems.get(position);
    
    }
    //获取ListViw中某个位置的识别号
    @Override
    
    public long getItemId(int position) {
    
    return mListItems.get(position).hashCode();
    
    }
    //重写Adapter最终的方法getView(),用于显示ListView中视图的内容,其内容根据标头和用户输入的有效信息作出不同处理。其中ConVertView用于缓存在用户滚动屏幕后离开屏幕的子视图,因此不必在滚动的时候都重新加载试图布局,从而有利于提高ListView的运行效率。
    @Override
    
    public View getView(int position, View convertView, ViewGroup parent) {
    
    ViewHolder holder = null;
    
    if (convertView == null) {
    
    holder = new ViewHolder();
    
    int type = getItemViewType(position);
    
    switch (type) {
    
    case TYPE_ITEM:
    
    convertView = mLayoutInflater.inflate(R.layout.row_view, null);
    
    break;
    
    case TYPE_SECTION:
    
    convertView = mLayoutInflater.inflate(R.layout.section_row_view, null);
    
    break;
    
    }
    
    holder.textView = (TextView) convertView.findViewById(R.id.row_title);
    
    convertView.setTag(holder);
    
    } else {
    
    holder = (ViewHolder) convertView.getTag();
    
    }
    
    holder.textView.setText(mListItems.get(position).toString());
    
    return convertView;
    
    }
    
    //重新IPinnedHeader里的方法。不得不说的是,这个方法的参数@position其实指的是ListView中显示在第一行元素在数组@mListItem中的位置,这个可以从类IPinnedHeaderListView中知道。
    @Override
    
    public int getPinnedHeaderState(int position) {
    
    // hide pinned header when items count is zero OR position is less than
    
    // zero OR
    
    // there is already a header in list view
    //getCount()=0才是判断的重点。
    if (getCount() == 0 || position < 0 || mListSectionPos.indexOf(position) != -1) {
    
    return PINNED_HEADER_GONE;
    
    }
    
    // the header should get pushed up if the top item shown
    
    // is the last item in a section for a particular letter.
    
    mCurrentSectionPosition = getCurrentSectionPosition(position);
    
    mNextSectionPostion = getNextSectionPosition(mCurrentSectionPosition);
    
    if (mNextSectionPostion != -1 && position == mNextSectionPostion - 1) {
    
    return PINNED_HEADER_PUSHED_UP;
    
    }
    
    return PINNED_HEADER_VISIBLE;
    
    }
    //同样,@position是ListView中显示在第一行元素在数组@mListItem中的位置
    public int getCurrentSectionPosition(int position) {
    
    String listChar = mListItems.get(position).toString().substring(0, 1).toUpperCase(Locale.getDefault());
    
    return mListItems.indexOf(listChar);
    
    }
    //获取下个标头在ListView中的位置
    public int getNextSectionPosition(int currentSectionPosition) {
    
    int index = mListSectionPos.indexOf(currentSectionPosition);
    
    if ((index + 1) < mListSectionPos.size()) {
    
    return mListSectionPos.get(index + 1);
    
    }
    
    return mListSectionPos.get(index);
    
    }
    
    //用于屏幕滚动时,动态设置ListView可视的第一行的内容
    @Override
    
    public void configurePinnedHeader(View v, int position) {
    
    // set text in pinned header
    
    TextView header = (TextView) v;
    
    mCurrentSectionPosition = getCurrentSectionPosition(position);
    
    header.setText(mListItems.get(mCurrentSectionPosition));
    
    }
    
    @Override
    
    public void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {
    
    if (view instanceof PinnedHeaderListView) {
    
    ((PinnedHeaderListView) view).configureHeaderView(firstVisibleItem);
    
    }
    
    }
    
    @Override
    
    public void onScrollStateChanged(AbsListView view, int scrollState) {
    
    // TODO Auto-generated method stub
    
    }
    
    //获取过滤器
    @Override
    
    public Filter getFilter() {
    
    return ((MainActivity) mContext).new ListFilter();
    
    }
    //用于提升ListView的运行效率
    public static class ViewHolder {
    
    public TextView textView;
    
    }
    
    }
    

    待完成的事:由于该类中的方法参数中的position很多都是指ListView显示在屏幕中第一行的位置,因此可以尝试进一步简化。

    相关文章

      网友评论

          本文标题:解析一个Github上的项目ListViewFilter之一

          本文链接:https://www.haomeiwen.com/subject/kvrhlttx.html