1、自定义View的属性
2、在View的构造方法中获得我们自定义的属性
3、重写onMesure
4、重写onDraw
3这个步骤不是必须,当然了大部分情况下还是需要重写的。
1、自定义View的属性,首先在res/values/ 下建立一个attrs.xml , 在里面定义我们的属性和声明我们的整个样式。
<?xml version="1.0" encoding="utf-8"?><resources><attr name="txtName" format="string"/><attr name="txtColor" format="color"/><attr name="txtSize" format="dimension" /><declare-styleable name="titleStyle"><attr name="txtName"/><attr name="txtColor"/><attr name="txtSize"/></declare-styleable></resources>
定义了字体,字体颜色,字体大小3个属性,format是值该属性的取值类型:
一共有:string,color,demension,integer,enum,reference,float,boolean,fraction,flag;
编写的时候工具会提醒你使用哪种,不知道也可以Google搜索下
接下来就自定义View
public class CustomTitleView extends View{private String txtName;private int txtColor,txtSize;private Paint mPaint;private Rect mBounds;public CustomTitleView(Context context) {this(context, null);}public CustomTitleView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public CustomTitleView(Context context, AttributeSet attrs, int defStyleAttr) {//具体操作}}
定义完自定义的View ,就该调用我们自定义的View了。
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="/apk/res/android"xmlns:title="/apk/res/com.example.androidDemo" 《》android:orientation="vertical" android:layout_width="match_parent"android:layout_height="match_parent"><com.example.androidDemo.View.CustomTitleViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerHorizontal="true"android:layout_centerVertical="true"android:padding="5dp"title:txtName="你好"title:txtColor="#ffffff"title:txtSize="16sp"/></RelativeLayout>
注意代码中的这行,自定义命名空间,com.example.androidDemo是项目包路径
xmlns:title="/apk/res/com.example.androidDemo"
使用自定义命名空间:
title:txtName="你好"title:txtColor="#ffffff"title:txtSize="16sp"
在View的构造方法中,获得我们的自定义的样式
public class CustomTitleView extends View{private String txtName;private int txtColor,txtSize;private Paint mPaint;private Rect mBounds;public CustomTitleView(Context context) {this(context, null);}public CustomTitleView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public CustomTitleView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs,R.styleable.titleStyle,defStyleAttr,0);int n = typedArray.getIndexCount();for (int i = 0; i < n; i++){int attr = typedArray.getIndex(i);switch (attr){case 0:txtName = typedArray.getString(attr);break;case 1:txtColor = typedArray.getColor(attr, Color.BLACK);break;case 2:txtSize = typedArray.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(PLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));break;}}typedArray.recycle();/*** 获得绘制文本的宽和高 */mPaint = new Paint();mPaint.setTextSize(txtSize);// mPaint.setColor(mTitleTextColor);mBounds = new Rect();mPaint.getTextBounds(txtName, 0, txtName.length(), mBounds);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int widthMode = MeasureSpec.getMode(widthMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);int width;int height ;if (widthMode == MeasureSpec.EXACTLY){width = widthSize;} else{mPaint.setTextSize(txtSize);mPaint.getTextBounds(txtName, 0, txtName.length(), mBounds);float textWidth = mBounds.width();int desired = (int) (getPaddingLeft() + textWidth + getPaddingRight());width = desired;}if (heightMode == MeasureSpec.EXACTLY){height = heightSize;} else{mPaint.setTextSize(txtSize);mPaint.getTextBounds(txtName, 0, txtName.length(), mBounds);float textHeight = mBounds.height();int desired = (int) (getPaddingTop() + textHeight + getPaddingBottom());height = desired;}setMeasuredDimension(width, height);}@Overrideprotected void onDraw(Canvas canvas) {mPaint.setColor(Color.YELLOW);canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);mPaint.setColor(txtColor);canvas.drawText(txtName, getWidth() / 2 - mBounds.width() / 2, getHeight() / 2 + mBounds.height() / 2, mPaint);}}
其中
MeasureSpec.EXACTLY判断你传人的宽,高是不是精确赋值
android:layout_width="wrap_content"
android:layout_height="wrap_content"
如果是wrap_content,
mPaint.setTextSize(txtSize);mPaint.getTextBounds(txtName, 0, txtName.length(), mBounds);float textWidth = mBounds.width();int desired = (int) (getPaddingLeft() + textWidth + getPaddingRight());width = desired;
如果是200dp这类精确的宽高值,
if (widthMode == MeasureSpec.EXACTLY){width = widthSize;}
效果图 ,是不是很好用呢