1.创建自定义控件
App->New->Ui Component ->Custom View,创建一个ATank控件
生成三个文件
1.ATank.Java
2.Sample_a_tank.xml
3.attrs_a_tank.xml
首先看一下 attrs_a_tank.xml
<resources>
<declare-styleable name="ATank">
<attr name="exampleString" format="string" />
<attr name="exampleDimension" format="dimension" />
<attr name="exampleColor" format="color" />
<attr name="exampleDrawable" format="color|reference" />
</declare-styleable>
</resources>
再看一下
ATank.Java
public class ATank extends View {
private String mExampleString; // 在xml定义字符属性
private int mExampleColor = Color.RED; //颜色属性
private float mExampleDimension = 0; // 尺度
private Drawable mExampleDrawable;//背景
private TextPaint mTextPaint; //绘制字符
private float mTextWidth; //字符宽度
private float mTextHeight; //字符高度
public ATank(Context context) { //构造1
super(context);
init(null, 0);
}
public ATank(Context context, AttributeSet attrs) { //构造2
super(context, attrs);
init(attrs, 0);
}
public ATank(Context context, AttributeSet attrs, int defStyle) { //构造3
super(context, attrs, defStyle);
init(attrs, defStyle);
}
private void init(AttributeSet attrs, int defStyle) { //初始化
// Load attributes 从xml中加载属性
final TypedArray a = getContext().obtainStyledAttributes(
attrs, R.styleable.ATank, defStyle, 0);
mExampleString = a.getString(
R.styleable.ATank_exampleString);
mExampleColor = a.getColor(
R.styleable.ATank_exampleColor,
mExampleColor);
// Use getDimensionPixelSize or getDimensionPixelOffset when dealing with
// values that should fall on pixel boundaries.
mExampleDimension = a.getDimension(
R.styleable.ATank_exampleDimension,
mExampleDimension);
//获取背景参数属性
if (a.hasValue(R.styleable.ATank_exampleDrawable)) {
mExampleDrawable = a.getDrawable(
R.styleable.ATank_exampleDrawable);
mExampleDrawable.setCallback(this);
}
a.recycle(); //释放该实例,从而使其可被其他模块复用。
// //设置字符参数属性 1
mTextPaint = new TextPaint();
mTextPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
//Paint.FILTER_BITMAP_FLAG是使位图过滤的位掩码标志
//Paint.ANTI_ALIAS_FLAG是使位图抗锯齿的标志
//Paint.DITHER_FLAG是使位图进行有利的抖动的位掩码标志
mTextPaint.setTextAlign(Paint.Align.LEFT);
//设置字符参数属性 2
invalidateTextPaintAndMeasurements();
}
//获取字符尺度属性
private void invalidateTextPaintAndMeasurements() {
mTextPaint.setTextSize(mExampleDimension);
mTextPaint.setColor(mExampleColor);
mTextWidth = mTextPaint.measureText(mExampleString);
Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
mTextHeight = fontMetrics.bottom;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// TODO: consider storing these as member variables to reduce
// allocations per draw cycle. 边界宽度
int paddingLeft = getPaddingLeft();
int paddingTop = getPaddingTop();
int paddingRight = getPaddingRight();
int paddingBottom = getPaddingBottom();
int contentWidth = getWidth() - paddingLeft - paddingRight; //内容宽度
int contentHeight = getHeight() - paddingTop - paddingBottom;
// Draw the text. 放到 Content的中间
canvas.drawText(mExampleString,
paddingLeft + (contentWidth - mTextWidth) / 2, //字符位置计算x
paddingTop + (contentHeight + mTextHeight) / 2,
mTextPaint);
// X+mTextWidth()/2 = (getWidth()-paddingRight-paddingLeft)/2 + paddingLeft
// X=[(getWidth()-paddingRight-paddingLeft) - mTextWidth()]/2 +paddingLeft
// // Draw the example drawable on top of the text.
if (mExampleDrawable != null) {
mExampleDrawable.setBounds(paddingLeft, paddingTop,
paddingLeft + contentWidth, paddingTop + contentHeight);
mExampleDrawable.draw(canvas);
}
}
}
在Activity_main.xml 中加入控件
<com.example.tankcombat.ATank
android:layout_width="300dp"
android:layout_height="300dp"
android:background="#ccc"
android:paddingLeft="20dp"
android:paddingBottom="40dp"
app:exampleColor="#33b5e5"
app:exampleDimension="24sp"
app:exampleString="Hello, ATank"
tools:ignore="MissingConstraints" />
字符定位的X,Y计算:
int contentWidth = getWidth() - paddingLeft - paddingRight;
int contentHeight = getHeight() - paddingTop - paddingBottom;
// Draw the text.
canvas.drawText(mExampleString,
paddingLeft + (contentWidth - mTextWidth) / 2,
paddingTop + (contentHeight + mTextHeight) / 2,
mTextPaint);