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


首先附上一张效果图;


主要功能介绍:

最顶部始终显示一个当前的分组,并且当下一个分组即将完全“推”上去上一个分组、或者下一个分组即将被“拉”下来的时候,最顶部的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);
    }


第二步:右边字母栏与滑动列表的联动实现,这一步最主要的就是,对源数据的分组及对分组控制;系统也为我们提供了一个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);
    }

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

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

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ListView
            android:id="@+id/country_lvcountry"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:divider="@color/listview_driver"
            android:dividerHeight="1px" />

        <TextView
            android:id="@+id/dialog"
            android:layout_width="80.0dip"
            android:layout_height="80.0dip"
            android:layout_gravity="center"
            android:background="@color/green"
            android:gravity="center"
            android:textColor="#ffffffff"
            android:textSize="30.0dip"
            android:visibility="invisible" />

        <com.stephen.curry.memesou.widget.SideBar
            android:id="@+id/sidrbar"
            android:layout_width="30.0dip"
            android:layout_height="match_parent"
            android:layout_gravity="right|center" />
    </FrameLayout>


    <LinearLayout
        android:id="@+id/title_layout"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:layout_alignParentTop="true"
        android:background="#303030">

        <TextView
            android:id="@+id/title"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1.0"
            android:background="#E0E0E0"
            android:paddingBottom="5dip"
            android:paddingLeft="10dip"
            android:paddingTop="5dip"
            android:text="热门城市"
            android:textColor="#454545" />
    </LinearLayout>

</RelativeLayout>

当下一个分组与顶部的分组接触时,顶部的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!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值