对于Android自定义View是高手进阶的必经之路,所有准备在自定义View好好学习,自己学习参考的博客http://blog.csdn.net/lmj623565791/article/details/24252901 在此表示万分感谢
1、自定义View的属性,首先在res/values/ 下建立一个attr.xml , 在里面定义我们的属性和声明我们的整个样式。
<?xml version="1.0" encoding="utf-8"?> <resources> <attr name="titleText" format="string" /> <attr name="titleTextColor" format="color" /> <attr name="titleTextSize" format="dimension" /> <declare-styleable name="CustomTitleView"> <attr name="titleText" /> <attr name="titleTextColor" /> <attr name="titleTextSize" /> </declare-styleable> </resources>2、在View的构造方法中,获得我们的自定义的样式
public class CustomTitleView extends View { /** * 文本 */ private String mTitleText; /** * 文本的颜色 */ private int mTitleTextColor; /** * 文本的大小 */ private int mTitleTextSize; /** * 绘制时控制文本绘制的范围 */ private Rect mBound; private Paint mPaint; public CustomTitleView(Context context) { // 这里一定要改成this this(context, null); } public CustomTitleView(Context context, AttributeSet attrs) { // 这里一定要改成this this(context, attrs, 0); } public CustomTitleView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // 获得我们自定义的属性 TypedArray obtainStyledAttributes = context.getTheme() .obtainStyledAttributes(attrs, R.styleable.CustomTitleView, defStyle, 0); // 获取一共定义了多少个属性值 int indexCount = obtainStyledAttributes.getIndexCount(); // 遍历获得所需的属性值 for (int i = 0; i < indexCount; i++) { // 获取对应属性值的对应下标 int viewIndex = obtainStyledAttributes.getIndex(i); switch (viewIndex) { case R.styleable.CustomTitleView_titleText: mTitleText = obtainStyledAttributes.getString(viewIndex); break; case R.styleable.CustomTitleView_titleTextColor: // 默认颜色设置为黑色 mTitleTextColor = obtainStyledAttributes.getColor(viewIndex, Color.BLACK); break; case R.styleable.CustomTitleView_titleTextSize: // 默认设置为16sp,TypeValue也可以把sp转化为px mTitleTextSize = obtainStyledAttributes.getDimensionPixelSize( viewIndex, (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, 16, getResources() .getDisplayMetrics())); break; default: break; } } obtainStyledAttributes.recycle(); /** * 获得绘制文本的宽和高 */ mPaint = new Paint(); mPaint.setTextSize(mTitleTextSize); mPaint.setColor(mTitleTextColor); mBound = new Rect(); mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { <span style="color:#3366ff;">/* * onMeasure传入的widthMeasureSpec和heightMeasureSpec不是一般的尺寸数值,而是将模式和尺寸组合在一起的数值 * 。 我们需要通过int mode = MeasureSpec.getMode(widthMeasureSpec)得到模式,用int * size = MeasureSpec.getSize(widthMeasureSpec)得到尺寸。 * * mode共有三种情况,取值分别为MeasureSpec.UNSPECIFIED, MeasureSpec.EXACTLY, * MeasureSpec.AT_MOST。 * * MeasureSpec.EXACTLY是精确尺寸, * 当我们将控件的layout_width或layout_height指定为具体数值时如andorid * :layout_width="50dip", 或者为FILL_PARENT是,都是控件大小已经确定的情况,都是精确尺寸。 * * MeasureSpec.AT_MOST是最大尺寸,当控件的layout_width或layout_height指定为WRAP_CONTENT时 * , 控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸只要不超过父控件允许的最大尺寸即可。因此,此时的mode是AT_MOST, * size给出了父控件允许的最大尺寸。 * * MeasureSpec.UNSPECIFIED是未指定尺寸,这种情况不多,一般都是父控件是AdapterView,通过measure方法传入的模式 * 。 */</span> int width = 0; int height = 0; /** * 设置宽度 */ int specMode = MeasureSpec.getMode(widthMeasureSpec); int specSize = MeasureSpec.getSize(widthMeasureSpec); switch (specMode) { case MeasureSpec.EXACTLY:// 明确指定了 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:// 明确指定了 height = getPaddingTop() + getPaddingBottom() + specSize; break; case MeasureSpec.AT_MOST:// 一般为WARP_CONTENT height = getPaddingTop() + getPaddingBottom() + mBound.height(); break; } //setMeasuredDimension(int, int)设置实际大小。 setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { mPaint.setColor(Color.BLUE); <span style="color:#3366ff;"> /** * getMeasuredWidth和getWidth的区别 * getWidth 是布局中展示出来的宽度 * getMeasuredWidth是全部的长度 包括隐藏的 */</span> //绘制一个矩形 canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint); mPaint.setColor(mTitleTextColor); <span style="color:#3333ff;"> /*drawText()参数 理解好一个函数所需参数的具体含义,是用好一个函数的关键。canvas.drawText(String text, float x, float y, Paint paint)中有四个参数, 这四个参数都是表示其相对于所在View中的坐标,和屏幕坐标无关。其中text和paint较容易理解,下面重点介绍x和y的具体含义。 float x:根据官方API上的解释,该参数表示text被画的起始x坐标。其实text被画的起始位置还与Paint有关, Paint的TextAlign属性决定了text相对于起始坐标x的相对位置。例如,TextAlign的默认属性为Paint.Align.LEFT,这是text就是从起始坐标x的右侧开始画起。*/</span> canvas.drawText(mTitleText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint); } }3.修改下布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" <span style="color:#ff0000;"> xmlns:app="http://schemas.android.com/apk/res/com.example.view01"</span> android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.view01.MainActivity" > <com.example.view01.CustomTitleView app:titleText="1233" android:padding="5dp" app:titleTextColor="#ff0000" app:titleTextSize="12sp" android:layout_height="100dp" android:layout_width="300dp" /> </RelativeLayout>
自己菜鸟一个,希望大家能给我指正错误,有什么不对的地方请见谅