自定义View
为什么要自定义View?
因为Android系统内置的View无法实现我们的需求,所以要根据自己的实际的需求来自定义View
如何使用自定义View(流程)?
①自定义View的属性
②继承View(至少重写2个构造方法)
③重写的 onMeasure(测量当前View的尺寸)、onDraw(绘画)、onLayout(定位)、onTouchEvent(监听)方法
使用教程(可以分为2种,一种是不使用自定义的View属性 另一种就是使用自定义的View属性。)
①先说不使用自定义的View(构造方法至少写2个,我这块写了4个)
package com.example.dabin.www.day03_viewcircle;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
* Created by Dabin on 2017/4/27.
*/
public class VirtualKeyView extends View {
public VirtualKeyView(Context context) {
super(context);
}
public VirtualKeyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public VirtualKeyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public VirtualKeyView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
//测量
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
//绘制
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//Paint 为画笔 Canvas为画布
Paint base = new Paint(); //最底部的圈
Paint middle = new Paint(); //中间的圈
Paint top = new Paint(); //最顶部的圈
//选取屏幕中间
float wi = canvas.getWidth() / 2;
float he = canvas.getHeight() / 2;
int baseR = dip2px(getContext(), 150); //设置底部圆半径
int middleR = dip2px(getContext(), 80); //设置中间圈半径
int topR = dip2px(getContext(), 50); //设置圆环宽度
base.setARGB(255, 199, 33, 56); //底部圈设置为红色
middle.setColor(Color.WHITE); //中间部圈设置为白色
top.setColor(Color.BLUE); //顶部圈设置为蓝色
//画笔样式分三种: 1.Paint.Style.STROKE:描边 2.Paint.Style.FILL_AND_STROKE:描边并填充3.Paint.Style.FILL:填充
//base.setStyle(Paint.Style.STROKE); //给底部圈描边
//设置描边的粗细,单位:像素px 注意:当setStrokeWidth(0)的时候描边宽度并不为0而是只占一个像素
//base.setStrokeWidth(20); //底部圈描边的粗细
//设置画笔为抗齿锯
base.setAntiAlias(true);
middle.setAntiAlias(true);
top.setAntiAlias(true);
canvas.drawColor(Color.YELLOW); //整体页面颜色
canvas.drawCircle(wi, he, baseR, base); //底部圈位置大小
canvas.drawCircle(wi, he, middleR, middle); //中间圈位置大小
canvas.drawCircle(wi, he, topR, top); //顶部圈位置大小
canvas.drawText("X", wi, he, base); //底部圈的字体
}
//定位
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
//监听
@Override
public boolean onTouchEvent(MotionEvent event) {
return super.onTouchEvent(event);
}
//根据手机的分辨率从 dp 的单位 转成为 px(像素)
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
我这块直接在onDraw中进行一系列操作,Paint()为画笔, Canvas为画布,其中根据手机分辨率从dp单位转成为px,可以不用,在相应的位置上直接写上数也可以。
其中drawCircle为画圆、drawLine绘制直线、drawRect绘制矩形、drawBitmap绘制位图
效果如下:
②使用View的属性(点击改变数字)
先在res/values下添加一个attrs.xml,在里面定义属性和声明样式
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="mText" format="string" />
<attr name="mTextColor" format="color" />
<attr name="mTextSize" format="dimension" />
<declare-styleable name="MyView">
<attr name="mText"/>
<attr name="mTextColor"/>
<attr name="mTextSize"/>
</declare-styleable>
</resources>
接着在我们的布局文件中声明我们的自定义View
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:dabin="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
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.dabin.com.www.view.MainActivity">
<com.example.dabin.www.day04_view.MyView
android:layout_width="200dip"
android:layout_height="100dip"
android:textSize="20sp"
dabin:mTextSize="25sp"
dabin:mText="i love you"
dabin:mTextColor ="#0000ff"
android:background="#ff0000"/>
</RelativeLayout>
紧记一定要引入 xmlns:dabin="http://schemas.andoroid.com/apk/res-auto" 这句话,这是命名空间,dabin:mTextSize=”25sp“ 这是对我们attrs.xml中声明属性的赋值。
接着看一下自定义View中的内容
package com.example.dabin.www.day04_view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
* Created by Dabin on 2017/9/28.
*/
public class MyView extends View {
private String mText;// 文字
private int mTextColor;// 颜色
private int mTextSize; // 字体大小
private Rect rect;
private Paint paint;
public MyView(Context context) {
this(context, null);
}
public MyView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//获取自定义属性的值
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyView, defStyleAttr, 0);
mText = a.getString(R.styleable.MyView_mText); //获取attrs.xml中的字体
mTextColor = a.getColor(R.styleable.MyView_mTextColor, Color.BLACK);//设置attrs.xml中的字体颜色
mTextSize = (int) a.getDimension(R.styleable.MyView_mTextSize, 100);//设置attrs.xml中的字体大小
a.recycle(); //注意回收
paint = new Paint();
paint.setTextSize(mTextSize); //设置字体大小
paint.setColor(mTextColor); //设置字体颜色
//获得绘制文本的宽和高
rect = new Rect();
paint.getTextBounds(mText, 0, mText.length(), rect);
}
// 绘制
@Override
protected void onDraw(Canvas canvas) {
canvas.drawText(mText, getWidth() / 2 - rect.width() / 2, getHeight() / 2 + rect.height() / 2, paint); //绘制文字
}
//监听
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE: //移动
break;
case MotionEvent.ACTION_DOWN: //按下
float a = (float) (Math.random() * 10000); //生成一个随机数
mText = "" + a;
invalidate(); //更新视图
break;
case MotionEvent.ACTION_UP: //抬起
break;
}
//这句话不要修改
return super.onTouchEvent(event);
}
}
在构造方法中,获取自定义View的对象,然后对其进行赋值。
在onTouchEvent()监听方法中设置点击改变值。
效果如下:
这些就是自定义View的一些简单使用。