Android 選擇器 PickerView實例,時間選擇器、地址選擇器、單項選擇器、多項選擇器自定義佈局

是採用的github開源庫PickerView,省時省力。最終效果圖見最後

首先添加依賴:

//PickerView 選擇器
implementation 'com.contrarywind:Android-PickerView:4.1.9'
//谷歌Gson
implementation 'com.google.code.gson:gson:2.8.6'
//eventbus
implementation 'org.greenrobot:eventbus:3.2.0'

Gson是在解析地址文件的時候要用,eventbus是傳遞選擇的數據的時候要用。

因爲他給的佈局通常是不太符合你實際需求的,所以使用自定義佈局的方式,先去寫好自己的佈局文件,如地址的

picker_location.xml

因爲有多個地方要重用選擇器的部分,所以我使用include方便重用:

include_picker_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="280dp"
    android:background="@drawable/shape_picker_bg">

    <TextView
        android:id="@+id/include_picker_tv_cancle"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:text="取消"
        android:textSize="14dp"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="20dp"
        android:textColor="@color/black_1A"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/include_picker_tv_submit"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:text="確定"
        android:textSize="14dp"
        android:layout_marginRight="20dp"
        android:layout_marginTop="20dp"
        android:textColor="@color/gray_9A"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <LinearLayout
        android:id="@+id/optionspicker"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="150dp"
        android:gravity="center"
        android:background="@android:color/white"
        android:orientation="horizontal"
        android:layout_marginTop="20dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent">

        <com.contrarywind.view.WheelView
            android:id="@+id/options1"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <com.contrarywind.view.WheelView
            android:id="@+id/options2"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <com.contrarywind.view.WheelView
            android:id="@+id/options3"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />
    </LinearLayout>


</androidx.constraintlayout.widget.ConstraintLayout>

我將這幾個封裝成了一個工具類,其中顯示地址的代碼:

private OptionsPickerView locationOptions;
//顯示地址選擇器
    public void showLocationPicker() {// 彈出選擇器
        if(!isLoaded){
            Toast.makeText(context,context.getResources().getString(R.string.loading_location_data),Toast.LENGTH_SHORT).show();
            return;
        }
        locationOptions = new OptionsPickerBuilder(context, new OnOptionsSelectListener() {
            @Override
            public void onOptionsSelect(int options1, int options2, int options3, View v) {
                //

            }
        })
                .setLayoutRes(R.layout.picker_location, new CustomListener() {
                    @Override
                    public void customLayout(View v) {
                        final TextView tvSubmit = v.findViewById(R.id.picker_location_inc_bg).findViewById(R.id.include_picker_tv_submit);
                        final TextView tvCancle = v.findViewById(R.id.picker_location_inc_bg).findViewById(R.id.include_picker_tv_cancle);
                        tvSubmit.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                if(!isChanged){//沒有改變默認選擇第一項
                                    String firstLocation = options1Items.get(0).getPickerViewText() + "\t" +  options2Items.get(0).get(0);
                                    EventBus.getDefault().post(new PickerMessageEvent(MESSAGE_TYPE_LOCATION,firstLocation,"0"));
                                }else {
                                    EventBus.getDefault().post(new PickerMessageEvent(MESSAGE_TYPE_LOCATION,checkedLocation,"0"));
                                }
                                locationOptions.dismiss();
                            }
                        });
                    }
                })
                .setOptionsSelectChangeListener(new OnOptionsSelectChangeListener() {
                    @Override
                    public void onOptionsSelectChanged(int options1, int options2, int options3) {
                        String opt1tx = options1Items.size() > 0 ?
                                options1Items.get(options1).getPickerViewText() : "";

                        String opt2tx = options2Items.size() > 0
                                && options2Items.get(options1).size() > 0 ?
                                options2Items.get(options1).get(options2) : "";
                        checkedLocation = opt1tx + "\t" + opt2tx;
                        isChanged = true;
                    }
                })
                .setLineSpacingMultiplier(2.4f)//設置距離
                .setItemVisibleCount(3)//設置顯示的數據數量
                .setContentTextSize(17)//設置標題字號
                .isRestoreItem(true)//是否每次從頭開始顯示數據
                .isAlphaGradient(true)
                .build();

        locationOptions.setPicker(options1Items, options2Items);
        locationOptions.show();
    }

    //初始化地區數據
    private void initJsonData() {//解析數據

        /**
         * 注意:assets 目錄下的Json文件僅供參考,實際使用可自行替換文件
         * 關鍵邏輯在於循環體
         *
         * */
        String JsonData = new GetJsonDataUtil().getJson(context, "province.json");//獲取assets目錄下的json文件數據

        ArrayList<JsonBean> jsonBean = parseData(JsonData);//用Gson 轉成實體

        /**
         * 添加省份數據
         *
         * 注意:如果是添加的JavaBean實體,則實體類需要實現 IPickerViewData 接口,
         * PickerView會通過getPickerViewText方法獲取字符串顯示出來。
         */
        options1Items = jsonBean;

        for (int i = 0; i < jsonBean.size(); i++) {//遍歷省份
            ArrayList<String> cityList = new ArrayList<>();//該省的城市列表(第二級)
            ArrayList<ArrayList<String>> province_AreaList = new ArrayList<>();//該省的所有地區列表(第三極)

            for (int c = 0; c < jsonBean.get(i).getCityList().size(); c++) {//遍歷該省份的所有城市
                String cityName = jsonBean.get(i).getCityList().get(c).getName();
                cityList.add(cityName);//添加城市
//                ArrayList<String> city_AreaList = new ArrayList<>();//該城市的所有地區列表

                //如果無地區數據,建議添加空字符串,防止數據爲null 導致三個選項長度不匹配造成崩潰
                /*if (jsonBean.get(i).getCityList().get(c).getArea() == null
                        || jsonBean.get(i).getCityList().get(c).getArea().size() == 0) {
                    city_AreaList.add("");
                } else {
                    city_AreaList.addAll(jsonBean.get(i).getCityList().get(c).getArea());
                }*/
//                city_AreaList.addAll(jsonBean.get(i).getCityList().get(c).getArea());
//                province_AreaList.add(city_AreaList);//添加該省所有地區數據
            }

            /**
             * 添加城市數據
             */
            options2Items.add(cityList);

            /**
             * 添加地區數據
             */
//            options3Items.add(province_AreaList);
        }

        mHandler.sendEmptyMessage(MSG_LOAD_SUCCESS);

    }


    //解析地區json文件
    public ArrayList<JsonBean> parseData(String result) {//Gson 解析
        ArrayList<JsonBean> detail = new ArrayList<>();
        try {
            JSONArray data = new JSONArray(result);
            Gson gson = new Gson();
            for (int i = 0; i < data.length(); i++) {
                JsonBean entity = gson.fromJson(data.optJSONObject(i).toString(), JsonBean.class);
                detail.add(entity);
            }
        } catch (Exception e) {
            e.printStackTrace();
            mHandler.sendEmptyMessage(MSG_LOAD_FAILED);
        }
        return detail;
    }

    public void removeHandler(){
        if (mHandler != null) {
            mHandler.removeCallbacksAndMessages(null);
        }
    }

其中

String JsonData = new GetJsonDataUtil().getJson(context, "province.json");//獲取assets目錄下的json文件數據

是一份地址數據文件放在本地assets。

JsonBean和GetJsonDataUtil請參照源碼,不過多解釋。

最後效果:

         

自己需要什麼樣的效果就通過佈局文件和locationOptions.set...去設置

源碼:

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