1. 程式人生 > >Android-PickerView的簡單封裝與使用

Android-PickerView的簡單封裝與使用

前言:這是一款仿iOS的PickerView控制元件,有時間選擇器和選項選擇,支援年月日時分,年月日,時分等格式。

主要目的:百度上有非常多寫這個開源專案的用法,不過大多數都是照搬github上面複製過來的,少有人說明該如何設定三級聯動的資料來源,這裡將身高、體重、年齡等進行簡單的封裝,使用只需一句程式碼,如需基本使用可參考原專案連結:

1、效果圖:

這裡寫圖片描述

專案build.gradle中加入:

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

studio版本3.0以下 implementation 換成compile

2、Data.java 三級聯動實體類

public class Data implements IPickerViewData{

    private String name;
    private List<CityBean> city;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<CityBean> getCity
() { return city; } public void setCity(List<CityBean> city) { this.city = city; } @Override public String getPickerViewText() { return name; } public static class CityBean { 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; } } }

注意實現IPickerViewData介面,並return對應的顯示內容,程式碼中也有說明

3、SingleOptionsPicker封裝類:

public class SingleOptionsPicker<T> {

    private Activity activity;
    //回撥介面
    private OnPickerOptionsClickListener listener;
    private OptionsPickerView pvOptions;
    //一級聯動或條件資料來源
    private List<T> options1Items;
    //二級聯動資料來源
    private List<List<T>> options2Items;
     //三級聯動資料來源
    private List<List<List<T>>> options3Items;
    //預設選中的位置
    private int options1, options2, options3;

    /**
     *普通條件選擇項方法
     */
    public SingleOptionsPicker(Activity activity, String select, List<T> options1Items, OnPickerOptionsClickListener listener) {
        this.activity = activity;
        this.listener = listener;
        this.options1Items = options1Items;
        boolean isContinue = true;
        for (int i = 0; i < options1Items.size() && isContinue; i++) {
            //設定選中項
            if (select.equals(options1Items.get(i))) {
                options1 = i;
                isContinue = false;
            }
        }
        getInstance();
    }

   /**
     *三級聯動選擇項方法
     */
    public SingleOptionsPicker(Activity activity, int options1, int options2, int options3, List<T> options1Items, List<List<T>> options2Items,
                               List<List<List<T>>> options3Items, OnPickerOptionsClickListener listener) {
        this.activity = activity;
        this.listener = listener;
        this.options1 = options1;
        this.options2 = options2;
        this.options3 = options3;
        this.options1Items = options1Items;
        this.options2Items = options2Items;
        this.options3Items = options3Items;
        getInstance();
    }


    private OptionsPickerView getInstance() {
        pvOptions = new OptionsPickerBuilder(activity, new OnOptionsSelectListener() {
            @Override
            public void onOptionsSelect(int options1, int options2, int options3, View v) {
                if (listener != null) {
                    listener.onOptionsSelect(options1, options2, options3, v);
                }
            }
        })
                //分隔線顏色。
                .setDividerColor(Color.parseColor("#BBBBBB"))
                //滾輪背景顏色
                .setBgColor(Color.parseColor("#F5F5F5"))
                //設定兩橫線之間的間隔倍數
                .setLineSpacingMultiplier(1.8f)
                //設定選中項的顏色
                .setTextColorCenter(Color.parseColor("#333333"))
                //是否只顯示中間選中項的label文字,false則每項item全部都帶有label
                .isCenterLabel(true)
                ////設定選擇的三級單位
                .setLabels("", "", "")
                //標題文字
                .setTitleText("標題文字")
                //預設選中項
                .setSelectOptions(options1, options2, options3)
                .setLayoutRes(R.layout.item_picker_options, new CustomListener() {//自定義佈局
                    @Override
                    public void customLayout(View v) {
                        final TextView tvSubmit = v.findViewById(R.id.tv_finish);
                        tvSubmit.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                pvOptions.returnData();
                                pvOptions.dismiss();
                            }
                        });
                    }
                })
                .build();
        pvOptions.setPicker(options1Items, options2Items, options3Items);//三級選擇器
        return pvOptions;
    }

    public static void openOptionsPicker(Activity activity, List<String> list, final int type, final TextView textView) {
        String select = textView.getText().toString();
        new SingleOptionsPicker(activity, select, list,
                new SingleOptionsPicker.OnPickerOptionsClickListener() {
                    @Override
                    public void onOptionsSelect(int options1, int options2, int options3, View view) {
                        if (type == 1) {
                            textView.setText(options1 + "歲");
                        } else if (type == 2) {
                            //注意起始數值
                            textView.setText(options1 + 80 + "CM");
                        } else if (type == 3) {
                            textView.setText(options1 + 30 + "KG");
                        }
                    }
                }).show();

    }

    /**
     * 顯示選擇器
     */
    public void show() {
        if (pvOptions != null && !pvOptions.isShowing()) {
            pvOptions.show();
        }
    }

    /**
     * 關閉選擇器
     */
    public void dismiss() {
        if (pvOptions != null && pvOptions.isShowing()) {
            pvOptions.dismiss();
        }
    }

    /**
     * 選擇項回撥
     */
    public interface OnPickerOptionsClickListener {

        void onOptionsSelect(int options1, int options2, int options3, View view);
    }

}

對應的自定義佈局:item_picker_options

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#F5F5F5"
        android:gravity="center_vertical"
        android:padding="5dp">

        <TextView
            android:padding="10dp"
            android:id="@+id/tv_cancel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="取消" />

        <TextView
            android:padding="10dp"
            android:id="@+id/tv_unit"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:gravity="center"
            android:maxLines="1"
            android:text="標題"
            android:textColor="@color/input_hint_color" />

        <TextView
            android:padding="10dp"
            android:id="@+id/tv_finish"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:text="確認" />

    </RelativeLayout>

    <!--此部分需要完整複製過去,刪減或者更改ID會導致初始化找不到內容而報空-->
    <LinearLayout
        android:id="@+id/optionspicker"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/white"
        android:orientation="horizontal">

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

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

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

</LinearLayout>

4、TestActivity 測試類也就是使用方法:

public class TestActivity extends AppCompatActivity implements View.OnClickListener {

    private TextView textview1, textview2, textview3, textview4;
    private ArrayList<Data> options1Items = new ArrayList<>();
    private ArrayList<ArrayList<String>> options2Items = new ArrayList<>();
    private ArrayList<ArrayList<ArrayList<String>>> options3Items = new ArrayList<>();
    //預設選中項(第一次為0,0,0)
    private int select1, select2, select3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);

        textview1 = this.findViewById(R.id.textview1);
        textview2 = this.findViewById(R.id.textview2);
        textview3 = this.findViewById(R.id.textview3);
        textview4 = this.findViewById(R.id.textview4);
        textview1.setOnClickListener(this);
        textview2.setOnClickListener(this);
        textview3.setOnClickListener(this);
        textview4.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.textview1:
                List<String> list1 = new ArrayList<>();
                for (int i = 0; i < 101; i++) {
                    list1.add(i + "歲");
                }
                SingleOptionsPicker.openOptionsPicker(this, list1, 1, textview1);
                break;

            case R.id.textview2:
                List<String> list2 = new ArrayList<>();
                for (int i = 80; i < 200; i++) {
                    list2.add(i + "CM");
                }
                SingleOptionsPicker.openOptionsPicker(this, list2, 2, textview2);
                break;

            case R.id.textview3:
                List<String> list3 = new ArrayList<>();
                for (int i = 30; i < 100; i++) {
                    list3.add(i + "KG");
                }
                SingleOptionsPicker.openOptionsPicker(this, list3, 3, textview3);
                break;

            case R.id.textview4:

                //省份
                ArrayList<Data> list = new ArrayList<>();
                //新增3個個省份
                Data data1 = new Data();
                Data data2 = new Data();
                Data data3 = new Data();
                data1.setName("江西省");
                data2.setName("河南省");
                data3.setName("湖北省");
                //新增市資料(省下面的資料)
                ArrayList<Data.CityBean> cityBeans1 = new ArrayList<>();
                ArrayList<Data.CityBean> cityBeans2 = new ArrayList<>();
                ArrayList<Data.CityBean> cityBeans3 = new ArrayList<>();
                //(第一個省份下面的市資料)
                Data.CityBean cityBean1 = new Data.CityBean();
                Data.CityBean cityBean2 = new Data.CityBean();
                Data.CityBean cityBean3 = new Data.CityBean();
                cityBean1.setName("南昌");
                cityBean2.setName("九江");
                cityBean3.setName("贛州");
                cityBeans1.add(cityBean1);
                cityBeans1.add(cityBean2);
                cityBeans1.add(cityBean3);
                //(第二個省份下面的市資料)
                Data.CityBean cityBean4 = new Data.CityBean();
                Data.CityBean cityBean5 = new Data.CityBean();
                Data.CityBean cityBean6 = new Data.CityBean();
                cityBean4.setName("洛陽");
                cityBean5.setName("開封");
                cityBean6.setName("許昌");
                cityBeans2.add(cityBean4);
                cityBeans2.add(cityBean5);
                cityBeans2.add(cityBean6);
                //(第三個省份下面的市資料)
                Data.CityBean cityBean7 = new Data.CityBean();
                Data.CityBean cityBean8 = new Data.CityBean();
                Data.CityBean cityBean9 = new Data.CityBean();
                cityBean7.setName("黃岡");
                cityBean8.setName("荊州");
                cityBean9.setName("鄂州");
                cityBeans3.add(cityBean7);
                cityBeans3.add(cityBean8);
                cityBeans3.add(cityBean9);

                //為市新增區(一共為9個市)
                ArrayList<String> area1 = new ArrayList<>();
                ArrayList<String> area2 = new ArrayList<>();
                ArrayList<String> area3 = new ArrayList<>();
                ArrayList<String> area4 = new ArrayList<>();
                ArrayList<String> area5 = new ArrayList<>();
                ArrayList<String> area6 = new ArrayList<>();
                ArrayList<String> area7 = new ArrayList<>();
                ArrayList<String> area8 = new ArrayList<>();
                ArrayList<String> area9 = new ArrayList<>();
                area1.add("東湖區");
                area1.add("西湖區");
                area1.add("青雲譜區");
                area2.add("潯陽區");
                area2.add("濂溪區");
                area2.add("九江縣");
                area3.add("贛縣");
                area3.add("信豐");
                area3.add("南康");
                area4.add("西工區");
                area4.add("洛龍區");
                area4.add("澗西區");
                area5.add("鼓樓區");
                area5.add("龍亭區");
                area5.add("金明區");
                area6.add("禹州市");
                area6.add("長葛市");
                area6.add("許昌縣");
                area7.add("團風縣");
                area7.add("浠水縣");
                area7.add("羅田縣");
                area8.add("荊州區");
                area8.add("沙市區");
                area8.add("江陵縣");
                area9.add("鄂城區");
                area9.add("華容區");
                area9.add("梁子湖區");

                //將區新增至市中(27個區)
                cityBean1.setArea(area1);
                cityBean2.setArea(area2);
                cityBean3.setArea(area3);
                cityBean4.setArea(area4);
                cityBean5.setArea(area5);
                cityBean6.setArea(area6);
                cityBean7.setArea(area7);
                cityBean8.setArea(area8);
                cityBean9.setArea(area9);

                //將市新增至省中(9個市)
                data1.setCity(cityBeans1);
                data2.setCity(cityBeans2);
                data3.setCity(cityBeans3);

                //將市新增至省中(3個省)
                list.add(data1);
                list.add(data2);
                list.add(data3);

                /**
                 * 新增省份資料(也可以新增string)
                 * 注意:如果是新增的JavaBean實體,則實體類需要實現 IPickerViewData 介面,
                 * PickerView會通過getPickerViewText方法獲取字串顯示出來。
                 */
                options1Items = list;

                for (int i = 0; i < list.size(); i++) {//遍歷省份
                    ArrayList<String> CityList = new ArrayList<>();//該省的城市列表(第二級)
                    ArrayList<ArrayList<String>> Province_AreaList = new ArrayList<>();//該省的所有地區列表(第三極)
                    for (int c = 0; c < list.get(i).getCity().size(); c++) {//遍歷該省份的所有城市
                        String CityName = list.get(i).getCity().get(c).getName();
                        CityList.add(CityName);//新增城市
                        ArrayList<String> City_AreaList = new ArrayList<>();//該城市的所有地區列表
                        //如果無地區資料,建議新增空字串,防止資料為null 導致三個選項長度不匹配造成崩潰
                        if (list.get(i).getCity().get(c).getArea() == null
                                || list.get(i).getCity().get(c).getArea().size() == 0) {
                            City_AreaList.add("");
                        } else {
                            City_AreaList.addAll(list.get(i).getCity().get(c).getArea());
                        }
                        Province_AreaList.add(City_AreaList);//新增該省所有地區資料
                    }
                    options2Items.add(CityList);
                    options3Items.add(Province_AreaList);
                }

                new SingleOptionsPicker(this, select1, select2, select3,
                        options1Items, options2Items, options3Items,
                        new SingleOptionsPicker.OnPickerOptionsClickListener() {
                            @Override
                            public void onOptionsSelect(int options1, int options2, int options3, View view) {
                                //返回的分別是三個級別的選中位置
                                String string = options1Items.get(options1).getPickerViewText() +
                                        options2Items.get(options1).get(options2) +
                                        options3Items.get(options1).get(options2).get(options3);
                                textview4.setText(string);
                                //將選擇後的選中項賦值
                                select1 = options1;
                                select2 = options2;
                                select3 = options3;
                            }
                        }).show();
                break;
        }
    }
}

對應佈局:activity_test

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".activity.TestActivity">

    <TextView
        android:id="@+id/textview1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:background="#BBBBBB"
        android:gravity="center"
        android:padding="20dp"
        android:text="年齡選擇器" />

    <TextView
        android:id="@+id/textview2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:background="#BBBBBB"
        android:gravity="center"
        android:padding="20dp"
        android:text="身高選擇器" />

    <TextView
        android:id="@+id/textview3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:background="#BBBBBB"
        android:gravity="center"
        android:padding="20dp"
        android:text="體重選擇器" />

    <TextView
        android:id="@+id/textview4"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:background="#BBBBBB"
        android:gravity="center"
        android:padding="20dp"
        android:text="api資料來源" />

</LinearLayout>

github上解析的是province.json檔案,實際資料來源應該是動態的。