自定義view(一)
簡單的五角星繪製
最近在研究自定義的view,俗話說什麼東西都得從簡單到困難,而自定義view又是安卓進階必備,所以今天開發一個很簡單的自定義view的五角星,作爲入門實戰
首先新建一個Wujiaoxing的java文件繼承view,實現倆個參數的構造方法就行了,因爲我們只在佈局中使用,如果要在java文件中使用,最好是把構造方法都實現一下,然後相互調用
首先實現onMeasure方法,
//定位屏幕的寬度
private int width;
//定義自定義view的中心點座標
private int centerX, centerY;
public Wujiaoxing(Context context, AttributeSet attrs) {
super(context, attrs);
//加個背景顏色,用來區分我們自定義的大小
setBackgroundColor(0x44ff0000);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
//設置view的寬度是屏幕寬度和高度中的最小值
width = Math.min(widthSize, heightSize);
//當出現這個特殊情況的時候,把屏幕的寬度作爲view的寬度
if (heightMode == MeasureSpec.UNSPECIFIED) {
width = widthSize;
} else if (widthMode == MeasureSpec.UNSPECIFIED) {
width = heightSize;
}
centerX = width / 2;
centerY = width / 2;
//因爲是正方形,所以寬度和高度一樣
setMeasuredDimension(width, width);
}
onMeasure是測量出我們需要的view的高度,比如我們需要一個正方形
簡單的解釋一下,MeasureSpec.getSize(widthMeasureSpec);拿到屏幕的寬度,
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
拿到寬度的mode,mode分爲3個模式,分別對應view的高度,寬度的大小
3個模式分別爲EXACTLY和AT_MOST,UNSPECIFIED
1、MeasureSpec.UNSPECIFIED,父視圖不對子視圖施加任何限制,子視圖可以得到任意想要的大小;
2、MeasureSpec.EXACTLY,父視圖希望子視圖的大小是specSize中指定的大小;
3、MeasureSpec.AT_MOST,子視圖的大小最多是specSize中的大小。
以上施加的限制只是父視圖“希望”子視圖的大小按MeasureSpec中描述的那樣,但是子視圖的具體大小取決於多方面的。
因爲我們定義的view是正方形,所以寬度和高度是相等的
然後在layout中看下效果
可以看到,我們自定義view的大小已經出來了,而且是正方形的
,然後我們開始繪製五角星,首先需要確定的是五個點的座標
首先中心點的座標很明顯就是width/2,width/2
我們把左上角看成0,0
那麼第一個點的座標是centerX,0
第二個點的座標是0,centerX/2
這樣分別得到5個點的座標
public List<Point> getFivePoint() {
mPointList.clear();
for (int i = 0; i < 6; i++) {
mPointList.add(getPoint(i));
}
return mPointList;
}
//採取4-1-5-2-3-4這樣的順序定義點的座標
private Point getPoint(int position) {
int x = 0;
int y = 0;
if (position == 0) {
x = (centerX / 2);
y = width;
} else if (position == 1) {
x = centerX;
y = 0;
} else if (position == 2) {
x = centerX * 3 / 2;
y = width;
} else if (position == 3) {
x = 0;
y = centerY / 2;
} else if (position == 4) {
x = width;
y = centerY / 2;
} else if (position == 5) {
x = (centerX / 2);
y = width;
}
return new Point(x, y);
}
使用系統graphics包中的point用來存儲x,y值
並創建一個list用來放置這5個點
現在我們有了存放這5個點座標的集合mlistPoint
接下來就可以繪製了
採取4-1-5-2-3-4這樣的順序進行繪線
接下來實現onDraw方法
首先初始化我們的畫筆
private void init() {
mPaint.setColor(0x88000000);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setStyle(Paint.Style.STROKE);
}
在view的構造函數中調用初始化操作
然後實現ondraw方法
@Override
protected void onDraw(Canvas canvas) {
getFivePoint();
Path path = new Path();
//首先將path移動到第一個點,然後往下一個點畫,繪製的基礎代碼,一看就能明白的
for (int i = 0; i < mPointList.size() - 1; i++) {
path.moveTo(mPointList.get(i).x, mPointList.get(i).y);
path.lineTo(mPointList.get(i + 1).x, mPointList.get(i + 1).y);
}
canvas.drawPath(path, mPaint);
//用下面這種方法也可以
// canvas.drawLine(centerX, centerY, mPointList.get(i).x, mPointList.get(i).y, mPaint);
}
接下來在我們的layout中build一下文件,五角星就出來了
下面貼出全部的代碼
package com.demo.swt.mystudyappshop.Wight;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
/**
* 介紹:這裏寫介紹
* 作者:sweet
* 郵箱:[email protected]
* 時間: 2017/2/17
*/
public class CstWuJiaoXingView extends View {
private int width;
private Paint mPaint = new Paint();
private List<Point> mPointList = new ArrayList<>();
private int centerX, centerY;
public CstWuJiaoXingView(Context context, AttributeSet attrs) {
super(context, attrs);
setBackgroundColor(0x44ff0000);
init();
}
private void init() {
mPaint.setColor(0x88000000);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setStyle(Paint.Style.STROKE);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
width = Math.min(widthSize, heightSize);
if (heightMode == MeasureSpec.UNSPECIFIED) {
width = widthSize;
} else if (widthMode == MeasureSpec.UNSPECIFIED) {
width = heightSize;
}
centerX = width / 2;
centerY = width / 2;
setMeasuredDimension(width, width);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
centerX = w / 2;
centerY = w / 2;
}
@Override
protected void onDraw(Canvas canvas) {
getFivePoint();
Path path = new Path();
for (int i = 0; i < mPointList.size() - 1; i++) {
path.moveTo(mPointList.get(i).x, mPointList.get(i).y);
path.lineTo(mPointList.get(i + 1).x, mPointList.get(i + 1).y);
}
canvas.drawPath(path, mPaint);
// canvas.drawLine(centerX, centerY, mPointList.get(i).x, mPointList.get(i).y, mPaint);
}
public List<Point> getFivePoint() {
mPointList.clear();
for (int i = 0; i < 6; i++) {
mPointList.add(getPoint(i));
}
return mPointList;
}
private Point getPoint(int position) {
int x = 0;
int y = 0;
if (position == 0) {
x = (centerX / 2);
y = width;
} else if (position == 1) {
x = centerX;
y = 0;
} else if (position == 2) {
x = centerX * 3 / 2;
y = width;
} else if (position == 3) {
x = 0;
y = centerY / 2;
} else if (position == 4) {
x = width;
y = centerY / 2;
} else if (position == 5) {
x = (centerX / 2);
y = width;
}
return new Point(x, y);
}
}
然後是layout文件的
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.demo.swt.mystudyappshop.Wight.CstWuJiaoXingView
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
代碼雖然很簡單,但是什麼事情都是從基礎開始的,
下一期會帶來一個五子棋遊戲的簡單製作,根據hyman大神的課程,編寫的。用來作爲我的記錄