Templates实战之更优雅实现自定义View构造方法详解
背景
自定义View是Android开发的重要组成部分,而在自定义View的创建过程中,构造方法也是非常重要的一步。在很多情况下,我们需要给自定义View设置一些特殊的属性,或者在初始化的时候进行一些特殊的操作。这时,我们就需要对自定义View的构造方法进行改造,以便更好地满足我们的需求。
常规做法
常规的做法是通过在构造方法中增加一些参数来实现自定义View的初始化,例如:
public class CustomView extends View {
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO: 在这里进行初始化操作
}
}
在这个例子中,我们将Context和AttributeSet作为参数传入自定义View的构造方法中,然后在方法内部进行初始化操作。
更好的做法
然而,这种做法有一个不足之处,那就是如果我们需要设置的属性非常多,那么就需要增加很多个参数,导致方法很难看,而且增加了出错的风险。为了解决这个问题,我们可以使用模板模式。模板模式是一种非常常见的设计模式,它可以将公共的代码放置在一个父类中,然后让子类继承这个父类,并实现特定的逻辑。
首先,我们创建一个模板类BaseCustomView,这个类作为所有自定义View的基类,包含了一些公共的代码,例如设置padding和背景颜色等操作。然后,我们再创建一个CustomView类,继承BaseCustomView类,并在这个类中实现我们想要做的特殊操作。
示例一
public abstract class BaseCustomView extends View {
public BaseCustomView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
private void init(AttributeSet attrs) {
int padding = getResources().getDimensionPixelSize(R.dimen.dimen_8dp);
setPadding(padding, padding, padding, padding);
setBackgroundColor(Color.GRAY);
initialize(attrs);
}
protected abstract void initialize(AttributeSet attrs);
}
public class CustomView extends BaseCustomView {
private String mText;
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void initialize(AttributeSet attrs) {
TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.CustomView);
mText = ta.getString(R.styleable.CustomView_text);
ta.recycle();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.WHITE);
paint.setTextSize(getResources().getDimensionPixelSize(R.dimen.dimen_14sp));
canvas.drawText(mText, getWidth() / 2, getHeight() / 2, paint);
}
}
在这个例子中,我们创建了一个BaseCustomView类,重写了它的构造方法和初始化方法,并在这个类中进行了一些公共的操作。然后,我们创建了一个CustomView类,继承自BaseCustomView类,并重写了它的initialize方法,在这个方法中获取了我们自定义的属性text,并保存在mText变量中。在CustomView的onDraw方法中,我们使用保存的mText值来绘制一个文字。
示例二
public abstract class BaseCustomView extends View {
public BaseCustomView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
private void init(AttributeSet attrs) {
int padding = getResources().getDimensionPixelSize(R.dimen.dimen_8dp);
setPadding(padding, padding, padding, padding);
setBackgroundColor(Color.GRAY);
initialize(attrs);
}
protected abstract void initialize(AttributeSet attrs);
protected void setAutoMeasure() {
if (getLayoutParams() == null) {
setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
}
}
}
public class CustomView extends BaseCustomView {
private String mText;
private int mTextSize;
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
setAutoMeasure();
}
@Override
protected void initialize(AttributeSet attrs) {
TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.CustomView);
mText = ta.getString(R.styleable.CustomView_text);
mTextSize = ta.getDimensionPixelSize(R.styleable.CustomView_textSize, getResources().getDimensionPixelSize(R.dimen.dimen_14sp));
ta.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(), mTextSize + getPaddingTop() + getPaddingBottom());
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.WHITE);
paint.setTextSize(mTextSize);
canvas.drawText(mText, getWidth() / 2, getHeight() / 2 + mTextSize / 2, paint);
}
}
在这个例子中,我们同样创建了一个BaseCustomView类,并且重写了这个类的构造方法和初始化方法。然后,我们创建了一个CustomView类,继承自BaseCustomView类,并重写了它的initialize方法,在这个方法中获取了我们自定义的属性text和textSize,并保存在相应的变量中。在CustomView的onMeasure方法中,我们根据获取到的mTextSize值来计算CustomView的高度。最后,在CustomView的onDraw方法中,我们再次使用mTextSize值来绘制文字,同时为了达到更好的效果,我们将文字描绘在CustomView的中央。
总结
在这篇文章中,我们使用了模板模式的思想,创建了一个BaseCustomView类,并且让所有自定义View都继承自这个类。在BaseCustomView类中,我们实现了一些公共的操作,包括设置padding和背景颜色等操作。然后,在每个自定义View的子类中,我们重写了BaseCustomView类的initialize方法,并在这个方法中获取了我们自定义的属性,并保存在相应的变量中。通过这种方式,我们可以更好地实现自定义View的构造方法,使代码更加简洁、清晰。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Templates实战之更优雅实现自定义View构造方法详解 - Python技术站