发现了一些好的东西:
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 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 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 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
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
{
"北京": ["东城区","西城区","海淀区",...],
"新疆": ["乌鲁木齐","克拉玛依","阿勒泰"],
"重庆": ["渝中区","大渡口区", ...
....
}
最后代码在 dialog-picker中,大家可以进行自己的定制哦,UI 逻辑什么的。
代码地址
https://github.com/iielse/pickerDialog另外推荐
https://github.com/AigeStudio/WheelPicker