自定义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
 * 邮箱:sunwentao@imcoming.cn
 * 时间: 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大神的课程,编写的。用来作为我的记录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值