一,为什么要自定义View
android原生控件基本上可以满足我们简易APP界面设计需求了,在随着APP越来越复杂,android系统提供的控件已无法满足我们的需求,于是自定义View闪亮登场!!
二,如何自定义View
自定义控件的实现有三种方式,分别是:组合控件、自绘控件和继承控件。今天我就写写如何自绘控件,另外两个在此就不写了。
在自定义view的时候,其实很简单,只需要知道4步骤:
1.属性--自定义View属性。
2.测量--onMeasure():决定View的大小。
3.布局--onLayout():决定View在ViewGroup中的位置。
4.绘制--onDraw():如何绘制这个View。
废话不多说,直接来个亲密接触!!,我们就来个简单的,自定义TextView》》》MyTextView
一,自定义View的属性,我们可以在Values文件夹下面创建attrs.xml文件,样式如下:
<?xml version="1.0" encoding="utf-8"?> <resources> <attr name="titleTextColor" format="color"/> <attr name="titleTextSize" format="dimension"/> <attr name="titleTextString" format="string"/> <declare-styleable name="customTitleView"> <attr name="titleTextColor"/> <attr name="titleTextSize"/> <attr name="titleTextString"/> </declare-styleable> </resources> 我分别定义了3个属性:字体颜色、字体大小、字体文本。 format为属性格式,还有其他格式:string,color,demension,integer,enum,reference,float,boolean,fraction,flag;具体的可以根据自己的需求定义。
二,我们自定义一个TextView。
public class MyTextView extends View { private String mTitleText; /** * 文本的颜色 */ private int mTitleTextColor; /** * 文本的大小 */ private int mTitleTextSize; private Paint mPaint; private Rect mBound; public MyTextView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyTextView(Context context) { this(context, null); } public MyTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); /** * 获得我们所定义的自定义样式属性 */ TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.customTitleView, defStyle, 0); int n = a.getIndexCount(); for (int i = 0; i < n; i++) { int attr = a.getIndex(i); switch (attr) { case R.styleable.customTitleView_titleTextString: mTitleText = a.getString(attr); break; case R.styleable.customTitleView_titleTextColor: // 默认颜色设置为黑色 mTitleTextColor = a.getColor(attr, Color.BLACK); break; case R.styleable.customTitleView_titleTextSize: // 默认设置为16sp,TypeValue也可以把sp转化为px mTitleTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics())); break; } } a.recycle(); mPaint=new Paint(); //先设置字体大小(在没有设置字体区域大小时,可以根据字体大小获取字体区域大小) mPaint.setTextSize(mTitleTextSize); mBound = new Rect();//字体区域 mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = 0; int height = 0; /** * 设置宽度 获得控件View的宽度。如果xml里面设置了宽度为match_parent或具体的宽度, * 则该控件的宽度就是match_parent或具体的宽度。如果设置宽度WARP_CONTENT, * 则控件宽度就是控件区域本身宽度 */ int specMode = MeasureSpec.getMode(widthMeasureSpec); int specSize = MeasureSpec.getSize(widthMeasureSpec); switch (specMode) { case MeasureSpec.EXACTLY:// 明确指定了大小 match_parent或具体大小如20dp width = getPaddingLeft() + getPaddingRight() + specSize; break; case MeasureSpec.AT_MOST:// 一般为WARP_CONTENT width = getPaddingLeft() + getPaddingRight() + mBound.width(); break; } /** * 设置高度 */ specMode = MeasureSpec.getMode(heightMeasureSpec); specSize = MeasureSpec.getSize(heightMeasureSpec); switch (specMode) { case MeasureSpec.EXACTLY:// 明确指定了match_parent或具体大小如20dp height = getPaddingTop() + getPaddingBottom() + specSize; break; case MeasureSpec.AT_MOST:// 一般为WARP_CONTENT height = getPaddingTop() + getPaddingBottom() + mBound.height(); break; } setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { //绘一个矩形背景为蓝色,大小看onMeasure方法 mPaint.setColor(Color.BLUE); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint); //绘字,字为区域中心 mPaint.setColor(mTitleTextColor); canvas.drawText(mTitleText, getWidth() / 2-mBound.width()/2 , getHeight() / 2+mBound.height()/2 , mPaint); } }是不是很简单?哈哈,一般人都能看懂,除非,你是大神,不屑看。。。
三,在布局中声明我们的自定义View
<?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:custom="http://schemas.android.com/apk/res-auto" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent"> <pw.onlyou.testapplication.MyTextView android:layout_width="200dp" android:layout_height="200dp" custom:titleTextColor="#ff0000" custom:titleTextSize="30dp" custom:titleTextString="Hello Word!"/> </RelativeLayout> 来看运行效果,是不是丑?不要太在意这些。。
在此,肯定有人说,册那,这个和原生TextView有啥区别?
下一节讲解 自定义动画
文章目前仍在更新中,如果你觉得我的文章有错误或者纰漏,欢迎指正,另外,如果你觉得有用的话,点个赞呗。