如果需要完全自定义的视图,则需要子类View(所有Android视图的超类),并提供自定义的sizing(onMeasure(...))和drawing(onDraw(...))方法:
创建您的自定义视图框架:每个自定义视图的基本相同。在这里,我们为自定义视图创建框架,该框架可以绘制一个笑脸,称为SmileyView:
public class SmileyView extends View {
private Paint mCirclePaint;
private Paint mEyeAndMouthPaint;
private float mCenterX;
private float mCenterY;
private float mRadius;
private RectF mArcBounds = new RectF();
public SmileyView(Context context) {
this(context, null, 0);
}
public SmileyView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SmileyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initPaints();
}
private void initPaints() {/* ... */}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {/* ... */}
@Override
protected void onDraw(Canvas canvas) {/* ... */}
}
初始化您的油漆:该Paint对象是你的虚拟画布的定义您的几何对象的渲染方式(如颜色,填充和中风风格等)刷。在这里,我们创建两个Paints,一个为圆形填充黄色,一个为眼睛和嘴巴绘制黑色描边:
private void initPaints() {
mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mCirclePaint.setStyle(Paint.Style.FILL);
mCirclePaint.setColor(Color.YELLOW);
mEyeAndMouthPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mEyeAndMouthPaint.setStyle(Paint.Style.STROKE);
mEyeAndMouthPaint.setStrokeWidth(16 * getResources().getDisplayMetrics().density);
mEyeAndMouthPaint.setStrokeCap(Paint.Cap.ROUND);
mEyeAndMouthPaint.setColor(Color.BLACK);
}
实现您自己的onMeasure(...)方法:这是必需的,以便父布局(例如FrameLayout)可以正确对齐您的自定义视图。它提供了一套measureSpecs,可用于确定视图的高度和宽度。在这里,我们通过确保高度和宽度相同来创建一个正方形:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int w = MeasureSpec.getSize(widthMeasureSpec);
int h = MeasureSpec.getSize(heightMeasureSpec);
int size = Math.min(w, h);
setMeasuredDimension(size, size);
}
请注意,onMeasure(...)必须至少包含对的一个调用,setMeasuredDimension(..)否则您的自定义视图将以崩溃IllegalStateException。
实现自己的onSizeChanged(...)方法:这使您可以捕获自定义视图的当前高度和宽度,以正确调整渲染代码。在这里,我们只计算中心和半径:
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mCenterX = w / 2f;
mCenterY = h / 2f;
mRadius = Math.min(w, h) / 2f;
}
实现自己的onDraw(...)方法:在这里实现视图的实际呈现。它提供了一个Canvas可以绘制的对象(Canvas有关所有可用绘制方法,请参见官方文档)。
@Override
protected void onDraw(Canvas canvas) {
// 画脸
canvas.drawCircle(mCenterX, mCenterY, mRadius, mCirclePaint);
// 吸引眼球
float eyeRadius = mRadius / 5f;
float eyeOffsetX = mRadius / 3f;
float eyeOffsetY = mRadius / 3f;
canvas.drawCircle(mCenterX - eyeOffsetX, mCenterY - eyeOffsetY, eyeRadius, mEyeAndMouthPaint);
canvas.drawCircle(mCenterX + eyeOffsetX, mCenterY - eyeOffsetY, eyeRadius, mEyeAndMouthPaint);
// mouth嘴
float mouthInset = mRadius /3f;
mArcBounds.set(mouthInset, mouthInset, mRadius * 2 - mouthInset, mRadius * 2 - mouthInset);
canvas.drawArc(mArcBounds, 45f, 90f, false, mEyeAndMouthPaint);
}
将自定义视图添加到布局:该自定义视图现在可以包含在您拥有的任何布局文件中。在这里,我们将其包装在内FrameLayout:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.app.SmileyView
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
请注意,建议在查看代码完成后构建项目。如果不进行构建,您将无法在Android Studio的预览屏幕上查看视图。
将所有内容放在一起后,启动包含上述布局的活动后,应该会出现以下屏幕: