Android自定义View【实战教程】2⃣️----自定义view那些事

很多人对自定义view都很胆怯,其实自己去玩一玩会发现很简单。

#知识点
个人把自定义View分为以下四个步骤

####1、自定义View的属性
####2、在View的构造方法中获得我们自定义的属性
####3、重写onMesure
####4、重写onDraw


##简单的自定义View Demo
###1、自定义View的属性

<?xml version="1.0" encoding="utf-8"?>
<resources>
    //??????,??????
    <attr name="titleText" format="string"/>
    <attr name="titleTextSize" format="dimension"/>
    <attr name="titleTextColor" format="color"/>
    <attr name="image" format="reference"/>
    <attr name="imageScaleType" >
        <enum name="fillXY" value="0"/>
        <enum name="center" value="1"/>
    </attr>

    //??????????
    <declare-styleable name="CustomImageView">
        <attr name="titleText" />
        <attr name="titleTextSize" />
        <attr name="titleTextColor" />
        <attr name="image" />
        <attr name="imageScaleType" />
    </declare-styleable>
</resources>

###2、在View的构造方法中获得我们自定义的属性

public class CustomImageView extends View {
private static final String TAG = CustomImageView.class.getSimpleName();
    /**
     * ????
     */
    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);
    }

    public CustomImageView(Context context, @Nullable AttributeSet attrs) {
        this(context,attrs,0);
    }

    public CustomImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomImageView, defStyleAttr, 0);

        int indexCount = typedArray.getIndexCount();

        for (int i = 0; i < indexCount; i++) {
            int attr = typedArray.getIndex(i);
            switch (attr) {
                case R.styleable.CustomImageView_image:
                    mImage = BitmapFactory.decodeResource(getResources(), typedArray.getResourceId(attr, 0));
                    break;
                case R.styleable.CustomImageView_imageScaleType:
                    mImageScale = typedArray.getInt(attr, 0);
                    break;
                case R.styleable.CustomImageView_titleText:
                    mTitle = typedArray.getString(attr);
                    break;
                case R.styleable.CustomImageView_titleTextColor:
                    mTextColor = typedArray.getColor(attr, Color.BLACK);
                    break;
                case R.styleable.CustomImageView_titleTextSize:
                    mTextSize = typedArray.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,16,getResources().getDisplayMetrics()));
                    break;
            }

        }

        typedArray.recycle();
        rect = new Rect();
        mPaint = new Paint();
        mTextBound = new Rect();
        mPaint.setTextSize(mTextSize);
        //???????????
        mPaint.getTextBounds(mTitle,0,mTitle.length(),mTextBound);
    }
}

###3、重写onMesure

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

        // TODO: 2017/3/22
        /**
         * UNSPECIFIED ????????????,????????
         * EXACTLY ?????????,???????????,??????????
         * AT_MOST ????????????
         */
        //????
        int specMode = MeasureSpec.getMode(widthMeasureSpec);
        int specSize = MeasureSpec.getSize(widthMeasureSpec);

        if(specMode == MeasureSpec.EXACTLY){ //match_parent
            Logger.i("EXACTLY");

            mWidth = specSize;
        }else {
            //??????
            int desireByImg = getPaddingLeft() + getPaddingRight() + mImage.getWidth();
            //??????
            int desireByTitle = getPaddingLeft() + getPaddingRight() + mTextBound.width();

            if(specMode == MeasureSpec.AT_MOST){ //wrap_content
                int desire = Math.max(desireByImg,desireByTitle);
                mWidth = Math.min(desire,specSize);
                Logger.i("AT_MOST");
            }

            Logger.i("getPaddingLeft "+getPaddingLeft() + "    getPaddingRight()"+ getPaddingRight());
        }

        //????
        specMode = MeasureSpec.getMode(heightMeasureSpec);
        specSize = MeasureSpec.getSize(heightMeasureSpec);

        if(specMode == MeasureSpec.EXACTLY){  //macth_parent
            mHeight = specSize;
        }else{
            int desire = getPaddingTop()+getPaddingBottom()+mImage.getHeight()+mTextBound.height();

            if(specMode == MeasureSpec.AT_MOST){ //wrap_content
                mHeight = Math.min(desire,specSize);
            }
        }

        setMeasuredDimension(mWidth,mHeight);
    }

###4、重写onDraw

@Override
    protected void onDraw(Canvas canvas) {
        //super.onDraw(canvas);

        /**
         * ??
         */
        mPaint.setStrokeWidth(4);
        mPaint.setStyle(STROKE);  // STROKE ?? FILL??
        mPaint.setColor(Color.CYAN);
        canvas.drawRect(0,0,getMeasuredWidth(),getMeasuredHeight(),mPaint);

        // TODO: 2017/3/22
        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 textpaint = new TextPaint(mPaint);
            String msg = TextUtils.ellipsize(mTitle,textpaint,(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);
        }

        // TODO: 2017/3/22
        //???????
        rect.bottom -= mTextBound.height();

        //?????
        if (mImageScale == IMAGE_SCALE_FITXY)
        {
            canvas.drawBitmap(mImage, null, rect, mPaint);
        } 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;

            Logger.e("mWidth : " +mWidth + "    mImage.getWidth() : " +mImage.getWidth());

            canvas.drawBitmap(mImage, null, rect, mPaint);
        }

    }

就是这么简单 完成了自定义View 接下来让我们看看如何使用

##应用
在布局使用的时候先要定义一下如下信息

xmlns:app="http://schemas.android.com/apk/res-auto"

然后才能使用

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.libin.factory.widget.CustomImageView
        android:id="@+id/civ_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:padding="10dp"
        app:image="@drawable/bg_test"
        app:imageScaleType="center"
        app:titleText="hello andorid ! "
        app:titleTextColor="#ff0000"
        app:titleTextSize="30sp" />
</LinearLayout>

???
???????

工程地址:
https://github.com/libin7278/Factory
java --》widget

扫码关注公众号“伟大程序猿的诞生“,更多干货新鲜文章等着你~

公众号回复“资料获取”,获取更多干货哦~

有问题添加本人微信号“fenghuokeji996” 或扫描博客导航栏本人二维码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值