android 自定义View基础(2)

来源:互联网 发布:如何设计软件 编辑:程序博客网 时间:2024/06/05 11:32

android 自定义View基础(2)

本篇文章是学习 hongyang 大神的文章:
http://blog.csdn.net/lmj623565791/article/details/24252901
的心得体会。
res/values/attrs.xml

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

自定义View java代码:

package com.crg.customview2;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.util.TypedValue;import android.view.View;import java.util.HashSet;import java.util.Random;import java.util.Set;/** * Created by crg on 16-6-11. */public class RandomView extends View{    private String mTextString;    private int mTextColor;    private int mTextSize;    private Paint mPaint;    private Rect mRect;    public RandomView(Context context, AttributeSet attrs) {        super(context, attrs);        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RandomView);        int count = ta.getIndexCount();        for (int i =0; i < count; i++){            int attr = ta.getIndex(i);            switch (attr){                case R.styleable.RandomView_text:                    mTextString = ta.getString(attr);                    break;                case R.styleable.RandomView_textSize:                    mTextSize = ta.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));                    break;                case R.styleable.RandomView_textColor:                    mTextColor = ta.getColor(attr, Color.BLACK);                    break;            }        }        //资源回收        ta.recycle();        //创建画字体的画笔        mPaint = new Paint();        //设置画笔的字体的大小        mPaint.setTextSize(mTextSize);        //初始化文字的范围Rect,及文所在的区域        mRect = new Rect();        //根据字体大小,内容,为mRect赋值。        mPaint.getTextBounds(mTextString, 0, mTextString.length(), mRect);        //给View添加点击事件        this.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                mTextString = generateRandomText();                //刷新这个view 当view有改变时,调用这个方法系统会调用 onDraw()                //此方法只能在ui线程调用//                invalidate();                //子线程调用 刷新 view,在ui线程也可以用                postInvalidate();            }        });    }    private String generateRandomText() {        Random random = new Random();        Set<Integer> set = new HashSet();        while (set.size() < 4){            int num = random.nextInt(10);            set.add(num);        }        StringBuffer stringBuffer = new StringBuffer();        for (Integer i : set){            stringBuffer.append(i);        }        return stringBuffer.toString();    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        /**         * 如果没有重写 onMeasure()         * wrap_content 属性将不起作用,系统会把 wrap_content 当成 match_parent 处理         */        /**         * Measure specification mode: The parent has not imposed any constraint         * on the child. It can be whatever size it wants.         *///        public static final int UNSPECIFIED = 0 << MODE_SHIFT;        /**         * Measure specification mode: The parent has determined an exact size         * for the child. The child is going to be given those bounds regardless         * of how big it wants to be.         *///        public static final int EXACTLY     = 1 << MODE_SHIFT;        /**         * Measure specification mode: The child can be as large as it wants up         * to the specified size.         *///        public static final int AT_MOST     = 2 << MODE_SHIFT;/*        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int widthSize = MeasureSpec.getSize(widthMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        //目标宽,即RandomView 的宽 在  onDraw() getMeasuredWidth() 获得此值        int width;        //目标高,即RandomView 的高 在  onDraw() getMeasuredHeight() 获得此值        int height;        if (widthMode == MeasureSpec.EXACTLY){            //精确模式,具体数值和match_parent            //            width = widthSize;        } else {            //AT_MOST  wrap_content            // UNSPECIFIED            // RandomView 的大小由里面的内容大小决定            width = getPaddingLeft() + mRect.width() + getPaddingRight();        }        if (heightMode == MeasureSpec.EXACTLY){            height = heightSize;        } else {            height = getPaddingTop() + mRect.height() + getPaddingTop();        }        //绘制结果        setMeasuredDimension(width, height);*/    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        //画出要显示的内容        //给画笔设置颜色 半透明的蓝色//        int color = 0x000000ff;//        int color = Color.argb(127, 0, 0, 255);        mPaint.setColor(mTextColor);        //第一步,先画背景的矩形        //画一个矩形,从左上角作为起点,getMeasuredWidth(), getMeasuredHeight() 就是布局文件里设置的宽和高,及        //这个view的大小        canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);        //画view里面要显示的文字        //带透明的绿色        int color = 0xbc00ff00;        mPaint.setColor(color);        canvas.drawText(mTextString, 0, mTextString.length(), getWidth()/2 - mRect.width()/2, getHeight()/2 + mRect.height()/2, mPaint);    }}

xml布局文件使用:

<?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:random="http://schemas.android.com/apk/res-auto"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="com.crg.customview2.MainActivity">    <com.crg.customview2.RandomView        android:layout_width="200dp"        android:layout_height="300dp"        random:text = "1263"        random:textSize = "60sp"        random:textColor = "#23ff0000"        /></RelativeLayout>

效果:

这里写图片描述

我们使用时,宽和高,都是给定的具体值,

        android:layout_width="200dp"        android:layout_height="300dp"

换成:

        android:layout_width="wrap_content"        android:layout_height="wrap_content"        random:text = "1263"        random:textSize = "60sp"        random:textColor = "#23ff0000"

效果如下:
这里写图片描述

原因是:我们没有重写

 @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        /**         * 如果没有重写 onMeasure()         * wrap_content 属性将不起作用,系统会把 wrap_content 当成 match_parent 处理         */    }

系统会把 wrap_content 测量为:match_parent。

打开:onMeasure()里的代码,效果如下
这里写图片描述

最后加点阴影干扰,做成简单的验证码:

//制作简单的验证码        int colorshade = Color.argb(127, 0, 0, 255);        mPaint.setColor(colorshade);        canvas.drawText("#$%&", 0, mTextString.length(), getWidth()/2 - mRect.width()/2, getHeight()/2 + mRect.height()/2, mPaint);

效果如下:

这里写图片描述

参考源码:
https://github.com/aloe-all/RandomView

0 0
原创粉丝点击