Android-PickerView的简单封装与使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34536167/article/details/81636414

前言:这是一款仿iOS的PickerView控件,有时间选择器和选项选择,支持年月日时分,年月日,时分等格式。

主要目的:百度上有非常多写这个开源项目的用法,不过大多数都是照搬github上面复制过来的,少有人说明该如何设置三级联动的数据源,这里将身高、体重、年龄等进行简单的封装,使用只需一句代码,如需基本使用可参考原项目链接:

https://github.com/Bigkoo/Android-PickerView

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文件,实际数据源应该是动态的。

猜你喜欢

转载自blog.csdn.net/qq_34536167/article/details/81636414