android自定义View探索2
来源:互联网 发布:淘宝印度神油是真的吗 编辑:程序博客网 时间:2024/05/21 11:30
前言:
本篇文章我们结合一个Demo学习自定义View的基本用法
一:自定义View的绘制流程
1:自定义View的属性
自定义View属性在哪里写?
我们要在在/res/values目录下新建一个attrs.xml文件,在attrs文件写自定义View
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="DeclareViewOne"> <attr name="mText" format="string" /> <attr name="mTextColor" format="color" /> <attr name="mTextSize" format="dimension" /> </declare-styleable></resources>
declare-styleable:给自定义控件添加自定义属性用的。
name:输性名
format:属性取值类型,有以下10种
string:字符串
color:颜色
demension:尺寸值
integer:整型
enum:枚举型
reference:参考指定Theme中资源ID
float:浮点型
boolean:布尔型
fraction:百分数型
flag:位或运算
自定义View属性怎么用?
来看看代码:
<?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" android:layout_width="match_parent" android:layout_height="match_parent"> <myview.csdn.com.view.one.ViewOne android:layout_width="wrap_content" android:layout_height="wrap_content" app:mText="测试文本" app:mTextColor="#ff0000" app:mTextSize="40sp" /></LinearLayout>
一定要引入xmlns:app="http://schemas.android.com/apk/res-auto"
2:获得我们自定义View的属性
自定义View的属性在自定义View的构造方法中获取。
3:重写onMeasure方法
计算View的高度和宽度
4:重写onDraw方法
绘制View的内容
二 来一个Demo
第一步 自定义View的属性(attrs.xml)
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="DeclareViewOne"> <attr name="mText" format="string" /> <attr name="mTextColor" format="color" /> <attr name="mTextSize" format="dimension" /> </declare-styleable></resources>
第二步 自定义View(ViewOne.class)
package myview.csdn.com.view.one;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.support.annotation.Nullable;import android.util.AttributeSet;import android.util.Log;import android.util.TypedValue;import android.view.View;import java.util.HashSet;import java.util.Random;import java.util.Set;import myview.csdn.com.R;/** * Created by Administrator on 2017/6/14. */public class ViewOne extends View { /** * 内容 */ private String mText; /** * 颜色 */ private int mTextColor; /** * 大小 */ private int mTextSize; /** * 绘制时控制文本绘制的范围 */ private Rect mRect; private Paint mPaint; public ViewOne(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ViewOne(Context context) { this(context, null); } /** * 获得自定义的样式属性 * * @param context * @param attrs * @param defStyle */ public ViewOne(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); /** * 所定义的自定义样式属性 */ TypedArray mType = context.getTheme().obtainStyledAttributes(attrs, R.styleable.DeclareViewOne, defStyle, 0); int count = mType.getIndexCount(); for (int i = 0; i < count; i++) { int attr = mType.getIndex(i); switch (attr) { case R.styleable.DeclareViewOne_mText: mText = mType.getString(attr); break; case R.styleable.DeclareViewOne_mTextColor: // 默认颜色设置为黑色 mTextColor = mType.getColor(attr, Color.BLACK); break; case R.styleable.DeclareViewOne_mTextSize: // 默认设置为16sp,TypeValue也可以把sp转化为px mTextSize = mType.getDimensionPixelSize(attr, (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics())); break; } } mType.recycle(); /** * 获得绘制文本的宽和高 */ mPaint = new Paint(); mPaint.setTextSize(mTextSize); mRect = new Rect(); mPaint.getTextBounds(mText, 0, mText.length(), mRect); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onDraw(Canvas canvas) { mPaint.setColor(Color.BLUE); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint); mPaint.setColor(mTextColor); canvas.drawText(mText, getWidth() / 2 - mRect.width() / 2, getHeight() / 2 + mRect.height() / 2, mPaint); }}
这里面有什么,哈哈 获得自定义View的属性,重写onMeasure方法,重写onDraw方法这些都在里面了
第三步 使用 aty_my_view1.xml
<?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" android:layout_width="match_parent" android:layout_height="match_parent"> <myview.csdn.com.view.one.ViewOne android:layout_width="wrap_content" android:layout_height="wrap_content" app:mText="测试文本" app:mTextColor="#ff0000" app:mTextSize="40sp" /></LinearLayout>
走完三步大功告成,来可以运行了,来一张截图
效果不对我们不是用了wrap_content吗。好下一节我们来完善它
三 修改onMeasure
ViewOne.class
package myview.csdn.com.view.one;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.support.annotation.Nullable;import android.util.AttributeSet;import android.util.Log;import android.util.TypedValue;import android.view.View;import java.util.HashSet;import java.util.Random;import java.util.Set;import myview.csdn.com.R;/** * Created by Administrator on 2017/6/14. */public class ViewOne extends View { /** * 内容 */ private String mText; /** * 颜色 */ private int mTextColor; /** * 大小 */ private int mTextSize; /** * 绘制时控制文本绘制的范围 */ private Rect mRect; private Paint mPaint; public ViewOne(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ViewOne(Context context) { this(context, null); } /** * 获得自定义的样式属性 * * @param context * @param attrs * @param defStyle */ public ViewOne(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); /** * 所定义的自定义样式属性 */ TypedArray mType = context.getTheme().obtainStyledAttributes(attrs, R.styleable.DeclareViewOne, defStyle, 0); int count = mType.getIndexCount(); for (int i = 0; i < count; i++) { int attr = mType.getIndex(i); switch (attr) { case R.styleable.DeclareViewOne_mText: mText = mType.getString(attr); break; case R.styleable.DeclareViewOne_mTextColor: // 默认颜色设置为黑色 mTextColor = mType.getColor(attr, Color.BLACK); break; case R.styleable.DeclareViewOne_mTextSize: // 默认设置为16sp,TypeValue也可以把sp转化为px mTextSize = mType.getDimensionPixelSize(attr, (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics())); break; } } mType.recycle(); /** * 获得绘制文本的宽和高 */ mPaint = new Paint(); mPaint.setTextSize(mTextSize); mRect = new Rect(); mPaint.getTextBounds(mText, 0, mText.length(), mRect); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { /** * 设置宽度、设置高度 */ initSpec(widthMeasureSpec,heightMeasureSpec); } /** * 设置宽度、设置高度 */ private void initSpec(int widthMeasureSpec, int heightMeasureSpec) { int width = 0; int height = 0; /**************************宽***************************/ int specMode = MeasureSpec.getMode(widthMeasureSpec); int specSize = MeasureSpec.getSize(widthMeasureSpec); switch (specMode) { case MeasureSpec.EXACTLY: width = getPaddingLeft() + getPaddingRight() + specSize; break; case MeasureSpec.AT_MOST: width = getPaddingLeft() + getPaddingRight() + mRect.width(); break; } /**************************高***************************/ specMode = MeasureSpec.getMode(heightMeasureSpec); specSize = MeasureSpec.getSize(heightMeasureSpec); switch (specMode) { case MeasureSpec.EXACTLY:// 明确指定了 height = getPaddingTop() + getPaddingBottom() + specSize; break; case MeasureSpec.AT_MOST:// 一般为WARP_CONTENT height = getPaddingTop() + getPaddingBottom() + mRect.height(); break; } setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { mPaint.setColor(Color.BLUE); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint); mPaint.setColor(mTextColor); canvas.drawText(mText, getWidth() / 2 - mRect.width() / 2, getHeight() / 2 + mRect.height() / 2, mPaint); }}在onMeasure中对代码进行了修改
aty_mv_view1.xml
<?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" android:gravity="center" android:layout_width="match_parent" android:layout_height="match_parent"> <myview.csdn.com.view.one.ViewOne android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="20dp" app:mText="测试文本" app:mTextColor="#ff0000" app:mTextSize="40sp" /></LinearLayout>
布局也做了小小的修改,设置了padding,grvity居中
再来一张截图
OK 任务完成 我们的第一个问题这些组件是如何实现的解决了。
当然我们不能仅仅满足此,来看看这篇文章中还有哪些问题?
这里我们对onMeasure和onDraw只是简单的使用,下一篇我们将对它们进行深入分析。
资源下载
- android自定义View探索2
- Android 自定义view探索
- android-自定义View初步探索
- 《Android开发艺术探索》 自定义View
- Android自定义View探索(一)—生命周期
- Android自定义View探索(二)—常用工具
- Android 自定义view探索——Canvas
- Android 自定义View探索——图片
- 《Android开发艺术探索第四章读书笔记-自定义VIew》
- Android开发艺术探索笔记(15)- 自定义View
- Android 自定义View探索——画布绘制
- android自定义View探索3(onMeasure深入分析一)
- android自定义View探索4(文字跑马灯)
- android自定义View探索5(onMeasure深入分析二LayoutParams)
- Android 自定义View(2)
- Android View---自定义View
- Android View---自定义View
- Android 自定义View学习(2)
- Kotlin开发语言学习(2)基本语法
- 关于phpcms根目录下ico图标,改了没效果的解决办法?
- 阿里云RDS数据恢复到本地MySQL数据库
- JavaScript中数组对象详解
- 游戏动画中欧拉角与万向锁的理解
- android自定义View探索2
- Kotlin开发语言学习(3)Kotlin与Java混编
- WebRtc部署
- 额。在js中拼写onclick无效
- 指针与堆内存
- 使用sklearn进行集成学习——理论
- yolo配置文件理解
- Kotlin开发语言学习(4) 类特性
- 使用Flask-Mail和qq邮箱SMTP服务发送邮件