一,为什么要自定义Viewandroid原生控件基本上可以满足我们简易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有啥区别?
文章目前仍在更新中,如果你觉得我的文章有错误或者纰漏,欢迎指正,另外,如果你觉得有用的话,点个赞呗。