[1] Android如何绘制视图?
当用户将Android视图引入焦点时,Android框架会引导视图进行绘制。这个绘图过程包括3个阶段:
measure 测量
测量 view 的宽和高。
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
setMeasuredDimension(getDefaultSize(
getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(),heightMeasureSpec));
}
layout 布局
确定 view 在父容器中的放置位置。
protected void onLayout(boolean changed, int l, int t, int r, int b){
if (mOrientation == VERTICAL){
layoutVertical(l, t, r, b);
}
else{
layoutHorizontal(l, t, r, b);
}
}
draw 绘制
负责将 view 绘制到屏幕上。
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Draw the shadow
canvas.drawOval(
mShadowBounds,
mShadowPaint
);
// Draw the label text
canvas.drawText(mData.get(mCurrentItem).mLabel, mTextX, mTextY, mTextPaint);
// Draw the pie slices
for (int i = 0; i < mData.size(); ++i) {
Item it = mData.get(i);
mPiePaint.setShader(it.mShader);
canvas.drawArc(mBounds,
360 - it.mEndAngle,
it.mEndAngle - it.mStartAngle,
true, mPiePaint);
}
// Draw the pointer
canvas.drawLine(mTextX, mPointerY, mPointerX, mPointerY, mTextPaint);
canvas.drawCircle(mPointerX, mPointerY, mPointerSize, mTextPaint);
}
[2] View的位置参数
View 的位置主要由它的四个顶点来决定,分别对应于 View 的四个属性:top、left、right、bottom。
其中 top 是左上角纵坐标,left 是左上角横坐标,right是右下角横坐标,bottom是右下角纵坐标。
图片来源于 Android 开发艺术探索
mLeft = getLeft();
mRight = getRight();
mBootom = getBottom();
mTop = getTop();
public final int getWidth(){
return mRight - mLeft;
}
public final int getHeight(){
return mBootom - mTop;
}
[3] 自定义View
先画一个简单的静态棋盘,如下图(好丑,莫笑,但是可以实现一直都是我赢,电脑输):
2017-10-6
代码实现:
package com.example.sweetgirl.customizeview.chess;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;
/**
* 象棋
* Created by sweetgirl on 2017/9/21
*/
public class ChessView extends View{
Paint paint;
public ChessView(Context context) {
super(context);
paint = new Paint();
paint.setColor(Color.BLACK);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(3);
paint.setTextSize(40);
}
/**
* 先画横线,top--bottom , 再画竖线 left--right
* @param canvas
*/
protected void onDraw(Canvas canvas) {
//top
paint.setColor(Color.BLACK);
canvas.drawLine(30, 30, 450, 30, paint);
canvas.drawLine(30, 100, 450, 100, paint);
canvas.drawLine(30, 170, 450, 170, paint);
canvas.drawLine(30, 240, 450, 240, paint);
canvas.drawLine(30, 310, 450, 310, paint);
// bottom
canvas.drawText(" 楚 河 ", 65, 355, paint);
canvas.drawText(" 汉 界 ", 320, 355, paint);
canvas.drawLine(30, 380, 450, 380, paint);
canvas.drawLine(30, 450, 450, 450, paint);
canvas.drawLine(30, 520, 450, 520, paint);
canvas.drawLine(30, 590, 450, 590, paint);
canvas.drawLine(30, 660, 450, 660, paint);
//left
canvas.drawLine(30, 30, 30, 660, paint);
canvas.drawLine(83, 30, 83, 310, paint);
canvas.drawLine(136, 30, 136, 310, paint);
canvas.drawLine(189, 30, 189, 310, paint);
canvas.drawLine(242, 30, 242, 310, paint);
canvas.drawLine(294, 30, 294, 310, paint);
canvas.drawLine(347, 30, 347, 310, paint);
canvas.drawLine(398, 30, 398, 310, paint);
//right
canvas.drawLine(83, 380, 83,660, paint);
canvas.drawLine(136, 380, 136,660, paint);
canvas.drawLine(189, 380, 189,660, paint);
canvas.drawLine(242, 380, 242,660, paint);
canvas.drawLine(294, 380, 294,660, paint);
canvas.drawLine(347, 380, 347,660, paint);
canvas.drawLine(398, 380, 398,660, paint);
canvas.drawLine(450,30 ,450,660, paint);
//大营
canvas.drawLine(189, 30, 294,170, paint);
canvas.drawLine(294, 30, 189,170, paint);
canvas.drawLine(189,520, 294,660, paint);
canvas.drawLine(294,520, 189,660, paint);
//circle
paint.setColor(Color.YELLOW);
canvas.drawCircle(450, 240,20, paint);
canvas.drawCircle(346, 240,20, paint);
canvas.drawCircle(242, 240,20, paint);
canvas.drawCircle(396, 170,20, paint);
canvas.drawCircle(450, 30,20, paint);
canvas.drawCircle(396, 30,20, paint);
canvas.drawCircle(346, 30,20, paint);
canvas.drawCircle(294, 30,20, paint);
canvas.drawCircle(242, 30,20, paint);
canvas.drawCircle(189, 30,20, paint);
canvas.drawCircle(135, 30,20, paint);
canvas.drawCircle(83, 30,20, paint);
canvas.drawCircle(30, 30,20 , paint);
canvas.drawCircle(83, 170,20, paint);
canvas.drawCircle(135, 240,20, paint);
canvas.drawCircle(30, 240,20, paint);
canvas.drawCircle(450, 450,20, paint);
canvas.drawCircle(346, 450,20, paint);
canvas.drawCircle(242, 450,20, paint);
canvas.drawCircle(396, 520,20, paint);
canvas.drawCircle(450, 660,20, paint);
canvas.drawCircle(396, 660,20, paint);
canvas.drawCircle(346, 660,20, paint);
canvas.drawCircle(294, 660,20, paint);
canvas.drawCircle(242, 660,20, paint);
canvas.drawCircle(189, 660,20, paint);
canvas.drawCircle(135, 660,20, paint);
canvas.drawCircle(83, 660,20, paint);
canvas.drawCircle(30, 660,20, paint);
canvas.drawCircle(83, 520,20, paint);
canvas.drawCircle(135, 450,20, paint);
canvas.drawCircle(30, 450,20, paint);
//text
paint.setColor(Color.RED);
paint.setTextSize(20);
canvas.drawText("兵", 21,458, paint);
canvas.drawText("兵", 127,458, paint);
canvas.drawText("兵", 232,458 , paint);
canvas.drawText("炮", 388,527, paint);
canvas.drawText("车", 440,668 , paint);
canvas.drawText("馬", 388,668 , paint);
canvas.drawText("象", 335,668 , paint);
canvas.drawText("仕", 285,668 , paint);
canvas.drawText("帥", 232,668 , paint);
canvas.drawText("仕", 180,668 , paint);
canvas.drawText("象", 127,668 , paint);
canvas.drawText("馬", 72,668 , paint);
canvas.drawText("车", 21,668 , paint);
canvas.drawText("炮", 72, 527, paint);
canvas.drawText("兵", 335,458 , paint);
canvas.drawText("兵", 440,458, paint);
paint.setColor(Color.BLACK);
canvas.drawText("卒", 21,245, paint);
canvas.drawText("卒", 127,245, paint);
canvas.drawText("卒", 232,245 , paint);
canvas.drawText("炮", 72, 177, paint);
canvas.drawText("车", 21,35 , paint);
canvas.drawText("馬", 72,35 , paint);
canvas.drawText("象", 127,35 , paint);
canvas.drawText("士", 180,35 , paint);
canvas.drawText("将", 232,35 , paint);
canvas.drawText("士", 285,35 , paint);
canvas.drawText("象", 335,35 , paint);
canvas.drawText("馬", 388,35 , paint);
canvas.drawText("车", 440,35 , paint);
canvas.drawText("炮", 388, 177, paint);
canvas.drawText("卒", 335,247 , paint);
canvas.drawText("卒", 440,247, paint);
}
}
在 layout 中引用:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_chess_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.sweetgirl.customizeview.activity.ChessViewActivity">
<com.example.sweetgirl.customizeview.chess.ChessView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/cv_chess"/>
</RelativeLayout>
在 Activity 中实现:
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.example.sweetgirl.customizeview.R;
import com.example.sweetgirl.customizeview.chess.ChessView;
public class ChessViewActivity extends AppCompatActivity {
private ChessView chessView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chess_view);
chessView = (ChessView)findViewById(R.id.cv_chess);
}
}
[4]总结
后期再做一个小球沿着 sin(x) 曲线运动的 demo, 最近很喜欢郭霖大神微信公众号上推出的自定义的各种高逼格 view, 有模仿着做了一个贝塞尔曲线之类的。感谢大神的分享。
网友评论