发现了一些好的东西:
https://github.com/weidongjian/androidWheelView
曾经找到过 WheelView。当时江湖救急,直接用了。数据源太大的话会导致性能降低。
当时有吐槽如果有使用自定义view或者继承ListView、RecyclerView的就好。
今日找到了使用自定义view方法写的。
红色为源码, 蓝色为哥写的对应扩展。
核心源码为LoopView,本来想看看实现原理方法,奈何源码被下了毒。
不过值得庆幸的是核心api还在
有了这些东西那么就可以自己进行一些定制了。
public class DataPickerDialog extends Dialog { private Params params; public DataPickerDialog(Context context, int themeResId) { super(context, themeResId); } private void setParams(DataPickerDialog.Params params) { this.params = params; } public interface OnDataSelectedListener { void onDataSelected(String itemValue); } private static final class Params { private boolean shadow = true; private boolean canCancel = true; private LoopView loopData; private String title; private String unit; private int initSelection; private OnDataSelectedListener callback; private final List<String> dataList = new ArrayList<>(); } public static class Builder { private final Context context; private final DataPickerDialog.Params params; public Builder(Context context) { this.context = context; params = new DataPickerDialog.Params(); } private final String getCurrDateValue() { return params.loopData.getCurrentItemValue(); } public Builder setData(List<String> dataList) { params.dataList.clear(); params.dataList.addAll(dataList); return this; } public Builder setTitle(String title) { params.title = title; return this; } public Builder setUnit(String unit) { params.unit = unit; return this; } public Builder setSelection(int selection) { params.initSelection = selection; return this; } public Builder setOnDataSelectedListener(OnDataSelectedListener onDataSelectedListener) { params.callback = onDataSelectedListener; return this; } public DataPickerDialog create() { final DataPickerDialog dialog = new DataPickerDialog(context, params.shadow ? R.style.Theme_Light_NoTitle_Dialog : R.style.Theme_Light_NoTitle_NoShadow_Dialog); View view = LayoutInflater.from(context).inflate(R.layout.layout_picker_data, null); if (!TextUtils.isEmpty(params.title)) { TextView txTitle = (TextView) view.findViewById(R.id.tx_title); txTitle.setText(params.title); } if (!TextUtils.isEmpty(params.unit)) { TextView txUnit = (TextView) view.findViewById(R.id.tx_unit); txUnit.setText(params.unit); } final LoopView loopData = (LoopView) view.findViewById(R.id.loop_data); loopData.setArrayList(params.dataList); loopData.setNotLoop(); if (params.dataList.size() > 0) loopData.setCurrentItem(params.initSelection); view.findViewById(R.id.tx_finish).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); if (params.callback != null) params.callback.onDataSelected(getCurrDateValue()); } }); Window win = dialog.getWindow(); win.getDecorView().setPadding(0, 0, 0, 0); WindowManager.LayoutParams lp = win.getAttributes(); lp.width = WindowManager.LayoutParams.MATCH_PARENT; lp.height = WindowManager.LayoutParams.WRAP_CONTENT; win.setAttributes(lp); win.setGravity(Gravity.BOTTOM); win.setWindowAnimations(R.style.Animation_Bottom_Rising); dialog.setContentView(view); dialog.setCanceledOnTouchOutside(params.canCancel); dialog.setCancelable(params.canCancel); params.loopData = loopData; dialog.setParams(params); return dialog; } } }
那么在Activity中
private final void showDialog() { DataPickerDialog.Builder builder = new DataPickerDialog.Builder(this); List<String> data = Arrays.asList(new String[]{"a", "b", "c", "d", "e", "f", "g", "h"}); DataPickerDialog dialog = builder.setUnit("单位").setData(data).setSelection(1).setTitle("标题") .setOnDataSelectedListener(new DataPickerDialog.OnDataSelectedListener() { @Override public void onDataSelected(String itemValue) { Toast.makeText(getApplicationContext(), itemValue, Toast.LENGTH_SHORT).show(); } }).create(); dialog.show(); }以上标准通用的选择器就可以直接用上啦。
public DatePickerDialog create() { final DatePickerDialog dialog = new DatePickerDialog(context, params.shadow ? R.style.Theme_Light_NoTitle_Dialog : R.style.Theme_Light_NoTitle_NoShadow_Dialog); View view = LayoutInflater.from(context).inflate(R.layout.layout_picker_date, null); final LoopView loopDay = (LoopView) view.findViewById(R.id.loop_day); loopDay.setArrayList(d(1, 30)); loopDay.setCurrentItem(15); loopDay.setNotLoop(); Calendar c = Calendar.getInstance(); int year = c.get(Calendar.YEAR); final LoopView loopYear = (LoopView) view.findViewById(R.id.loop_year); loopYear.setArrayList(d(MIN_YEAR, year - MIN_YEAR + 1)); loopYear.setCurrentItem(year - MIN_YEAR - 25); loopYear.setNotLoop(); final LoopView loopMonth = (LoopView) view.findViewById(R.id.loop_month); loopMonth.setArrayList(d(1, 12)); loopMonth.setCurrentItem(6); loopMonth.setNotLoop(); final LoopListener maxDaySyncListener = new LoopListener() { @Override public void onItemSelect(int item) { Calendar c = Calendar.getInstance(); c.set(Integer.parseInt(loopYear.getCurrentItemValue()), Integer.parseInt(loopMonth.getCurrentItemValue()) - 1, 1); c.roll(Calendar.DATE, false); int maxDayOfMonth = c.get(Calendar.DATE); int fixedCurr = loopDay.getCurrentItem(); loopDay.setArrayList(d(1, maxDayOfMonth)); // 修正被选中的日期最大值 if (fixedCurr > maxDayOfMonth) fixedCurr = maxDayOfMonth - 1; loopDay.setCurrentItem(fixedCurr); } }; loopYear.setListener(maxDaySyncListener); loopMonth.setListener(maxDaySyncListener); view.findViewById(R.id.tx_finish).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); params.callback.onDateSelected(getCurrDateValues()); } }); Window win = dialog.getWindow(); win.getDecorView().setPadding(0, 0, 0, 0); WindowManager.LayoutParams lp = win.getAttributes(); lp.width = WindowManager.LayoutParams.MATCH_PARENT; lp.height = WindowManager.LayoutParams.WRAP_CONTENT; win.setAttributes(lp); win.setGravity(Gravity.BOTTOM); win.setWindowAnimations(R.style.Animation_Bottom_Rising); dialog.setContentView(view); dialog.setCanceledOnTouchOutside(params.canCancel); dialog.setCancelable(params.canCancel); params.loopYear = loopYear; params.loopMonth = loopMonth; params.loopDay = loopDay; dialog.setParams(params); return dialog; }maxDaySyncListener 将调用 loopDay.setCurrentItem() 修正日期的错误。
地域选择器
ta的不同之处在于数据源,然后联动。
Map<String, List<String>>
Key表示城市.value表示区域
public Builder(Context context) { this.context = context; params = new RegionPickerDialog.Params(); try { InputStreamReader inputReader = new InputStreamReader(context.getAssets().open("city_data.json")); BufferedReader bufReader = new BufferedReader(inputReader); String line = ""; StringBuffer result = new StringBuffer(); while ((line = bufReader.readLine()) != null) { result.append(line); } params.dataList = new Gson().fromJson(result.toString(), new TypeToken<Map<String, List<String>>>() { }.getType()); } catch (Exception e) { Log.e("RegionPickerDialog", "The Region source file does not exist or has been damaged"); params.dataList = new HashMap<>(); } }
{ "北京": ["东城区","西城区","海淀区",...], "新疆": ["乌鲁木齐","克拉玛依","阿勒泰"], "重庆": ["渝中区","大渡口区", ... .... }
最后代码在 dialog-picker中,大家可以进行自己的定制哦,UI 逻辑什么的。
代码地址
https://github.com/iielse/pickerDialog
另外推荐
https://github.com/AigeStudio/WheelPicker