[自定义控件]android自定义view基础

    xiaoxiao2021-03-26  27

    [自定义控件]android自定义view基础

    尊重原创,转载请注明出处: http://blog.csdn.net/qq137722697

    [自定义控件]android自定义view实战之太极图(传送门) ————>这是一篇自定view的实战文章

    大部分的自定义view包括以下的步骤:

    1、在style.xml文件中定义暴露的属性;

    2、继承view或其子类,重写构造方法,获取;

    [ 3、重写onMeasure方法,获取/设置控件的大小; ]

    4、重写onDraw方法,实际的绘制逻辑。

    第三步可以不走哦;

    一、资源文件(style.xml)中定义可以暴露的属性

    如下:

    <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="YZMView"> <attr name="text" format="string" /> <attr name="textSize" format="dimension" /> <attr name="textColor" format="color|reference" /> </declare-styleable> </resources>

    这里的format有下面的值:

    1、reference:引用资源ID类型,如android:text=”@string/str_title”,str_title=“标题”;

    2、color:颜色类型,如为字体设置颜色;

    3、boolean:布尔类型,如设置是否显示;

    4、dimension:尺寸大小类型,如设置字体的大小;

    5、float:浮点类型,如设置透明度;

    6、integer:整形类型,如设置时间间隔;

    7、string:字符串类型,如设置字体内容;

    8、fraction:百分数类型,如设置点的相对位置;

    9、enum:枚举类型,如某个属性只能有几个固定的值;

    10、flag:位或运算类型,如属性多选。

    温馨提示:一个属性值可以设置多种类型。

    二、继承view或其子类,重写构造方法,获取属性

    在有三个参数的构造方法中使用TypedArray(属性类型数组来获取),TypedArray需要关联布局文件中的属性:attrs,defStyle为构造方法中的参数,直接使用即可,这里只需要传入自动一的属性资源R.styleable.YZMView

    TypedArray arr=context.getTheme().obtainSyteleAttributes(attrs,R.styleable.YZMView,defStyle,0);

    上面是映射属性,属性是需要拿来设置,如何拿呢?其实它已经存在TypedArray了

    public class YZMView extends View { private String text = "1234"; private float textSize = 48; private int textColor = 0xFFFFFFFF; public YZMView(Context context) { this(context, null); } public YZMView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public YZMView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.YZMView, defStyleAttr, 0); textSize = ta.getDimension(R.styleable.YZMView_textSize, 48);//16sp=48px默认16sp textColor = ta.getColor(R.styleable.YZMView_textColor, 0xFFFFFFFF); ta.recycle();//及时释放 } }

    三、重写onMeasure方法,获取/设置控件的大小

    以下基本上是固定写法(当然有些view是不需要重写这个方法的):

    @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec);//获取宽的模式 int widthSize = MeasureSpec.getSize(widthMeasureSpec);//获取宽的值 int heightMode = MeasureSpec.getMode(heightMeasureSpec);//获取高的模式 int heightSize = MeasureSpec.getSize(heightMeasureSpec);//获取高的值 if (widthMode == MeasureSpec.AT_MOST) {//如果用户设置了宽度为wrap_content,那么就要自己测量了 widthSize =200;//设置默认值 } if (heightMode == MeasureSpec.AT_MOST) {//如果用户设置高度为wrap_content,也是要自己测量 heightSize =100;//设置默认值 } setMeasuredDimension(widthSize, heightSize);//设置测量的宽度 }

    测量大小的类型:

    EXACTLY:设置了明确的值或者match_parent

    AT_MOST:设置为warp_content

    UNSPECLIFIED:想多大就多大,一般不用

    如果使用自定义控件的地方使用了wrap_content,那么系统是默认的是测量全部,这里需要自己处理一下(就像上面的固定写法一样)

    四、重写onDraw方法,实际的绘制逻辑

    @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas);//这里需要调用父类的绘制方法,这样系统会为本view绘制一些基本通用属性,如背景颜色 canvas.drawText(text, getMeasuredWidth() / 2 - mRect.width() / 2, getMeasuredHeight() / 2 + mRect.height() / 2, mPaint); }

    Paint画笔对象

    android中画笔工具叫Paint,它可以画任何几何图形、文字、bitmap、setAnitAlias(true)表示去掉齿轮。

    Paint的Style有3种:

    Paint.Style.FILL 填充内部

    Paint.Style.FILL_AND_STROKE 填充内部和描边

    Paint.Style.STROKE 描边

    Paint详细介绍

    http://blog.csdn.net/abcdef314159/article/details/51720686

    关于重绘

    控件重绘就是重新调用“onDraw()”【原理就是,使用view.postInvalidate()——>子线程中使用,view.invalidate()——>主线程中调用】方法触发onDraw()。

    五、实例

    下面用一个简单验证码的实例来进入自定义view

    属性定义(res/style.xml):

    <resources> <declare-styleable name="YZMView"> <attr name="text" format="string|reference" /> <attr name="textSize" format="dimension" /> <attr name="textColor" format="color|reference" /> </declare-styleable> </resources>

    YZMView类:

    /** * 自定义View-------验证码 * Created by HDL on 2017/2/5. */ public class YZMView extends View { private String text = "1234"; private float textSize = 48; private int textColor = 0xFFFFFFFF; private Paint mPaint; private Rect mRect; private static final String TAG = "YZMView"; public YZMView(Context context) { this(context, null); } public YZMView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public YZMView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); createCode(); TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.YZMView, defStyleAttr, 0); textSize = ta.getDimension(R.styleable.YZMView_textSize, 48); textColor = ta.getColor(R.styleable.YZMView_textColor, 0xFFFFFFFF); ta.recycle();//及时释放 this.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { createCode(); Log.e(TAG, "setOnClickListener: " + text); postInvalidate(); } }); mPaint = new Paint(); mPaint.setAntiAlias(true);//取消锯齿 mPaint.setTextSize(textSize); Log.e(TAG, "YZMView: " + textColor); mPaint.setColor(textColor); mRect = new Rect(); mPaint.getTextBounds(text, 0, text.length(), mRect);//将text的边框赋值给mrect } /** * 随机创建4位数字 */ private void createCode() { text = ""; for (int i = 0; i < 4; i++) { text += (int) (Math.random() * 10 - 1) + ""; } } public String getText() { return text; } public void setText(String text) { this.text = text; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawText(text, getMeasuredWidth() / 2 - mRect.width() / 2 - 6.6f, getMeasuredHeight() / 2 + mRect.height() / 2, mPaint);//加6.6是因为有测量误差 } }

    在布局文件中使用:

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout 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:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="view.cusstom.hdl.com.customview.MainActivity"> <view.cusstom.hdl.com.customview.YZMView android:id="@+id/yzm_main_code" android:layout_width="80dp" android:layout_height="40dp" android:background="#c9c7c9" app:textColor="#090a09" app:textSize="30sp" /> <Button android:layout_width="wrap_content" android:text="校验" android:onClick="onCheck" android:layout_height="wrap_content" /> </LinearLayout>

    添加噪点的代码就很简单了,for循环画指定数量的点和线即可,这里就不贴了,网上一大堆。

    觉得不错的话顶一个吧

    尊重原创,转载请注明出处: http://blog.csdn.net/qq137722697

    转载请注明原文地址: https://ju.6miu.com/read-662297.html

    最新回复(0)