最近一直在研究 Android 自定义控件,因此 LZ 将根据自己的学习经历将自定义控件中用到的知识一 一解析,如果小伙伴还没有看过 LZ 的第一讲,那么请小伙伴自行移步 Android 自定义控件之第一讲:attr format 取值类型,好了,就先扯到这里,下面开始今天内容讲解:
Google 开发者平台是这么解释这个类的:
大体意思是:TypedArray 是一个数组容器,在这个容器中装由 obtainStyledAttributes(AttributeSet, int[], int, int)
或者 obtainAttributes(AttributeSet, int[])
函数获取到的属性值。用完之后记得调用 recycle()
函数回收资源。索引值用来获取 Attributes 对应的属性值(这个 Attributes 将会被传入 obtainStyledAttributes()
函数)。
好了,光说不练,多没有说服力,下面就让我们用一个例子来讲解如何使用 TypedArray
吧:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyFirstCustomerView">
<attr name="text" format="string" />
<attr name="textColor" format="color"/>
<attr name="textSize" format="dimension"/>
</attr>
</declare-styleable>
</resources>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:first_customer="http://schemas.android.com/apk/res/com.smart.customer_view_03_19"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${packageName}.${activityClass}" >
<com.smart.customer_view_03_19.customerview.MyFirstCustomerView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="@dimen/small_padding"
android:layout_centerInParent="true"
first_customer:text="1234"
first_customer:textColor="@color/green"
first_customer:textSize="@dimen/x_large_font"
/>
</RelativeLayout>
注意:
第三行 xmlns:first_customer="http://schemas.android.com/apk/res/com.smart.customer_view_03_19"
的作用是在 XML 文件中声明我们自己的命名空间,这样之后 XML 解析器就可以解析我们自定义的属性了。其中:xmlns
是 Extensible Markup Language Name Space
的缩写。它的主要作用就是告诉解析器:XML 应该从哪里解析此文件,默认为 Anroid System。
package com.smart.customer_view_03_19.customerview;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.View.OnClickListener;
import com.smart.customer_view_03_19.R;
public class MyFirstCustomerView extends View implements OnClickListener{
private Context mContext;
/** * 文本 */
private String mText;
/** * 文本的颜色 */
private int mTextColor;
/** * 文本的大小 */
private int mTextSize;
/** * 绘制时控制文本绘制的范围 */
private Rect mBound;
private Paint mPaint;
public MyFirstCustomerView(Context context) {
this(context,null);
}
//默认情况下,系统调用的是这个构造函数
public MyFirstCustomerView(Context context, AttributeSet attrs) {
this(context,attrs,0);
}
public MyFirstCustomerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.mContext = context;
//获取 TypedArray 对象
TypedArray _TypedArray = mContext.getTheme().obtainStyledAttributes(attrs, R.styleable.MyFirstCustomerView, 0, 0);
try {
mText = _TypedArray.getString(R.styleable.MyFirstCustomerView_text);
mTextColor = _TypedArray.getColor(R.styleable.MyFirstCustomerView_textColor, Color.BLACK);
mTextSize = _TypedArray.getDimensionPixelSize(R.styleable.MyFirstCustomerView_textSize,
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));
} finally {
_TypedArray.recycle();
}
/** * 获得绘制文本的宽和高 */
mPaint = new Paint();
mPaint.setTextSize(mTextSize);
mPaint.setTextAlign(Paint.Align.CENTER);
mBound = new Rect();
Log.i("Tag", "TextLength:" + mText.length());
mPaint.getTextBounds(mText, 0, mText.length(), mBound);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.i("Tag", "onMeasure():");
int _WidthMode = MeasureSpec.getMode(widthMeasureSpec);
int _WidthSpec = MeasureSpec.getSize(widthMeasureSpec);
int _HeightMode = MeasureSpec.getMode(heightMeasureSpec);
int _HeightSpec = MeasureSpec.getSize(heightMeasureSpec);
int _Width;
int _Height;
//宽度
if(_WidthMode == MeasureSpec.EXACTLY){
_Width = _WidthSpec;
}else{
mPaint.setTextSize(mTextSize);
mPaint.getTextBounds(mText, 0, mText.length(), mBound);
float _TextWidth = mBound.width();
_Width = (int) (getPaddingLeft() + _TextWidth + getPaddingRight());
}
//高度
if(_HeightMode == MeasureSpec.EXACTLY){
_Height = _HeightSpec;
}else{
mPaint.setTextSize(mTextSize);
mPaint.getTextBounds(mText, 0, mText.length(), mBound);
float _TextHeight = mBound.height();
_Height = (int) (getPaddingTop() + _TextHeight + getPaddingBottom());
}
setMeasuredDimension(_Width, _Height);
}
@Override
protected void onDraw(Canvas canvas) {
Log.i("Tag", "onDraw():");
mPaint.setColor(Color.YELLOW);
Log.i("Tag", "getMeasuredWidth():" + getMeasuredWidth() + " " + getMeasuredHeight());
canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);
mPaint.setColor(mTextColor);
Log.i("Tag", "getWidth():" + getWidth() + " " + getHeight());
Log.i("Tag", "mBound.width():" + mBound.width() + " " + mBound.height());
canvas.drawText(mText, getWidth() / 2, getHeight() / 2 + mBound.height() / 2, mPaint);
}
}
有没有觉得生活如此美好呢,小伙伴们~?
今天主要讲解的就是 TypedArray
的用法,小伙伴不用考虑后面的 onMeasure
和 onDraw
函数,后面 LZ 会一 一道来的,耐心等待吧!
Ps:参考文章
鸿洋_Android 自定义View (一)
好了,这篇文章到这里就结束了,希望可以帮到小伙伴,have a good day~