Android 自定义仿京东地址选择器

Android 自定义仿京东地址选择器,第1张

public class AddressPickerViewextends RelativeLayout{

// recyclerView 选中Item 的颜色

    private int defaultSelectedColor = ColorparseColor("#3D71FF");

    // recyclerView 未选中Item 的颜色

    private int defaultUnSelectedColor = ColorparseColor("#2c2c2c");

    // 确定字体不可以点击时候的颜色

    private int defaultSureUnClickColor = ColorparseColor("#7F7F7F");

    // 确定字体可以点击时候的颜色

    private int defaultSureCanClickColor = ColorparseColor("#3D71FF");

    private ContextmContext;

    private int defaultTabCount =3; //tab 的数量

    private TabLayoutmTabLayout; // tabLayout

    private RecyclerViewmRvList; // 显示数据的RecyclerView

    private StringdefaultProvince ="省份"; //显示在上面tab中的省份

    private StringdefaultCity ="城市"; //显示在上面tab中的城市

    private StringdefaultDistrict ="区县"; //显示在上面tab中的区县

    private ListmRvData; // 用来在recyclerview显示的数据

    private AddressAdaptermAdapter;  // recyclerview 的adapter

    private YwpAddressBeanmYwpAddressBean; // 总数据

    private YwpAddressBeanAddressItemBeanmSelectProvice; //选中 省份bean

    private YwpAddressBeanAddressItemBeanmSelectCity;//选中 城市bean

    private YwpAddressBeanAddressItemBeanmSelectDistrict;//选中 区县bean

    private int mSelectProvicePosition =0; //选中 省份 位置

    private int mSelectCityPosition =0;//选中 城市  位置

    private int mSelectDistrictPosition =0;//选中 区县  位置

    private OnAddressPickerSureListenermOnAddressPickerSureListener;

    public AddressPickerView(Context context) {

super(context);

        init(context);

    }

public AddressPickerView(Context context, @Nullable AttributeSet attrs) {

super(context, attrs);

        init(context);

    }

public AddressPickerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

        init(context);

    }

/

    初始化

    /

    private void init(Context context) {

mContext = context;

        mRvData =new ArrayList<>();

        // UI

        View rootView =inflate(mContext, Rlayoutaddress_picker_view, this);

        // tablayout初始化

        mTabLayout = (TabLayout) rootViewfindViewById(RidtlTabLayout);

        mTabLayoutaddTab(mTabLayoutnewTab()setText(defaultProvince));

        mTabLayoutaddTab(mTabLayoutnewTab()setText(defaultCity));

        mTabLayoutaddTab(mTabLayoutnewTab()setText(defaultDistrict));

        mTabLayoutaddOnTabSelectedListener(tabSelectedListener);

        // recyclerview adapter的绑定

        mRvList = (RecyclerView) rootViewfindViewById(RidrvList);

        mRvListsetLayoutManager(new LinearLayoutManager(context));

        mAdapter =new AddressAdapter();

        mRvListsetAdapter(mAdapter);

        // 初始化默认的本地数据  也提供了方法接收外面数据

        mRvListpost(new Runnable() {

@Override

            public void run() {

initData();

            }

});

    }

/

    初始化数据

    拿assets下的json文件

    /

    private void initData() {

StringBuilder jsonSB =new StringBuilder();

        try {

BufferedReader addressJsonStream =new BufferedReader(new InputStreamReader(mContextgetAssets()open("addressjson")));

            String line;

            while ((line = addressJsonStreamreadLine()) !=null) {

jsonSBappend(line);

            }

}catch (IOException e) {

eprintStackTrace();

        }

// 将数据转换为对象

        mYwpAddressBean =new Gson()fromJson(jsonSBtoString(), YwpAddressBeanclass);

        if (mYwpAddressBean !=null) {

mRvDataclear();

            mRvDataaddAll(mYwpAddressBeangetProvince());

            mAdapternotifyDataSetChanged();

        }

}

/

    开放给外部传入数据

    暂时就用这个Bean模型,如果数据不一致就需要各自根据数据来生成这个bean了

    /

    public void initData(YwpAddressBean bean) {

if (bean !=null) {

mSelectDistrict =null;

            mSelectCity =null;

            mSelectProvice =null;

            mTabLayoutgetTabAt(0)select();

            mYwpAddressBean = bean;

            mRvDataclear();

            mRvDataaddAll(mYwpAddressBeangetProvince());

            mAdapternotifyDataSetChanged();

        }

}

//点确定

    private void sure() {

if (mSelectProvice !=null &&

mSelectCity !=null &&

mSelectDistrict !=null) {

//  回调接口

            if (mOnAddressPickerSureListener !=null) {

mOnAddressPickerSureListeneronSureClick(mSelectProvicegetN(), mSelectCitygetN(), mSelectDistrictgetN());

            }

}else {

ToastmakeText(mContext, "地址还没有选完整哦", ToastLENGTH_SHORT)show();

        }

}

@Override

    protected void onDetachedFromWindow() {

superonDetachedFromWindow();

      // mYwpAddressBean = null;

    }

/

    TabLayout 切换事件

    /

    TabLayoutOnTabSelectedListenertabSelectedListener =new TabLayoutOnTabSelectedListener() {

@Override

        public void onTabSelected(TabLayoutTab tab) {

mRvDataclear();

            switch (tabgetPosition()) {

case 0:

mRvDataaddAll(mYwpAddressBeangetProvince());

                    mAdapternotifyDataSetChanged();

                    // 滚动到这个位置

                    mRvListsmoothScrollToPosition(mSelectProvicePosition);

break;

                case 1:

// 点到城市的时候要判断有没有选择省份

                    if (mSelectProvice !=null) {

for (YwpAddressBeanAddressItemBean itemBean :mYwpAddressBeangetCity()) {

if (itemBeangetP()equals(mSelectProvicegetI()))

mRvDataadd(itemBean);

                        }

}else {

ToastmakeText(mContext, "请您先选择省份", ToastLENGTH_SHORT)show();

                    }

mAdapternotifyDataSetChanged();

                    // 滚动到这个位置

                    mRvListsmoothScrollToPosition(mSelectCityPosition);

break;

                case 2:

// 点到区的时候要判断有没有选择省份与城市

                    if (mSelectProvice !=null &&mSelectCity !=null) {

for (YwpAddressBeanAddressItemBean itemBean :mYwpAddressBeangetDistrict()) {

if (itemBeangetP()equals(mSelectCitygetI()))

mRvDataadd(itemBean);

                        }

}else {

ToastmakeText(mContext, "请您先选择省份与城市", ToastLENGTH_SHORT)show();

                    }

mAdapternotifyDataSetChanged();

                    // 滚动到这个位置

                    mRvListsmoothScrollToPosition(mSelectDistrictPosition);

break;

            }

}

@Override

        public void onTabUnselected(TabLayoutTab tab) {

}

@Override

        public void onTabReselected(TabLayoutTab tab) {

}

};

    /

    下面显示数据的adapter

/

    class AddressAdapterextends RecyclerViewAdapter {

@Override

        public ViewHolderonCreateViewHolder(ViewGroup parent, int viewType) {

return new ViewHolder(LayoutInflaterfrom(mContext)inflate(Rlayoutitem_address_text, parent, false));

        }

@Override

        public void onBindViewHolder(final ViewHolder holder, final int position) {

final int tabSelectPosition =mTabLayoutgetSelectedTabPosition();

            holdermTitlesetText(mRvDataget(position)getN());

            holdermTitlesetTextColor(defaultUnSelectedColor);

            // 设置选中效果的颜色

            switch (tabSelectPosition) {

case 0:

if (mRvDataget(position) !=null &&

mSelectProvice !=null &&

mRvDataget(position)getI()equals(mSelectProvicegetI())) {

holdermTitlesetTextColor(defaultSelectedColor);

                    }

break;

                case 1:

if (mRvDataget(position) !=null &&

mSelectCity !=null &&

mRvDataget(position)getI()equals(mSelectCitygetI())) {

holdermTitlesetTextColor(defaultSelectedColor);

                    }

break;

                case 2:

if (mRvDataget(position) !=null &&

mSelectDistrict !=null &&

mRvDataget(position)getI()equals(mSelectDistrictgetI())) {

holdermTitlesetTextColor(defaultSelectedColor);

                    }

break;

            }

// 设置点击之后的事件

            holdermTitlesetOnClickListener(new OnClickListener() {

@Override

                public void onClick(View v) {

// 点击 分类别

                    switch (tabSelectPosition) {

case 0:

mSelectProvice =mRvDataget(position);

                            // 清空后面两个的数据

                            mSelectCity =null;

                            mSelectDistrict =null;

                            mSelectCityPosition =0;

                            mSelectDistrictPosition =0;

                            mTabLayoutgetTabAt(1)setText(defaultCity);

                            mTabLayoutgetTabAt(2)setText(defaultDistrict);

                            // 设置这个对应的标题

                            mTabLayoutgetTabAt(0)setText(mSelectProvicegetN());

                            // 跳到下一个选择

                            mTabLayoutgetTabAt(1)select();

                            mSelectProvicePosition =position;

break;

                        case 1:

mSelectCity =mRvDataget(position);

                            // 清空后面一个的数据

                            mSelectDistrict =null;

                            mSelectDistrictPosition =0;

                            mTabLayoutgetTabAt(2)setText(defaultDistrict);

                            // 设置这个对应的标题

                            mTabLayoutgetTabAt(1)setText(mSelectCitygetN());

                            // 跳到下一个选择

                            mTabLayoutgetTabAt(2)select();

                            mSelectCityPosition =position;

break;

                        case 2:

mSelectDistrict =mRvDataget(position);

                            // 没了,选完了,这个时候可以点确定了

                            mTabLayoutgetTabAt(2)setText(mSelectDistrictgetN());

                            notifyDataSetChanged();

                            mSelectDistrictPosition =position;

                            sure();

break;

                    }

}

});

        }

@Override

        public int getItemCount() {

return mRvDatasize();

        }

class ViewHolderextends RecyclerViewViewHolder {

TextViewmTitle;

            ViewHolder(View itemView) {

super(itemView);

                mTitle = (TextView) itemViewfindViewById(RiditemTvTitle);

            }

}

}

/

    点确定回调这个接口

    /

    public interface OnAddressPickerSureListener {

void onSureClick(String proviceName,String cityName,String earaName);

    }

public void setOnAddressPickerSure(OnAddressPickerSureListener listener) {

thismOnAddressPickerSureListener = listener;

    }

搜索框功能主要有3部分组成:

ES官方文档建议通过phrase Suggester实行搜索框的自动补全,但这种查询对中文支持不太友好,经常会不做提示;下面我们通过n-gram来实现符合中国人民使用习惯的提示框。

假设有一个词hello,普通建索引时,就是把这个词hello放入倒排索引
用户输入h、he时会找不到索引(倒排索引中只有hello),因此匹配失败
而对于输入即搜索这种应用场景,可以使用一种特殊的n-gram,称为边界n-grams (edge n-grams)
所谓的edge n-gram,就是指它会固定从一边开始,进行窗口滑动,每次滑动长度为1,最终的结果取决于 n 的选择长度
以单词hello为例,它的edge n-gram的结果如下:

因此可以发现到,在使用edge n-gram建索引时,一个单词会生成好几个索引,而这些索引一定是从头开始
这符合了输入即搜索的特性,即是用户打h、he能找到倒排中的索引h、he,而这些索引对应著的数据就是hello

需要注意的是,这里使用fuzziness来模糊匹配提升用户体验,fuzziness=1 允许用户输入一个错别字,并通过prefix_length设置为1来跳过开头首个字符的判断,因为一般用户输入出错大多发生在后面

需要注意:
其中min_word_length是用来控制候选词长度的,这里设置为2,意思是当term长度>=2才会被显示;
prefix_length=1表示忽略首字符是错别字,大多数输入错别字发生在后面;
min_doc_freq 当建议词出现文档频率低于该值时将被忽略,线上可适当调大该值以提升搜索效果

易企秀商城


DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
乐在赚 » Android 自定义仿京东地址选择器

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情