自定義view的簡單實現(一)

自定義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大神的課程,編寫的。用來作爲我的記錄

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章