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
- android 自定义View基础(2)
- Android自定义View基础
- android--View自定义基础
- android自定义View基础
- Android 自定义View(基础)
- Android自定义View基础
- Android自定义view基础
- android基础之自定义view
- Android自定义View基础学习
- android 自定义view 基础(一)
- Android 自定义View(基础)
- Android自定义View绘图基础
- Android自定义View基础详解
- Android 自定义View基础(一)
- Android 自定义View基础(二)
- android动画基础-自定义View
- Android自定义View基础绘制
- Android自定义View基础部分
- 4-7 统计某类完全平方数 (20分)
- Moc'ing qt1.h... 系统找不到指定的路径。 Project : error PRJ0019: 工具从"Moc'ing qt1.h..."
- Range——插入对象insertNode
- Serializable 和 Parcelable 两种序列化
- Eclipse使用Material Design步骤详解
- android 自定义View基础(2)
- Android的线程和线程池
- 数据库&MYSQL&JDBC
- mysql -uroot -proot tc -e "select * from merchandise limit 1"这个-E的命令作用是什么,用来什么什么的?
- java的常见异常与错误总结
- libuv学习笔记(2)
- LeetCode:Trapping Rain Water
- 没有到主机的路由
- mysql免密码登录, 及使用-e 参数执行sql脚本