Lib_Dialog是对封装DialogFragment的Dialog模块,使用链式调用对Dialog进行设置。
Lib_Dialog有良好的扩展性,有两个方便使用继承类:一个是CustomDialog,继承于BaseDialogFragment,用于实现布局简单的自定义View的Dialog;一个是DefinedDialog,直接继承于DialogFragment,用于直接使用系统的Dialog和已定义好的Dialog(已定义好的Dialog本可以直接继承DialogFragment来扩展,DefinedDialog统一了调用风格。
在封装的基础上重写了选项选择器和时间选择器,选项选择器分别有单项选择器、多项(最多三项)不联动选择器和多项联动选择器。
参考了两个开源项目NiceDialog和Android-PickerView。
CustomDialog使用示例:
public void showCustom(View view) {
CustomDialog.init()
.setLayoutId(R.layout.dialog_confirm)//布局
.setConvertListener(new ViewConvertListener() {//设置UI的样式
@Override
public void convertView(ViewHolder holder, final BaseDialogFragment dialogFragment) {
holder.setText(R.id.title, "提示");
holder.setTextColor(R.id.title, getResources().getColor(R.color.title_red));
holder.setText(R.id.message, "您已支付成功!");
holder.setBackgroundColor(R.id.message, Color.GRAY);
holder.setOnClickListener(R.id.cancel, new View.OnClickListener() {
@Override
public void onClick(View v) {
dialogFragment.dismiss();
}
});
holder.setOnClickListener(R.id.ok, new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "onClicked Confirm",
Toast.LENGTH_SHORT).show();
dialogFragment.dismiss();
}
});
}
})
// .setStyleId(R.style.LibDialog)//风格
// .setAnimStyleId(R.style.DefaultAnimation)//动画
// .setWidth(WindowManager.LayoutParams.MATCH_PARENT)//宽度,可以是MATCH_PARENT、WRAP_CONTENT和具体数值
// .setHeight(WindowManager.LayoutParams.WRAP_CONTENT)//高度,同上
// .setHMargin(200)//水平方向边距
// .setHMargin(200)//垂直方向边距
.setOutCancelable(false)//点击外部是否隐藏
.setX(100)//相对于原始位置的x坐标偏移
.setY(200)//y坐标偏移
.setGravity(Gravity.START|Gravity.TOP)//显示位置
.setDimAmount(0.4f)//灰度值
.showDialog(getSupportFragmentManager(), "custom");
}
其中,ViewConvertListener用于设置Dialog中view的样式,包括字体大小、字体颜色、背景、点击事件。
注意,init()放在最前面,子类的方法优先在前面调用,如上,setLayoutId()和setConvertListener()是CustomDialog的方法,需要放在前面,其它属性的设置方法是BaseDialogFragment所有,放在后面。
DefinedDialog使用示例:
public void showSystem(View view) {
DefinedDialog.init()
.setInitDialogListener(new InitDialogListener() {//返回已定义的dialog
@Override
public Dialog create() {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("系统dialog")
.setMessage("测试已有的dialog")
.setPositiveButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this, "点击取消", Toast.LENGTH_SHORT).show();
}
})
.setNegativeButton("测试", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this, "test", Toast.LENGTH_SHORT).show();
}
})
.setCancelable(false);
return builder.create();
}
})
.showDialog(getSupportFragmentManager(), "system");
}
DefinedDialog只有以上代码中的方法,Dialog的设置全部由定义好的Dialog自己封装。
注意,DefinedDialog必须设置InitDialogListener,用来创建已有的Dialog,否则,会抛出错误。
WheelView是一个3D滚动控件,在原有基础上了做了一些改动,完善接口封装,可以单独使用,可通过xml布局文件设置WheelView的属性,见R.styleable.WheelView。也可以通过代码设置,见下:
private String mLabel;// 附加单位
private int mTextSize;// 选项的文字大小
private int mOutTextColor = 0xffa8a8a8;
private int mCenterTextColor = 0xff2a2a2a;
private int mDividerColor = 0xffd5d5d5;
boolean mLoop;// item是否循环
private int mGravity = Gravity.CENTER;
private float mLineSpaceMultiplier = LINE_SPACE_MULTIPLIER;// 条目间距倍数,限制为1.0~2.0
实现原理见Android-PickerView系列之源码解析篇(二)
单项选择器。
使用示例:
public void showOption(View view) {
final ArrayList list = new ArrayList<>(20);
for (int i = 0; i < 20; i++) {
list.add("数据" + i);
}
SingleOptionDialog.init(list)
.setTitle("单项选择器")//设置标题
.setSelectPosition(5)//设置居中项
.setConvertListener(new ViewConvertListener() {//设置UI样式
@Override
public void convertView(ViewHolder holder, BaseDialogFragment dialogFragment) {
holder.setTextColor(R.id.tv_confirm, Color.YELLOW);
holder.setTextColor(R.id.tv_title, Color.LTGRAY);
}
})
.setWheelViewSetListener(new OnWheelViewSetListener() {//设置WheelView样式
@Override
public void setWheelView(WheelView wheelView) {
wheelView.setTextSize(30);
wheelView.setDividerColor(Color.RED);
wheelView.setCenterTextColor(Color.RED);
}
})
.setOptionSelectListener(new OnOptionSelectListener() {//设置选中回调
@Override
public void onOptionSelect(int option) {
Toast.makeText(MainActivity.this, list.get(option), Toast.LENGTH_SHORT).show();
}
})
.showDialog(getSupportFragmentManager(), "option");
}
可通过ViewConvertListener设置包裹WheelView的外部布局的样式,还有OnWheelViewSetListener用于设置WheelView的属性,OnOptionSelectListener用于设置点击右上角确认按钮时的回调。
多项联动选择器,最多三项,主要用于选择省市县地址。
使用示例:
public void showLinkedOptions(View view) {
final ArrayList list1 = new ArrayList<>(20);
final ArrayList> list2 = new ArrayList<>(20);
final ArrayList>> list3 = new ArrayList<>(20);
for (int i = 0; i < 20; i++) {
list1.add("一级" + i);
list2.add(new ArrayList(20));
list3.add(new ArrayList>(20));
for (int j = 0; j < 20; j++) {
list2.get(i).add("二级" + "-" + i + "-" + j);
list3.get(i).add(new ArrayList(20));
for (int k = 0; k < 20; k++) {
list3.get(i).get(j).add("三级" + "-" + i + "-" + j + "-" + k);
}
}
}
LinkedOptionsDialog.init(list1, list2, list3)
.setTitle("三级联动")
.setWheelViewsSetListener(new OnWheelViewsSetListener() {//设置WheelView样式
@Override
public void setWheelViews(WheelView wheelView1, WheelView wheelView2, WheelView wheelView3) {
wheelView1.setOutTextColor(Color.RED);
}
})
.setOptionsSelectListener(new OnOptionsSelectListener() {
@Override
public void onOptionsSelect(int position1, int position2, int position3) {
Toast.makeText(MainActivity.this,
list1.get(position1) + "~" + list2.get(position1).get(position2) + "~" + list3.get(position1).get(position2).get(position3),
Toast.LENGTH_SHORT).show();
}
})
.showDialog(getSupportFragmentManager(), "threeLinked");
}
其中,LinkedOptionsDialog可通过ViewConvertListener设置包裹WheelView的外部UI的样式,通过OnWheelViewsSetListener设置WheelView的属性,通过OnOptionsSelectListener设置点击右上角确认按钮时的回调。
注意,LinkedOptionsDialog通过泛型控制实体类形参,对于数字或String,使用init(List,List,List)做初始化;对于其他实体类,需要实现IPickerViewEntity接口,用于在获取绘制在WheelView中的内容,还需要实现Serializable接口,因为保存信息的时候需要序列化(说明,ArrayList不支持Parcelable序列化,为了简单统一,选项选择器中的实体类都使用Serializable),初始化使用init()方法,然后调用setOptionsList(ArrayList, ArrayList, ArrayList)方法设置实体类数据列表。
多项非联动选择器,最多三项。
使用示例:
public void showUnLinkedOptions(View view) {
final ArrayList list1 = new ArrayList<>(20);
final ArrayList list2 = new ArrayList<>(20);
final ArrayList list3 = new ArrayList<>(20);
for (int i = 0; i < 20; i++) {
list1.add("一级数据" + i);
list2.add("二级数据" + i);
list3.add("三级数据" + i);
}
UnLinkedOptionsDialog.init(list1, list2, list3)
.setTitle("三级非联动")
.setSelectPositions(2, 3, 4)
.setOptionsSelectListener(new OnOptionsSelectListener() {
@Override
public void onOptionsSelect(int position1, int position2, int position3) {
Toast.makeText(MainActivity.this, list1.get(position1) + list2.get(position2) + list3.get(position3),
Toast.LENGTH_SHORT).show();
}
})
.showDialog(getSupportFragmentManager(), "threeUnLinked");
}
UnLinkedOptionsDialog使用类似于LinkedOptionsDialog,更加简单。
时间选择器,支持年月日时分秒,默认只显示年月日。其中年月日可以设置起始和结束时间边界,默认1900~2100;年月日时分秒可以设置选中居中的值,默认当前时间。
使用示例:
public void showTime(View view) {
TimeDialog.init()//默认时间为当前时间
.setTitle("时间选择器")
.setMvVisibility(true, true, true, true, true, true)//设置显示的WheelView,对应年月日时分秒
.setInitTimeRangeListener(new InitTimeRangeListener() {//设置时间范围,只支持年月日
@Override
public Calendar getStartCalendar() {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 2010);
calendar.set(Calendar.MONTH, 0);
calendar.set(Calendar.DAY_OF_MONTH, 10);
// calendar.set(Calendar.HOUR_OF_DAY, 8);
// calendar.set(Calendar.MINUTE, 20);
// calendar.set(Calendar.SECOND, 10);
return calendar;//2010.1.10 8:20:10
}
@Override
public Calendar getEndCalendar() {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 2020);
calendar.set(Calendar.MONTH, 9);
calendar.set(Calendar.DAY_OF_MONTH, 30);
// calendar.set(Calendar.HOUR_OF_DAY, 22);
// calendar.set(Calendar.MINUTE, 30);
// calendar.set(Calendar.SECOND, 30);
return calendar;//2020.10.30 22:30:30
}
@Override
public Calendar getSelectedCalendar() {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 2019);
calendar.set(Calendar.MONTH, 9);
calendar.set(Calendar.DAY_OF_MONTH, 18);
calendar.set(Calendar.HOUR_OF_DAY, 12);
calendar.set(Calendar.MINUTE, 30);
calendar.set(Calendar.SECOND, 25);
return calendar;//2019.10.18 12:30:25
}
})
// .setSelectedTime(Calendar)//另一个设置居中时间的方法
// .setRangeTime(Calendar, Calendar)//另一个设置时间范围的方法
.setOnTimeSelectListener(new OnTimeSelectListener() {//设置回调
@Override
public void onTimeSelect(Date date) {
DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Toast.makeText(MainActivity.this, DATE_FORMAT.format(date), Toast.LENGTH_SHORT).show();
}
})
.showDialog(getSupportFragmentManager(), "time");
}
TimeDialog可以设置包裹WheelView外部的UI,也可以设置WheelView的属性。
另外,InitTimeRangeListener用于设置起始时间和结束时间的边界,以及居中选中时间。OnTimeSelectListener用于回调右上角点击确认事件,返回一个Date。
- 当
WheelView中绘制的内容过长时,可能会和Label重叠,可能会超出WheelView的宽度; - 目前默认
Lable固定绘制在居中WheelView的右侧,如果想让每个WheelView都带Label的话,只能把Label添加到实体类中; WheelView默认展示11个Item,不可修改;这样,WheelView的高度由文字大小和间距决定。文字很大时,UI会有影响。
NiceDialog
Android-PickerView.
有问题请联系邮箱ymwm116@163.com,欢迎交流,提出修改建议。