步骤一、编写自定义属性
<?xml version="1.0" encoding="utf-8"?> <resources> <attr name="titleText" format="string" /> <attr name="titleTextColor" format="color" > </attr> <attr name="titleTextSize" format="dimension" /> <declare-styleable name="CustomTitleView"> <attr name="titleText" /> <attr name="titleTextColor" /> <attr name="titleTextSize" /> </declare-styleable> </resources>步骤二、在view的构造方法中获取自定义的属性
public CustomTitleView(Context context, AttributeSet attrs) {//加载布局时,系统默认调用两个参数的构造方法,所以在此手动调用带有三个参数的构造方法 this(context, attrs, 0); } public CustomTitleView(Context context) { this(context, null); } /** * 获得我自定义的样式属性 * * @param context * @param attrs * @param defStyle */ public CustomTitleView(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_titleText: 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); // mPaint.setColor(mTitleTextColor); mBound = new Rect(); mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound); }步骤三、调用ondraw方法,将内容画出来
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mPaint.setColor(Color.YELLOW); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);//先画背景 mPaint.setColor(mTitleTextColor); canvas.drawText(mTitleText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint); Log.e("长度尺寸","getMeasuredWidth = "+getMeasuredWidth()+",getMeasuredHeight() ="+getMeasuredHeight() +",getWidth ="+getWidth()+",mBound.width() ="+mBound.width()); }在布局中调用
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:mzb="http://schemas.android.com/apk/res-auto"> <com.example.administrator.myview.CustomTitleView android:layout_width="200dp" android:layout_height="100dp" mzb:titleText="3712" mzb:titleTextColor="#ff0000" mzb:titleTextSize="40sp" /> </RelativeLayout>注意,一定要加入
xmlns:mzb="http://schemas.android.com/apk/res-auto"如果我们修改布局为
<com.example.administrator.myview.CustomTitleView android:layout_width="wrap_content" android:layout_height="wrap_content" mzb:titleText="3712" mzb:titleTextColor="#ff0000" mzb:titleTextSize="40sp" />此时我们就需要重写onmeasure方法来测量
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int width,height; //EXACTLY 对应matchparent AT_MOST 对应wrapcontent if (widthMode == MeasureSpec.EXACTLY){ width = widthSize; }else { mPaint.setTextSize(mTitleTextSize); mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound); float textWidth = mBound.width(); int desired = (int) (getPaddingLeft() + textWidth + getPaddingRight()); width = desired; } if (heightMode == MeasureSpec.EXACTLY){ height = heightSize; }else { mPaint.setTextSize(mTitleTextSize); mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound); float textHeight = mBound.height(); int desired = (int) (getPaddingTop() + textHeight + getPaddingBottom()); height = desired; } setMeasuredDimension(width,height);//将测量出来的宽高设置进去 }我们同样可以自定义自己的点击事件,在构造方法中添加我们的点击事件
this.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mTitleText = randomText(); postInvalidate();//局部刷新布局 } });randomText()方法为一个获取随机数的方法
private String randomText() { Random random = new Random(); Set<Integer> set = new HashSet<Integer>(); while (set.size() < 4) { int randomInt = random.nextInt(10); set.add(randomInt); } StringBuffer sb = new StringBuffer(); for (Integer i : set) { sb.append("" + i); } return sb.toString(); }这样我们的自定义属性就告一段落