Android-PickerView框架的簡單使用

參考GitHub:https://github.com/Bigkoo/Android-PickerView

這個框架的效果感覺不錯,但是作者不得不讓人吐槽,但是沒辦法,人家效果好,還得想辦法用,接下來我寫的比較基礎簡單,其他方法設置可以去GitHub或Demo中去查看,希望我下面的講解能幫助大家,如果還是不明白並且導入他的框架運行報錯的話,可以找我解決報錯問題。

一、主要說明如下功能,如果想實現其他功能可以下載GitHub中的Demo或者去調用方法看看效果。

1. 時間選擇器

2. 條件選擇器和省市區三級聯動

3. 自定義選擇器

二、加入依賴

implementation 'com.contrarywind:Android-PickerView:4.1.7'

三、時間選擇器

    private void initTimePicker() {//Dialog 模式下,在底部彈出
        TimePickerView pvTime = new TimePickerBuilder(this, new OnTimeSelectListener() {
            @Override
            public void onTimeSelect(Date date, View v) {
                Toast.makeText(MainActivity.this, getTime(date), Toast.LENGTH_SHORT).show();
            }
        }).build();
    }
 
    private String getTime(Date date) {//可根據需要自行截取數據顯示
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return format.format(date);
    }

四、條件選擇器和省市區三級聯動

1. 省市區三級聯動

第一步:先在main文件下創建assets文件夾,從Demo的main/assets中複製一個province.json文件在此文件下。

第二步:佈局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_json_data"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    android:paddingBottom="16dp"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:paddingTop="16dp">
 
    <Button
        android:id="@+id/btn_data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/picker_text_parse"/>
 
    <Button
        android:id="@+id/btn_show"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/picker_text_show"
        android:layout_marginTop="@dimen/activity_horizontal_margin" />
 
</LinearLayout>

第三步:解析province.json數據的工具類

public class GetJsonDataUtil {
 
    public String getJson(Context context, String fileName) {
        StringBuilder stringBuilder = new StringBuilder();
        try {
            AssetManager assetManager = context.getAssets();
            BufferedReader bf = new BufferedReader(new InputStreamReader(
                    assetManager.open(fileName)));
            String line;
            while ((line = bf.readLine()) != null) {
                stringBuilder.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return stringBuilder.toString();
    }
 
}

第四步:創建一個Bean類

public class JsonBean implements IPickerViewData {
 
    /**
     * name : 省份
     * city : [{"name":"北京市","area":["東城區","西城區","崇文區","宣武區","朝陽區"]}]
     */
    private String name;
    private List<CityBean> city;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public List<CityBean> getCityList() {
        return city;
    }
 
    public void setCityList(List<CityBean> city) {
        this.city = city;
    }
 
    // 實現 IPickerViewData 接口,
    // 這個用來顯示在PickerView上面的字符串,
    // PickerView會通過IPickerViewData獲取getPickerViewText方法顯示出來。
    @Override
    public String getPickerViewText() {
        return this.name;
    }
 
    public static class CityBean {
        /**
         * name : 城市
         * area : ["東城區","西城區","崇文區","昌平區"]
         */
        private String name;
        private List<String> area;
 
        public String getName() {
            return name;
        }
 
        public void setName(String name) {
            this.name = name;
        }
 
        public List<String> getArea() {
            return area;
        }
 
        public void setArea(List<String> area) {
            this.area = area;
        }
    }
}

第五步:Activity,你可以讓他頁面一打開就開始解析數據

public class JsonDataActivity extends AppCompatActivity implements View.OnClickListener {
 
    private List<JsonBean> options1Items = new ArrayList<>();
    private ArrayList<ArrayList<String>> options2Items = new ArrayList<>();
    private ArrayList<ArrayList<ArrayList<String>>> options3Items = new ArrayList<>();
    private Thread thread;
    private static final int MSG_LOAD_DATA = 0x0001;
    private static final int MSG_LOAD_SUCCESS = 0x0002;
    private static final int MSG_LOAD_FAILED = 0x0003;
 
    private static boolean isLoaded = false;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_json_data);
        initView();
    }
 
 
    private void initView() {
        findViewById(R.id.btn_data).setOnClickListener(this);
        findViewById(R.id.btn_show).setOnClickListener(this);
    }
 
    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_LOAD_DATA:
                    if (thread == null) {//如果已創建就不再重新創建子線程了
                        Toast.makeText(JsonDataActivity.this, "Begin Parse Data", Toast.LENGTH_SHORT).show();
                        thread = new Thread(new Runnable() {
                            @Override
                            public void run() {
                                // 子線程中解析省市區數據
                                initJsonData();
                            }
                        });
                        thread.start();
                    }
                    break;
 
                case MSG_LOAD_SUCCESS:
                    Toast.makeText(JsonDataActivity.this, "Parse Succeed", Toast.LENGTH_SHORT).show();
                    isLoaded = true;
                    break;
 
                case MSG_LOAD_FAILED:
                    Toast.makeText(JsonDataActivity.this, "Parse Failed", Toast.LENGTH_SHORT).show();
                    break;
            }
        }
    };
 
    private void initJsonData() {//解析數據
 
        /**
         * 注意:assets 目錄下的Json文件僅供參考,實際使用可自行替換文件
         * 關鍵邏輯在於循環體
         *
         * */
        String JsonData = new GetJsonDataUtil().getJson(this, "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);
 
    }
 
    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;
    }
 
    private void showPickerView() {// 彈出選擇器
 
        OptionsPickerView pvOptions = new OptionsPickerBuilder(this, new OnOptionsSelectListener() {
            @Override
            public void onOptionsSelect(int options1, int options2, int options3, View v) {
                //返回的分別是三個級別的選中位置
                String opt1tx = options1Items.size() > 0 ?
                        options1Items.get(options1).getPickerViewText() : "";
 
                String opt2tx = options2Items.size() > 0
                        && options2Items.get(options1).size() > 0 ?
                        options2Items.get(options1).get(options2) : "";
 
                String opt3tx = options2Items.size() > 0
                        && options3Items.get(options1).size() > 0
                        && options3Items.get(options1).get(options2).size() > 0 ?
                        options3Items.get(options1).get(options2).get(options3) : "";
 
                String tx = opt1tx + opt2tx + opt3tx;
                Toast.makeText(JsonDataActivity.this, tx, Toast.LENGTH_SHORT).show();
            }
        })
 
                .setTitleText("城市選擇")
                .setDividerColor(Color.BLACK)
                .setTextColorCenter(Color.BLACK) //設置選中項文字顏色
                .setContentTextSize(20)
                .build();
 
        /*pvOptions.setPicker(options1Items);//一級選擇器
        pvOptions.setPicker(options1Items, options2Items);//二級選擇器*/
        pvOptions.setPicker(options1Items, options2Items, options3Items);//三級選擇器
        pvOptions.show();
    }
 
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mHandler != null) {
            mHandler.removeCallbacksAndMessages(null);
        }
    }
 
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_data:
                mHandler.sendEmptyMessage(MSG_LOAD_DATA);
                break;
            case R.id.btn_show:
                if (isLoaded) {
                    showPickerView();
                } else {
                    Toast.makeText(JsonDataActivity.this, "Please waiting until the data is parsed", Toast.LENGTH_SHORT).show();
                }
                break;
        }
    }
}

2. 條件選擇器:只需要把上面的數據源修改成你需要的即可。

五、自定義選擇器

private void initCustomTimePicker() {
 
        /**
         * @description
         *
         * 注意事項:
         * 1.自定義佈局中,id爲 optionspicker 或者 timepicker 的佈局以及其子控件必須要有,否則會報空指針.
         * 具體可參考demo 裏面的兩個自定義layout佈局。
         * 2.因爲系統Calendar的月份是從0-11的,所以如果是調用Calendar的set方法來設置時間,月份的範圍也要是從0-11
         * setRangDate方法控制起始終止時間(如果不設置範圍,則使用默認時間1900-2100年,此段代碼可註釋)
         */
        Calendar selectedDate = Calendar.getInstance();//系統當前時間
        Calendar startDate = Calendar.getInstance();
        startDate.set(2014, 1, 23);
        Calendar endDate = Calendar.getInstance();
        endDate.set(2027, 2, 28);
        //時間選擇器 ,自定義佈局
        pvCustomTime = new TimePickerBuilder(this, new OnTimeSelectListener() {
            @Override
            public void onTimeSelect(Date date, View v) {//選中事件回調
                mTv.setText(getTime(date));
            }
        })
                .setDate(selectedDate)
                .setRangDate(startDate, endDate)
                //添加自定義佈局的回調方法
                .setLayoutRes(R.layout.pickerview_custom_time, new CustomListener() {
 
                    @Override
                    public void customLayout(View v) {
                        final TextView tvSubmit = (TextView) v.findViewById(R.id.tv_finish);
                        ImageView ivCancel = (ImageView) v.findViewById(R.id.iv_cancel);
                        tvSubmit.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                pvCustomTime.returnData();
                                pvCustomTime.dismiss();
                            }
                        });
                        ivCancel.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                pvCustomTime.dismiss();
                            }
                        });
                    }
                })
                .setContentTextSize(18)
                .setType(new boolean[]{false, false, false, true, true, true})
                .setLabel("年", "月", "日", "時", "分", "秒")
                .setLineSpacingMultiplier(1.2f)
                .setTextXOffset(0, 0, 0, 40, 0, -40)
                .isCenterLabel(false) //是否只顯示中間選中項的label文字,false則每項item全部都帶有label。
                .setDividerColor(0xFF24AD9D)
                .build();
 
    }

六、其他

1. 上面的最後一步都是用picker.show();控制展示。

2. 其他樣式可根據GitHub中的講解的方法選擇性添加。

3. 有什麼疑問,歡迎大家來提問。

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