Android建造者设计模式实现自定义Toast
2017-07-03 本文已影响290人
任珉豪
原生的吐司是在屏幕下面弹出,新的需求是在屏幕中间弹出,并且布局需要自定义。
建造者模式:
建造者模式是将一个复杂对象的创建过程给封装起来,客户只需要知道可以利用对象名或者类型就能够得到一个完整的对象实例,而不需要关心对象的具体创建过程。
为什么要用设计模式?
可实现链式调用
详细代码
final public class DialogBundle {
private static float scale_num = 160;
DialogBundle() {
}
/**
* 显示Toast类型的Dialog:中间Dialog
*/
public static class ToastDialog extends Toast {
static public class Builder {
Context context;
CharSequence alert;
int delay;
public Builder(Context context) {
this.context = context;
}
public Builder setAlert(String alert) {
this.alert = alert;
return this;
}
public Builder setAlert(int alert) {
this.alert = this.context.getResources().getText(alert);
return this;
}
public ToastDialog build() {
return new ToastDialog(context, this);
}
}
//VIEW ROOT
LinearLayout ll_root;
//ALERT
TextView tv_alert;
//handler
Handler handler;
//builder
int delay;
//默认延时
final int defaultDelay = 2000;
final int minimumWidth = 270;
final int padding_30 = 30;
final int padding_3 = 3;
final int shapeSize = 10;
final int textSize = 15;
final int zero_num = 0;
ToastDialog(Context context, Builder builder) {
super(context);
//UI
{
ll_root = new LinearLayout(context);
//样式
{
ll_root.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
ll_root.setOrientation(LinearLayout.VERTICAL);
ll_root.setMinimumWidth(dp2px(context, minimumWidth));
ll_root.setPadding(dp2px(context, padding_30), dp2px(context, padding_3), dp2px(context, padding_30), dp2px(context, padding_3));
ll_root.setGravity(Gravity.CENTER);
RoundRectShape roundRectShape = new RoundRectShape(new float[]{shapeSize, shapeSize, shapeSize, shapeSize, shapeSize, shapeSize, shapeSize, shapeSize}, null, null);
ShapeDrawable drawable = new ShapeDrawable(roundRectShape);
drawable.getPaint().setColor(ContextCompat.getColor(context,R.color.cl_7f333333));
drawable.getPaint().setStyle(Paint.Style.FILL_AND_STROKE);
ll_root.setBackgroundDrawable(drawable);
}
//子VIEW
{
//ALERT
{
tv_alert = new TextView(context);
ll_root.addView(tv_alert);
//样式
{
tv_alert.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
tv_alert.setTextColor(ContextCompat.getColor(context,R.color.cl_ffffff));
tv_alert.setTextSize(textSize);
tv_alert.setBackgroundColor(ContextCompat.getColor(context,R.color.cl_00000000));
tv_alert.setGravity(Gravity.CENTER);
}
}
}
}
//配置
{
setView(ll_root);
setGravity(Gravity.CENTER, zero_num, zero_num);
setDuration(Toast.LENGTH_SHORT);
if (builder.alert != null && builder.alert.length() > zero_num) {
tv_alert.setText(builder.alert);
tv_alert.setVisibility(View.VISIBLE);
}
this.delay = builder.delay <= zero_num ? defaultDelay : builder.delay;
this.handler = new Handler(Looper.getMainLooper());
}
}
@Override
public void show() {
//判断是主线程 还是子线程 放在上层做
super.show();
handler.postDelayed(new Runnable() {
@Override
public void run() {
ToastDialog.this.cancel();
}
}, this.delay);
}
}
/**
* dp转 px.
*
* @param value the value
* @return the int
*/
private static int dp2px(Context context, float value) {
final float scale = context.getResources().getDisplayMetrics().densityDpi;
return (int) (value * (scale / scale_num) + 0.5f);
}
}
代码调用
new DialogBundle.ToastDialog.Builder(AppProfile.getContext()).setAlert(resId).build().show();
反思
类似的控件封装,比如对话框,你是否也会用这种封装技巧了呢?
总结
DialogBundle : 控件集合类
ToastDialog:具体生成的子控件类
Builder:每个控件的建造类
setAlert:Builder中的方法,生成具体的子控件对象
具体的创建细节放入ToastDialog的构造方法中。
可加群交流:136705426