Android通讯录、城市选择器列表的实现


首先附上一张效果图;

Android通讯录、城市选择器列表的实现_第1张图片

主要功能介绍:

最顶部始终显示一个当前的分组,并且当下一个分组即将完全“推”上去上一个分组、或者下一个分组即将被“拉”下来的时候,最顶部的view会有一个退出和进入的动画效果;

列表的顶部是一个GridView,可对其进行另外的定制,比如显示热门的城市、热门的商品等效果;

对列表的图片加载进行了优化、加入了磁盘缓存、内存缓存、图片压缩、以及列表快速的大量的滑动过程中进行了图片加载的优化,解决列表卡顿的问题;

右边的字母栏列表可以快速的对列表的数据进行定位搜索,便于查找;

 

接下来简单谈谈具体的实现过程;

第一步:滑动列表listview(不包括右侧的拼音栏)的实现:上面的9个热门城市采用了GridView来实现,加载之后,调用listview.addHeaderView完成添加;

这一步需要注意的地方,gridview需要重写其onmeasure方法;

 @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = View.MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
                View.MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);
    }
Android通讯录、城市选择器列表的实现_第2张图片

第二步:右边字母栏与滑动列表的联动实现,这一步最主要的就是,对源数据的分组及对分组控制;系统也为我们提供了一个SectionIndexer的分组接口,并且也为我们提供了一个具体的实现——AlphabetIndexer,直接采用AlphabetIndexer,也可以自己去实现接口的功能;

第三步:对于“大数据”的支持,主要工作是进行图片方面的优化;包括:

A:图片缓存,包括内存缓存和磁盘缓存,分别对应于LruCache和DiskLruCache;LruCache系统本身就为我们提供的有了,于此不在多说;DiskLruCache系统本身没有为我们提供,但是却得到了Android官方的推荐,所以需要我们自己的引入,在此,引入的是Jake warthon的开源版本(compile 'com.jakewharton:disklrucache:2.0.2'),github地址为https://github.com/JakeWharton/DiskLruCache;在此项目中,只做了初始化的工具,具体的缓存实现还没有完成,请知悉:

B:优化卡顿,解决思路就是不要在UI线程中做太耗时的操作即可提高滑动的流畅度,主要包含几个反面;

B1:不要在Adapter的getview方法中执行耗时操作,此案例中就是不要在getview方法中加载图片,需要异步的方式来实现;

B2:控制异步任务的执行频率;如果用户频繁快速的进行列表滑动,也会瞬间产生上百个异步任务,这些异步任务会导致线程池的拥堵并随即带来大量的UI更新操作;就会造成一定程度的卡顿。思路就是在列表滑动停止的时候再加载图片;首先,给listview设置setonscrolllistener(),并在onscrolllistener的onscrollstatechanged方法中判断列表是否处于滑动状态,如果是就停止加载图片;

然后,在getview方法中,仅当列表静止的时候再加载图片;

//只有在列表静止的时候,我们再加载图片;
		if (isListViewIdle){
			//加载图片操作


		}

C:图片压缩,其实现也很简单;

public Bitmap decodeSampleBitmapFromResource(Resources resources,int resId,int reqWidth,int reqHeight){
        final BitmapFactory.Options options=new BitmapFactory.Options();
        options.inJustDecodeBounds=true;
        BitmapFactory.decodeResource(resources,resId,options);
        options.inSampleSize=calculateInSampleSize(options,reqWidth,reqHeight);
        options.inJustDecodeBounds=false;
        return BitmapFactory.decodeResource(resources,resId,options);
    }

第四步:分组之间挤压动画的实现;属于润色的功能;其具体实现也很简单,首先看看布局情况;




    

        

        

        
    


    

        
    

当下一个分组与顶部的分组接触时,顶部的view通过计算滑动距离,不断的上移就可以了,代码如下:

@Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                if (firstVisibleItem != lastFirstVisibleItem) {
                    ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) title_ll.getLayoutParams();
                    params.topMargin = 0;
                    title_ll.setLayoutParams(params);
                }

                int section = adapter.getSectionForPosition(firstVisibleItem);
                int lastSection ;
                if (firstVisibleItem==0){
                    lastSection=-1;
                    title_tv.setText("热门城市");
                }else {
                    lastSection= adapter.getSectionForPosition(firstVisibleItem - 1);
                    title_tv.setText(adapter.getHeaderText(firstVisibleItem-1));
                }
                if (lastSection != section) {
                    View childView = view.getChildAt(0);
                    if (childView != null) {
                        int titleHeight = title_ll.getHeight();
                        int bottom = childView.getBottom();
                        ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) title_ll
                                .getLayoutParams();
                        if (bottom < titleHeight) {
                            float pushedDistance = bottom - titleHeight;
                            params.topMargin = (int) pushedDistance;
                            title_ll.setLayoutParams(params);
                        } else {
                            if (params.topMargin != 0) {
                                params.topMargin = 0;
                                title_ll.setLayoutParams(params);
                            }
                        }
                    }
                }
                lastFirstVisibleItem = firstVisibleItem;
            }

最后附上demo的github地址:https://github.com/jyvvip/address-list-and-city-selector,欢迎各位看官star!

你可能感兴趣的:(Android)