美文网首页
城市选择列表的实现

城市选择列表的实现

作者: 木小伍 | 来源:发表于2017-12-15 15:41 被阅读0次

特别感谢github项目

直接上效果图
图1-预览界面 图2-效果展示界面 图3-城市查询
使用到的第三方依赖,具体详情请参照片头github链接
 compile 'com.github.mcxtzhang:SuspensionIndexBar:V1.0.0'
1.布局分析

布局主要由3部分组成,自定义搜索框,快速索引栏,以及recycleView组成。
主播代码如下:

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="44dp"
            android:background="@color/bg_white"
            android:gravity="center_vertical">

            <ImageView
                android:id="@+id/tv_selectCity_back"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:padding="3dp"
                android:src="@mipmap/back_dark_gray" />

            <com.wyw.selectcitydemo.EditTextWithDel
                android:id="@+id/etd_search"
                android:layout_width="match_parent"
                android:layout_height="30dp"
                android:layout_marginLeft="13dp"
                android:layout_marginRight="15dp"
                android:background="@drawable/shape_corner20_gray"
                android:hint="输入城市名查询"
                android:paddingLeft="10dp"
                android:paddingRight="10dp"
                android:singleLine="true"
                android:textColor="@color/font_black"
                android:textSize="14sp" />

        </LinearLayout>

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

            <android.support.v7.widget.RecyclerView
                android:id="@+id/rv_content"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@android:color/white" />

            <com.mcxtzhang.indexlib.IndexBar.widget.IndexBar
                android:id="@+id/indexBar"
                android:layout_width="24dp"
                android:layout_height="match_parent"
                android:layout_gravity="right"
                app:indexBarPressBackground="#00000000"
                app:indexBarTextSize="16sp" />

            <TextView
                android:id="@+id/tvSideBarHint"
                android:layout_width="80dp"
                android:layout_height="80dp"
                android:layout_gravity="center"
                android:gravity="center"
                android:textColor="#7BA0F6"
                android:textSize="48sp"
                android:visibility="gone"
                tools:text="A"
                tools:visibility="visible" />
        </FrameLayout>
    </LinearLayout>
2.代码分析

由于本项目中要求有,当前定位的城市,热门城市,以及历史访问城市3个部分,而且样式与主体城市列表不一致,参加图1,我姑且认为3个部分为3个头布局区域。

2.1控件的初始化
        //初始化recycleview的分割线
        mDecoration = new CharDecoration(mActivity, mAllDatas);
        mDecoration.setmDatas(mAllDatas);

        //indexbar初始化
        mIndexBar.setmPressedShowTextView(mTvSideBarHint)//设置HintTextView
                .setNeedRealIndex(true)//设置需要真实的索引
                .setmLayoutManager(mManager);
        mCityRcv.setAdapter(mHeaderAdapter);
2.2头布局区域的实现

这3个头布局可以理解完成写死的3个部分。所以本博客只列举当前定位城市代码实现。

   String localCityName = getIntent().getStringExtra("local_city");
        //通过地理坐标获取当前城市
        localCityName = TextUtils.isEmpty(localCityName) ? "定位失败" : localCityName;
        CityInfoBean localCity = new CityInfoBean().setName(localCityName).setTop(true).setBaseIndexTag(INDEX_STRING_LOCAL);

值得注意的是,创建的javaBean对象需要按照开篇中GitHub链接中继承父类BaseIndexPinyinBean
public class CityInfoBean extends BaseIndexPinyinBean implements Serializable{
 @Expose
    protected String id;

    @Expose
    protected String name;

}

将3个已经创建好的数据填充到界面对应的视图中

            mHeaderAdapter.setHeaderView(0, R.layout.meituan_item_header_local, localHeader);//对应的是当前城市的数据
            mHeaderAdapter.setHeaderView(1, R.layout.meituan_item_header, hotHeader);//热门城市的数据
            mHeaderAdapter.setHeaderView(2, R.layout.meituan_history_header, HistoryHeader);//历史城市的记录数据

  //通过对recycleview的adapter添加heardview或者footerview
        mHeaderAdapter = new HeaderRecyclerAndFooterWrapperAdapter(filterAdapter) {
            @Override
            protected void onBindHeaderHolder(ViewHolder holder, int headerPos, int layoutId, Object o) {
                final CityHeaderBean meituanHeaderBean = (CityHeaderBean) o;

                switch (layoutId) {
                    case R.layout.meituan_item_header_local: { //当前定位城市
                        RecyclerView recyclerView = holder.getView(R.id.rvCity);
                        recyclerView.setAdapter(
                                new CommonAdapter<CityInfoBean>(mActivity, R.layout.item_local_city, meituanHeaderBean.getCityList()) {
                                    @Override
                                    public void convert(ViewHolder holder, final CityInfoBean cityName) {
                                        holder.setText(R.id.tv_city, cityName.getTarget());
                                    }
                                });
                        recyclerView.setLayoutManager(new LinearLayoutManager(mActivity));
                    }
                    break;
...其他略
2.3城市数据的填充

主体主要也是采用recycleview来承载数据,同样参照头部视图数据的方法,创建一个内部类FilterAdapter继承至于CommonAdapter(因为涉及到后面的筛选操作,所以就不创建匿名内部类了)
核心代码如下:

 class FilterAdapter extends CommonAdapter<BaseIndexPinyinBean> {
        private CityFilter cityFilter = new CityFilter();

        public FilterAdapter(Context context, int layoutId, List<BaseIndexPinyinBean> datas) {
            super(context, layoutId, datas);
        }

        @Override
        public void convert(ViewHolder holder, BaseIndexPinyinBean cityInfo) {
            holder.setText(R.id.tv_item_credit_city_name, cityInfo.getTarget());
            holder.setVisible(R.id.tv_item_credit_city_tag, false);
            holder.itemView.setTag(R.id.cb_item_tag, cityInfo);
            holder.itemView.setOnClickListener(MainActivity.this);
        }
}
2.4 城市筛选的实现

该功能主要是由文本输入框内的字符数据来控制,所以需要重写文本框的监听方法。通过文本框内数据来控制recycleview中的数据变化。

 /**
     * 核心方法:1、通过过滤条件初始化数据;2、通过过滤条件控制辅助View;3、应用数据到核心显示控件
     *
     * @param filter
     */
    public void filter(String filter) {
        if (StringUtils.isEmpty(filter)) {//无过滤条件
            mAllDatas.add(0, localHeader);
            mAllDatas.add(1, hotHeader);
            mAllDatas.add(2, HistoryHeader);

            mHeaderAdapter.setHeaderView(0, R.layout.meituan_item_header_local, localHeader);//对应的是当前城市的数据
            mHeaderAdapter.setHeaderView(1, R.layout.meituan_item_header, hotHeader);//热门城市的数据
            mHeaderAdapter.setHeaderView(2, R.layout.meituan_history_header, HistoryHeader);//历史城市的记录数据

            mCityRcv.addItemDecoration(mDecoration);
            mIndexBar.setVisibility(View.VISIBLE);
        } else {//过滤条件有效,开始初始化过滤条件
            mAllDatas.remove(localHeader);
            mAllDatas.remove(hotHeader);
            mAllDatas.remove(HistoryHeader);

            mHeaderAdapter.clearHeaderView();
            mCityRcv.removeItemDecoration(mDecoration);
            mIndexBar.setVisibility(View.GONE);
        }

        /**
         * 应用过滤条件到各个View上
         */
        mIndexBar.setmSourceDatas(mAllDatas).invalidate();
        mIndexBar.getDataHelper().sortSourceDatas(mBodyDatas);
        filterAdapter.setFilter(filter);
        mHeaderAdapter.notifyDataSetChanged();
    }

在内部类FilterAdapter中添加方法,以便控制adapter中的不同数据源在recycleview中展示。(图3)

 public void setFilter(String filter) {
            List<BaseIndexPinyinBean> datas = new ArrayList<>();
            if (TextUtils.isEmpty(filter)) {
                datas.clear();
                datas.addAll(mAllDatas);
            } else {
                List<BaseIndexPinyinBean> temp = CollectionUtils.filter(mAllDatas, cityFilter.setFilter(filter));
                datas.clear();
                datas.addAll(temp);
            }
            //从过滤掉的数据中去除上面三区域的数据
            datas.remove(localHeader);
            datas.remove(hotHeader);
            datas.remove(HistoryHeader);
            setDatas(datas);
        }
2.5 历史城市的选择实现

历史城市,我采用的是SharedPreferences来存储我们历史点击过的城市,当然我们也需要对点击过的城市,进行过滤操作,避免历史记录中存储相同的城市。

 /**
     * 添加城市到历史记录中去
     *
     * @param cityInfo
     */
    private void addCity2History(CityInfoBean cityInfo) {
        boolean notExit = true;
        for (BaseIndexPinyinBean city : historyCitys) {
            if (city instanceof CityInfoBean) {
                String cityName = ((CityInfoBean) city).getName();
                if (!TextUtils.isEmpty(cityName) && cityName.contains(cityInfo.getName())) {
                    notExit = false;
                    break;
                }
            }
        }
        if (notExit) {
            if (historyCitys.size() >= 6) {  //当历史记录里面有没有该城市的时候
                ArrayList<CityInfoBean> tempLists = new ArrayList<>();
                historyCitys.remove(0);
                tempLists.addAll(historyCitys);
                tempLists.add(cityInfo);
                historyCitys.clear();
                historyCitys.addAll(tempLists);
            } else {
                historyCitys.add(cityInfo);
            }
        }

        String historyCityStr = JsonUtils.toJson(historyCitys);
        sharedPreUtils.saveValue(CITY_KEY, historyCityStr);
    }

最后附上完整的代码链接完整项目demo

相关文章

  • 城市选择列表的实现

    特别感谢github项目 直接上效果图 使用到的第三方依赖,具体详情请参照片头github链接 1.布局分析 布局...

  • ReactNative实现城市选择列表

    引言 使用RN开发了一段时间,最近遇到了一个比较棘手的问题,就是用react写个城市选择列表,当然这个如果用And...

  • RN--城市选择

    1、城市选择 2、React-Native实现高性能城市列表/联系人列表。 转自:https://www.jian...

  • React项目实战四

    选择城市列表 选择城市列表渲染后的界面: 1,获取并处理城市列表数据 接口返回的数据结构: 渲染城市列表的数据格式...

  • 微信通讯录页面UITableView细节探究

    写在前面的 最近做了一个城市选择列表页的需求,大概是一个页面,内容是中国城市的列表(UITableView 实现)...

  • 小程序中实现城市选择列表

    直入主题,实现什么蛇皮东西呢?大概是这个样子: 这样就可以得到全部城市的信息,然后去遍历,但是这个citys是个对...

  • Android 城市列表选择

    1、整个demo项目代码结构,内容不算太多,也不算太难 2、build.gradle依赖内容 3、效果图 注意:d...

  • Swift 城市列表选择

    本文是作者闲余时间写的Swift版本的城市列表选择,代码逻辑很简单,大致是:对城市名字进行处理,取出第一个字,转化...

  • 微信小程-实现城市列表选择

    实现效果预览 1、定位当前城市 2、根据首字母定位到响应的区域 3、点击选中区域 目录结构 index.wxml ...

  • React Native实现城市选择列表,仿联系人列表

    项目地址源码地址点我如果有不懂的问题,可以在评论区留言, 看到了就回复,每天都能回复

网友评论

      本文标题:城市选择列表的实现

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