【Android】android自定义View以及属性的实现(2)

前言

如果对自定义ViewGroup感兴趣的,可以去查看第一篇文章:

https://my.oschina.net/u/2547914/blog/810722

1.自定义View的属性

2.在View的构造方法中获取我们自定义的属性

3.重写onMesure方法(有的时候重写)

4.重写onDraw方法

下面是一个完成的代码,自定义的View,上面有很想详细的注释,这边就不过多的详解了,我这边只是为了记录一下自己的笔记,如果看到对你有帮助,欢迎留言和关注交流,如若没有,请忽略。

完整代码:

package com.zhjy.hxf.hzcustomview.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;

import com.zhjy.hxf.hzcustomview.R;

/**
 * @author :huangxianfeng on 2016/12/26.
 * 实现自定义ImageView的属性等
 * 1.自定义View的属性
 * 2.在View的构造方法中获取我们自定义的属性
 * 3.重写onMesure方法(有的时候重写)
 * 4.重写onDraw方法
 */
public class CustomImageView extends View {

    private final static String TAG = "CustomImageView";
    /**
     * 控件的宽
     */
    private int mWidth;
    /**
     * 控件的高
     */
    private int mHeight;
    /**
     * 控件中的图片
     */
    private Bitmap mImage;
    /**
     * 图片的缩放模式
     */
    private int mImageScale;
    private static final int IMAGE_SCALE_FITXY = 0;
    private static final int IMAGE_SCALE_CENTER = 1;
    /**
     * 图片的介绍
     */
    private String mTitle;
    /**
     * 字体的颜色
     */
    private int mTextColor;
    /**
     * 字体的大小
     */
    private int mTextSize;

    private Paint mPaint;
    /**
     * 对文本的约束
     */
    private Rect mTextBound;
    /**
     * 控制整体布局
     */
    private Rect rect;

    public CustomImageView(Context context) {
        super(context);
        Log.e(TAG, "n = 1");
    }

    public CustomImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        Log.e(TAG, "n = 2");
    }

    public CustomImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        Log.e(TAG, "n = 3");


        /**
         * TypedArray:获取TypedArray对象来对属性进行操作设置。
         */
        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomImageView,defStyle,0);
        int n = typedArray.getIndexCount();
        Log.e(TAG,"n = "+n);
        for (int i = 0; i < n; i++) {
            int attr = typedArray.getIndex(i);
            switch (attr){
                case R.styleable.CustomImageView_image:
                    Log.e(TAG,"执行了CustomImageView_image");
                    mImage = BitmapFactory.decodeResource(getResources(),typedArray.getResourceId(attr,0));
                    break;
                case R.styleable.CustomImageView_imageScaleType:
                    mImageScale = typedArray.getInt(attr,0);
                    Log.e(TAG,"执行了CustomImageView_imageScaleType");
                    break;
                case R.styleable.CustomImageView_titleText:
                    mTitle = typedArray.getString(attr);
                    Log.e(TAG,"执行了CustomImageView_titleText");
                    break;
                case R.styleable.CustomImageView_titleTextColorss:
                    mTextColor = typedArray.getColor(attr, Color.BLACK);
                    Log.e(TAG,"执行了CustomImageView_titleTextColorss");
                    break;
                case R.styleable.CustomImageView_titleTextSize:
                    mTextSize = typedArray.getDimensionPixelSize(attr,(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                            16, getResources().getDisplayMetrics()));
                    Log.e(TAG,"执行了CustomImageView_titleTextSize");
                    break;
            }
        }
        typedArray.recycle();
        typedArray.recycle();
        rect = new Rect();
        mPaint = new Paint();
        mTextBound = new Rect();//对文本的约束
        mPaint.setTextSize(mTextSize);
        // 计算了描绘字体需要的范围
        mPaint.getTextBounds(mTitle, 0, mTitle.length(), mTextBound);
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        /**
         * 设置宽度
         * 1.首先要查看测量模式
         * 2.查看测量的宽度大小
         */
        int specMode = MeasureSpec.getMode(widthMeasureSpec);
        int specSize = MeasureSpec.getSize(widthMeasureSpec);

        if (specMode == MeasureSpec.EXACTLY ){
            Log.e("xxx", "EXACTLY");
            mWidth = specSize;
        }else {
            /**
             * 由图片决定的宽
             */
            Log.e(TAG,"onMeasure 执行了 = "+(mImage ==null));
            int desireByImg = getPaddingLeft() + getPaddingRight() + mImage.getWidth();
            /**
             * 由字体决定的宽
             */
            int desireByTitle = getPaddingLeft() + getPaddingRight() + mTextBound.width();
            if (specMode == MeasureSpec.AT_MOST){
                int desire = Math.max(desireByImg,desireByTitle);
                mWidth = Math.min(desire,specSize);
                Log.e("xxx", "AT_MOST");
            }
        }

        /**
         * 设置高度
         * 1.首先要查看测量模式
         * 2.查看测量的高度大小
         */
        specMode = MeasureSpec.getMode(heightMeasureSpec);
        specSize = MeasureSpec.getSize(heightMeasureSpec);

        if (specMode == MeasureSpec.EXACTLY){
            mHeight = specSize;
        }else{
            int desire = getPaddingTop() + getPaddingBottom() + mTextBound.height();
            if (specMode == MeasureSpec.AT_MOST){
                mHeight = Math.min(desire, specSize);
            }
        }
        //设置宽度和高度给View
        setMeasuredDimension(mWidth,mHeight);
    }

    /**
     * 绘制View显示
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        /**
         * 边框
         */
        mPaint.setStrokeWidth(4);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(Color.CYAN);
        //把画笔设置给画布开始绘画
        canvas.drawRect(0,0,getMeasuredWidth(),getMeasuredHeight(),mPaint);

        /**
         * rect是绘制整体布局使用的
         */
        rect.left = getPaddingLeft();
        rect.right = mWidth - getPaddingRight();
        rect.top = getPaddingTop();
        rect.bottom = mHeight - getPaddingBottom();


        mPaint.setColor(mTextColor);
        mPaint.setStyle(Paint.Style.FILL);
        /**
         * 当前设置的宽度小于字体需要的宽度,将字体改为xxx...
         */
        if (mTextBound.width() > mWidth){
            TextPaint paint = new TextPaint();
            String msg = TextUtils.ellipsize(mTitle, paint, (float) mWidth - getPaddingLeft() - getPaddingRight(),
                    TextUtils.TruncateAt.END).toString();
            canvas.drawText(msg,getPaddingLeft(),mHeight-getPaddingBottom(),mPaint);
        }else{
            //正常情况,将字体居中
            canvas.drawText(mTitle, mWidth / 2 - mTextBound.width() * 1.0f / 2, mHeight - getPaddingBottom(), mPaint);
        }

        /**
         * 取消使用掉的高度
         */
        rect.bottom -= mTextBound.height();
        if (mImageScale == IMAGE_SCALE_FITXY){
            canvas.drawBitmap(mImage,null,rect,null);
        }else{
            /**
             * 计算居中的矩形范围
             */
            rect.left = mWidth / 2 - mImage.getWidth() / 2;
            rect.right = mWidth / 2 + mImage.getWidth() / 2;
            rect.top = (mHeight - mTextBound.height()) / 2 - mImage.getHeight() / 2;
            rect.bottom = (mHeight - mTextBound.height()) / 2 + mImage.getHeight() / 2;
            canvas.drawBitmap(mImage, null, rect, mPaint);
        }
    }
}

其中牵扯到了自定义属性,这也是在我们编程中有时候经常遇到的问题:

首先要在values文件中新建一个attrs.xml布局文件:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <!-- 关于 attr属性自定义详解
        (1)attr的节点有两个属性,name 和format,name是属性的名称,format是属性自定的一个类型
        (2)format:的类型有以下几种
            1.reference:这个是引用类型比如<attr name="icon" format="reference"/>
            2.color:是颜色的类型。
            3.String:是字符串的类型
            4.dimension:是尺寸的类型,主要是用于尺寸的大小设置
        -->
    
    <attr name="titleText" format="string"/>
    <attr name="titleTextSize" format="dimension"/>
    <attr name="titleTextColorss" format="color"/>
    <attr name="image" format="reference"/>

    <attr name="imageScaleType">
        <enum name="fillXY" value="0"></enum>
        <enum name="center" value="1"></enum>
    </attr>

    <!--这个位置只要attr属性的name,而不需要format属性,这里只是为了加强-->
    <declare-styleable name="CustomImageView">
        <attr name="titleText" />
        <attr name="titleTextSize" />
        <attr name="titleTextColorss" />
        <attr name="image" />
        <attr name="imageScaleType" />
    </declare-styleable>
    
</resources>

然后在自定义的View中找到attrs中定义的属性:

        /**
         * TypedArray:获取TypedArray对象来对属性进行操作设置。
         */
        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomImageView,defStyle,0);
        int n = typedArray.getIndexCount();
        Log.e(TAG,"n = "+n);
        for (int i = 0; i < n; i++) {
            int attr = typedArray.getIndex(i);
            switch (attr){
                case R.styleable.CustomImageView_image:
                    Log.e(TAG,"执行了CustomImageView_image");
                    mImage = BitmapFactory.decodeResource(getResources(),typedArray.getResourceId(attr,0));
                    break;
                case R.styleable.CustomImageView_imageScaleType:
                    mImageScale = typedArray.getInt(attr,0);
                    Log.e(TAG,"执行了CustomImageView_imageScaleType");
                    break;
                case R.styleable.CustomImageView_titleText:
                    mTitle = typedArray.getString(attr);
                    Log.e(TAG,"执行了CustomImageView_titleText");
                    break;
                case R.styleable.CustomImageView_titleTextColorss:
                    mTextColor = typedArray.getColor(attr, Color.BLACK);
                    Log.e(TAG,"执行了CustomImageView_titleTextColorss");
                    break;
                case R.styleable.CustomImageView_titleTextSize:
                    mTextSize = typedArray.getDimensionPixelSize(attr,(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                            16, getResources().getDisplayMetrics()));
                    Log.e(TAG,"执行了CustomImageView_titleTextSize");
                    break;
            }

在最上面也有很完整的代码,在自定义的属性里面,也有不同表现的使用详解。

欢迎大家留言和关注交流。

转载于:https://my.oschina.net/huangxianfeng/blog/813082

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值