Android-PickerView的簡單封裝與使用
阿新 • • 發佈:2019-01-07
前言:這是一款仿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檔案,實際資料來源應該是動態的。