Android 自定义View (三部曲)
2016-07-01 10:57
405 查看
设置自定义View的属性(第一部曲)
首先,我们需要创建一个attr.xml文件,在这个文件中,我们定义好View的属性和相关的数据类型。
<resources> <!--name 是自定义属性名,format 是属性的单位--> <attr name="text" format="string" /> <attr name="textSize" format="dimension" /> <attr name="textColor" format="color" /> <!--name 是自定义控件的类名--> <declare-styleable name="CustomView"> <attr name="text" /> <attr name="textSize" /> <attr name="textColor" /> </declare-styleable> </resources>
其中,format支持的类型有enum、boolean、color、dimension、flag、float、fraction、integer、reference、string类型。
如果同学们想具体知道attr属性的定义的话,建议同学们去阅读这位博主的博文Android 自定义view (一)——attr 理解
写一个继承View的类,并重写里面的onMeasure和onDraw方法 (第二部曲)
public class CustomView extends View { /** * 测得的自定义view的宽 */ int width; /** * 测得的自定义view的高 */ int height; /** * 文本 */ private String mText; /** * 文本颜色 */ private int mTextColor; /** * 文本大小 */ private int mTextSize; private Paint mPaint; /** * 文本绘制的范围 */ private Rect mTextBound; /** * 矩阵的四个参数 * --Rect rect=new Rect(100,100,300,600); 两个点 ==> 左上,右下 * --but右下角(300,600)其实是不在这个矩形里面的 * --这个矩形实际表示的区域是:(100,100,299,599) */ public CustomView(Context context) { this(context, null); } public CustomView(Context context, AttributeSet attrs) { this(context, attrs, 0); } /** * 获得我自定义的样式属性 * * @param context * @param attrs * @param defStyle 默认的Style */ public CustomView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); /** * 获得我们所定义的自定义样式属性 * TypedArray是一个用来存放由context.obtainStyledAttributes获得的属性的数组 在使用完成后,一定要调用recycle方法 */ TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomView, defStyle, 0); int n = a.getIndexCount(); for(int i =0;i<n;i++){ int attr = a.getIndex(i); switch (attr){ case R.styleable.CustomView_text: mText = a.getString(attr); break; case R.styleable.CustomView_textColor: mTextColor = a.getColor(attr, Color.BLACK); break; case R.styleable.CustomView_textSize: mTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, 20, getResources().getDisplayMetrics())); break; } } a.recycle();//一定要调用,否则这次的设定会对下次的使用造成影响(回收资源) /** * 获得绘制文本的宽和高 */ mPaint = new Paint(); mTextBound = new Rect(); mPaint.setTextSize(mTextSize); mPaint.getTextBounds(mText, 0, mText.length(), mTextBound); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); /** * 设置宽度 */ if(widthMode == MeasureSpec.EXACTLY){ width = widthSize; }else { int desiredByText = getPaddingLeft() + mTextBound.width() + getPaddingRight(); width = desiredByText; } /*** * 设置高度 */ if(heightMode == MeasureSpec.EXACTLY){ height = heightSize; }else { mPaint.setTextSize(mTextSize); mPaint.getTextBounds(mText,0,mText.length(),mTextBound); int desire = getPaddingTop() + getPaddingBottom() + mTextBound.height(); height = Math.min(desire,heightSize);//无论如何都不能超过view的高度 } setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { mPaint.setColor(mTextColor); mPaint.setStyle(Paint.Style.FILL); /** * -计算了描绘字体需要的范围 * * -y是 基准线,不是字串符的底部 就像 英文的第三根线 */ canvas.drawText(mText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint); } }
现在,我们回过头来看一下onMeasure方法,顾名思义,这个方法的主要功能就是测量我们自定义view的宽和高。
和onMeasure方法相关的有一个叫做MeasureSpec的类,这个类封装了父布局传递给子布局的布局要求,每个MeasureSpec代表了一组宽度和高度的要求。
MeasureSpec有三种模式,分别是
1. EXACTLY
设置了明确的值或者是MATCH_PARENT,模式为EXACTLY
2. AT_MOST
表示子布局限制在一个最大值内,一般为WARP_CONTENT
3. UNSPECIFIED
表示视图可以是任意的大小,没有任何限制。
完成我们的xml布局文件(第三部曲)
记得加上命名空间 AS建议我们这样写 xmlns:yuan="http://schemas.android.com/apk/res-auto"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:yuan="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.motoyuan.myapplication.MainActivity"> <com.motoyuan.myapplication.CustomView android:layout_width="382dp" android:layout_height="382dp" android:padding="10dp" yuan:text="8796" yuan:textColor="#ff0000" yuan:textSize="30sp" /> </LinearLayout>
如此一来,一个简单的自定义View就完成了
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories