action_main:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="255dp"
android:layout_height="255dp"
tools:context=".MainActivity">
<com.example.zdyview_measure_day03.weight.MyMeasureTest
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:visibility="gone" />
<com.example.zdyview_measure_day03.weight.MyLuckView
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@mipmap/ic_launcher"/>
</RelativeLayout>
public class MyLuckView extends View implements View.OnClickListener {
private String[] contents = new String[]{"美 女", "女 神", "热 舞", "丰 满", "性 感", "知 性"};
public int[] colors = new int[]{Color.parseColor("#8EE5EE"), Color.parseColor("#FFD700"), Color.parseColor("#FFD39B"), Color.parseColor("#FF8247"), Color.parseColor("#FF34B3"), Color.parseColor("#F0E68C")};
private int mWidth;
private Paint mPaint;
private Context mContext;
private String mStr = "start";
public MyLuckView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mPaint = new Paint();
setOnClickListener(this);
}
//会发生覆盖效果
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
bigCircle(canvas);
//因为要画扇形 里面有个RectF
//因为那个园其实是占全屏的,所以我这个RectF的空间也是全屏
RectF rectF = paintArc(canvas);
paintText(canvas, rectF);
paintCenter(canvas);
}
private void paintCenter(Canvas canvas) {
mPaint.setColor(Color.GREEN);
canvas.drawCircle(mWidth / 2, mWidth / 2, 50, mPaint);
mPaint.setColor(Color.BLACK);
mPaint.setTextSize(24);
//咱们在最中心的位置画一个start (150,150) 我们要得到我们写的字的高和宽
Rect rect = new Rect();
mPaint.getTextBounds(mStr, 0, mStr.length(), rect);
int width = rect.width();
int height = rect.height();
canvas.drawText(mStr, mWidth / 2 - width / 2, mWidth / 2 + height / 2, mPaint);
}
private void paintText(Canvas canvas, RectF rectF) {
mPaint.setColor(Color.BLACK);
mPaint.setTextSize(24);
for (int i = 0; i < contents.length; i++) {
int startjd = i * 60;//i=0 0 i=1 =60
//Path 代表路径 想怎么画就怎么画
Path path = new Path();
path.addArc(rectF, startjd, 60);
canvas.drawTextOnPath(contents[i], path, 50, 50, mPaint);
}
}
@NonNull
private RectF paintArc(Canvas canvas) {
RectF rectF = new RectF(0, 0, mWidth, mWidth);
mPaint.setStyle(Paint.Style.FILL);
for (int i = 0; i < colors.length; i++) {
mPaint.setColor(colors[i]);
int startjd = i * 60;//i=0 0 i=1 =60
canvas.drawArc(rectF, startjd, 60, true, mPaint);
}
return rectF;
}
private void bigCircle(Canvas canvas) {
mPaint.setColor(Color.YELLOW);
mPaint.setStyle(Paint.Style.STROKE);
//设置边缘锯齿
mPaint.setAntiAlias(true);
mPaint.setStrokeWidth(3);
Log.e("width", mWidth + "");
canvas.drawCircle(mWidth / 2, mWidth / 2, mWidth / 2, mPaint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(300, 300);
//得到测量过后的高和宽
mWidth = getMeasuredWidth();
}
@Override
public void onClick(View v) {
startAnim();
}
private void startAnim() {
Random random = new Random();
float jd = random.nextInt(3600);
RotateAnimation rotateAnimation = new RotateAnimation(0f, jd, mWidth / 2, mWidth / 2);
rotateAnimation.setDuration(3000);
//保留最后执行完的位置
rotateAnimation.setFillAfter(true);
startAnimation(rotateAnimation);
}
}
public class MyMeasureTest extends View {
private Bitmap mImage;
private Paint mPaint;
public MyMeasureTest(Context context, AttributeSet attrs) {
super(context, attrs);
mImage = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
mPaint = new Paint();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mImage, 0, 0, mPaint);
Log.e("onDraw", getWidth() + "高" + getHeight());
}
//这两个参数就是对应我们xml布局你自己写的layout_width和layout_height
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int myWidth = 0;
//提供了获取测量模式的方法和控件大小
int mode = MeasureSpec.getMode(widthMeasureSpec);//1:match_parent 2:wrap_parent 3:指定的值比如50dp
int size = MeasureSpec.getSize(widthMeasureSpec);
switch (mode) {
case MeasureSpec.UNSPECIFIED:
myWidth = size;
Log.e("UNSPECIFIED", "宽" + myWidth);
break;
case MeasureSpec.AT_MOST://最大值模式 不能超过父控件的大小
myWidth = getImageWidth();
Log.e("AT_MOST", "宽" + myWidth);
break;
case MeasureSpec.EXACTLY://精准模式 match_parent 指定的值比如50dp
myWidth = size;
Log.e("EXACTLY", "宽" + myWidth);
break;
}
int myHeight = 0;
int modeHeight = MeasureSpec.getMode(heightMeasureSpec);//1:match_parent 2:wrap_parent 3:指定的值比如50dp
int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
switch (modeHeight) {
case MeasureSpec.UNSPECIFIED:
myHeight = sizeHeight;
Log.e("UNSPECIFIED", "高" + myHeight);
break;
case MeasureSpec.AT_MOST://最大值模式 不能超过父控件的大小
myHeight = getImageHeight();
Log.e("AT_MOST", "高" + myHeight);
break;
case MeasureSpec.EXACTLY://精准模式 match_parent 指定的值比如50dp
myHeight = sizeHeight;
Log.e("EXACTLY", "高" + myHeight);
break;
}
//测量完处理
setMeasuredDimension(myWidth, myHeight);
}
//正常开发用到自定义view 这个很小但是呢他占的位置确实很大 所以我们进行精确测量
private int getImageWidth() {
//计算我们画的实际大小 考虑到一个控件正常大小是加上padding
int width = mImage.getWidth() + getPaddingLeft() + getPaddingRight();
Log.e("实际的大小", width + ",左天冲" + getPaddingLeft() + "有填充" + getPaddingRight());
return width;
}
private int getImageHeight() {
//计算我们画的实际大小 考虑到一个控件正常大小是加上padding
int height = mImage.getHeight() + getPaddingTop() + getPaddingBottom();
return height;
}
}