首先我们在res/values目录下建一个xml文件夹,一般取名为attrs。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--name 自定义View的名字 TextView-->
<declare-styleable name="MyTextView">
<!-- name 属性名称
format 格式: string 文字 color 颜色
dimension 宽高 字体大小 integer 数字
reference 资源(drawable)
-->
<attr name="lzyText" format="string"/>
<attr name="lzyTextColor" format="color"/>
<attr name="lzyTextSize" format="dimension"/>
<attr name="lzyMaxLength" format="integer"/>
<!-- 枚举 -->
<attr name="lzyInputType">
<enum name="number" value="1"/>
<enum name="text" value="2"/>
<enum name="password" value="3"/>
</attr>
</declare-styleable>
</resources>
自己的布局文件里面使用:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.michael.view_01.MainActivity">
<com.example.michael.view_01.MyTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:lzyText="hello world"
app:lzyTextColor="@color/colorAccent"
app:lzyTextSize="20sp"
/>
</LinearLayout>
注意:
xmlns:app="http://schemas.android.com/apk/res-auto"
一定要有这样的命名空间!
自定义TextView:
public class MyTextView extends View {
private String mText;
private int mTextColor;
private int mTextSize;
private Paint mPaint;
//构造函数在代码new的时候调用
public MyTextView(Context context) {
this(context,null);
}
//在布局中使用
public MyTextView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
//在不居中调用,布局中有style的情况
public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.MyTextView);
mText = a.getString(R.styleable.MyTextView_lzyText);
mTextColor = a.getColor(R.styleable.MyTextView_lzyTextColor, Color.BLACK);
mTextSize = a.getDimensionPixelSize(R.styleable.MyTextView_lzyTextSize,20);
a.recycle();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setTextSize(mTextSize);
mPaint.setColor(mTextColor);
}
//布局的宽高都是有这个方法指定
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//获取宽高的模式
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
if (widthMode == MeasureSpec.AT_MOST){
Rect rect = new Rect();
mPaint.getTextBounds(mText,0,mText.length(),rect);
width = rect.width();
}
int height = MeasureSpec.getSize(heightMeasureSpec);
if (heightMode == MeasureSpec.AT_MOST){
Rect r = new Rect();
mPaint.getTextBounds(mText,0,mText.length(),r);
height = r.height();
}
setMeasuredDimension(width,height);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint.FontMetricsInt fontMetricsInt = mPaint.getFontMetricsInt();
int dy = 0;
dy = (fontMetricsInt.bottom - fontMetricsInt.top)/2 - fontMetricsInt.bottom;
int baseLine = getHeight()/2 + dy;
canvas.drawText(mText,0,baseLine,mPaint);
}
}