Android 地址選擇器仿京東;

控件很簡單,上方tab是使用LinearLayout動態添加View,下方就是一個RecyclerView;

目前的數據就三級(省市區\縣),選擇完成或點擊確定就回調結果(Json字符串);

點擊上方的tab可以回選;

....

很簡單,主要是代碼和思路吧;看一下代碼;

public class AddressSelectView extends RelativeLayout {

    private LinearLayout tab;
    private RecyclerView rv;
    private Context mC;
    private AddressBean addressBean;//數據源
    private List<AddressBean.AddressItemBean> addressDatas; //當前正在選擇的數據
    private List<AddressBean.AddressItemBean> alreadySelectDatas; //已經選擇的數據

    public AddressSelectView(Context context) {
        super(context);
        init(context);
    }

    public AddressSelectView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public AddressSelectView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private View rootView;

    private void init(Context context) {
        mC = context;
        rootView = View.inflate(context, R.layout.activity_address_select, this);
        tab = rootView.findViewById(R.id.tab);
        rv = rootView.findViewById(R.id.rv);
        initList();
        initData();
        initView();
    }

    private String clickText; //回退時點擊的文字

    private void initList() {
        rootView.findViewById(R.id.tvQ).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (onSelectConfirmListEner != null) onSelectConfirmListEner.onConfirm(new Gson().toJson(alreadySelectDatas));
            }
        });
        setOnTabClickListEner(new OnTabClickListEner() {
            @Override
            public void onTabClick(View view, int position) {
                if (alreadySelectDatas == null || position == tab.getChildCount() - 1) return;
                if (alreadySelectDatas.size() > position)
                    clickText = alreadySelectDatas.get(position).getName();
                if (position == 0) {
                    //如果點擊第一個,就重新開始選擇
                    if (alreadySelectDatas != null) alreadySelectDatas.clear();
                    tab.removeAllViews();
                    addRadioButton("選擇省");
                    if (addressBean != null) {
                        addressAdapter.setDatas(addressBean.getProvince());
                    }
                } else {
                    //如果點擊的不是第一個,則刷新數據
                    List<AddressBean.AddressItemBean> alreadySelectDatas2 = new ArrayList<>();
                    if (alreadySelectDatas.size() >= position) {
                        for (int i = 0; i < position; i++) {
                            //只保留點擊的這個之前的數據;
                            alreadySelectDatas2.add(alreadySelectDatas.get(i));
                        }
                    }
                    alreadySelectDatas.clear();
                    alreadySelectDatas.addAll(alreadySelectDatas2);
                    //使用新的數據重新規劃數據源和UI
                    tab.removeAllViews();
                    for (int j = 0; j < alreadySelectDatas.size(); j++) {
                        addRadioButton(alreadySelectDatas.get(j).getName());
                    }
                    selectPostion(alreadySelectDatas.get(alreadySelectDatas.size() - 1), false);
                }
            }
        });
    }


    private AddressAdapter addressAdapter;

    private void initView() {
        addRadioButton("選擇省");
        rv.setLayoutManager(new LinearLayoutManager(mC));
        addressAdapter = new AddressAdapter(mC, null);
        rv.setAdapter(addressAdapter);
        if (addressBean != null) {
            addressAdapter.setDatas(addressBean.getProvince());
        }
    }

    /**
     * 初始化數據
     * 拿assets下的json文件
     */
    private void initData() {
        StringBuilder jsonSB = new StringBuilder();
        try {
            BufferedReader addressJsonStream = new BufferedReader(new InputStreamReader(mC.getAssets().open("address.json")));
            String line;
            while ((line = addressJsonStream.readLine()) != null) {
                jsonSB.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 將數據轉換爲對象
        addressBean = new Gson().fromJson(jsonSB.toString(), AddressBean.class);
    }

    /**
     * 添加一個Tab
     *
     * @param text
     * @return
     */
    private void addRadioButton(String text) {
        for (int i = 0; i < tab.getChildCount(); i++) {
            ((TextView) tab.getChildAt(i)).setTextColor(getResources().getColor(R.color.textmain));
        }
        final TextView textView = new TextView(mC);
        textView.setTag(tab.getChildCount());
        textView.setText(text);
        textView.setTextSize(16);
        textView.setPadding(20, 0, 0, 0);
        textView.setTextColor(getResources().getColor(R.color.textselect));
        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (onTabClickListEner != null)
                    onTabClickListEner.onTabClick(textView, (int) textView.getTag());
            }
        });
        tab.addView(textView);
    }

    /**
     * 選擇一個位置後
     *
     * @param data
     */
    private void selectPostion(AddressBean.AddressItemBean data, boolean isAddData) {
        rv.scrollToPosition(0);
        if (alreadySelectDatas == null) {
            alreadySelectDatas = new ArrayList<>();
        }
        if (isAddData) alreadySelectDatas.add(data);

        if (addressDatas == null) {
            addressDatas = new ArrayList<>();
        } else {
            addressDatas.clear();
        }
        //修改當前選擇的名稱
        ((TextView) tab.getChildAt(tab.getChildCount() - 1)).setText(data.getName());

        if (tab.getChildCount() == 1) {
            addRadioButton("選擇市");
            for (int i = 0; i < addressBean.getCity().size(); i++) {
                if (TextUtils.equals(data.getId(), addressBean.getCity().get(i).getAboveId())) {
                    addressDatas.add(addressBean.getCity().get(i));
                }
            }
        } else if (tab.getChildCount() == 2) {
            addRadioButton("選擇區");
            for (int i = 0; i < addressBean.getDistrict().size(); i++) {
                if (TextUtils.equals(data.getId(), addressBean.getDistrict().get(i).getAboveId())) {
                    addressDatas.add(addressBean.getDistrict().get(i));
                }
            }
        }else {
            if (onSelectConfirmListEner != null) onSelectConfirmListEner.onConfirm(new Gson().toJson(alreadySelectDatas));
        }
        addressAdapter.setDatas(addressDatas);
    }

    private class AddressAdapter extends RecyclerView.Adapter<AddressAdapter.Vh> {

        private Context context;
        private List<AddressBean.AddressItemBean> datas;

        public AddressAdapter(Context context, List<AddressBean.AddressItemBean> datas) {
            this.context = context;
            if (datas == null) {
                this.datas = new ArrayList<>();
            } else {
                this.datas = datas;
            }
        }

        public void setDatas(List<AddressBean.AddressItemBean> datas) {
            if (datas == null) {
                this.datas = new ArrayList<>();
            } else {
                this.datas = datas;
            }
            notifyDataSetChanged();
        }

        @NonNull
        @Override
        public Vh onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            return new Vh(LayoutInflater.from(context).inflate(R.layout.item_address, parent, false));
        }

        @Override
        public void onBindViewHolder(@NonNull Vh holder, final int position) {
            holder.tv.setText(datas.get(position).getName());
            holder.tv.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    selectPostion(datas.get(position), true);
                }
            });
            //如果用戶點擊導航條重新選擇的話,就標記當前選擇過的顏色加深
            if (TextUtils.equals(datas.get(position).getName(), clickText)) {
                holder.tv.setTextColor(context.getResources().getColor(R.color.textselect));
            } else {
                holder.tv.setTextColor(context.getResources().getColor(R.color.textmain));
            }
        }

        @Override
        public int getItemCount() {
            return datas.size();
        }

        class Vh extends RecyclerView.ViewHolder {

            public TextView tv;

            public Vh(@NonNull View itemView) {
                super(itemView);
                tv = itemView.findViewById(R.id.tv);
            }
        }
    }


    interface OnTabClickListEner {
        void onTabClick(View view, int position);
    }

    private OnTabClickListEner onTabClickListEner;

    private void setOnTabClickListEner(OnTabClickListEner onTabClickListEner) {
        this.onTabClickListEner = onTabClickListEner;
    }

    public interface OnSelectConfirmListEner {
        void onConfirm(String s);
    }

    public OnSelectConfirmListEner onSelectConfirmListEner;

    public void setOnSelectConfirmListEner(OnSelectConfirmListEner onSelectConfirmListEner) {
        this.onSelectConfirmListEner = onSelectConfirmListEner;
    }
}

項目在這裏:https://github.com/CuiChenbo/AddressSelectView

若是想實現類似的效果,推薦把源代碼copy下來,按照自己的UI風格和數據源格式改一下就OK啦;

當然什麼代碼都不動也可以,就是上面的效果;

把控件放在一個PopupWindow或Dialog中彈出來,選擇完成後在隱藏掉;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章