自定义View2

步骤

  1. 自定义属性
  2. 重写onMeasure(…)
  3. 重写onDraw(…)

带着问题看代码

  1. 怎么获取图片资源
  2. 怎么确定View的位置
  3. 在字符串过长时,怎么在后面加入省略号
  4. 在什么时候调用onDraw(…)和onMeasure()方法 (以后分析)

效果图

这里写图片描述

  • 第一个View的width_parent和height_parent固定为180dp
  • 第二个View的width_parent和height_parent为wrap_content
  • 第三个View的width_parent和height_parent为match_parent

布局文件

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:test="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#fff"
    android:orientation="vertical"
    tools:context="com.nobita.customimageview.MainActivity">

    <com.nobita.customimageview.MyImageView
        android:layout_width="180dp"
        android:layout_height="180dp"
        test:mImage="@mipmap/ic_launcher"
        test:mImageSize="30dp"
        test:mText="Hello Worldfffffffffffffffffff!"
        test:mTextColor="#f00"
        test:mTextSize="20sp"/>

    <com.nobita.customimageview.MyImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        test:mImage="@mipmap/ic_launcher"
        test:mImageSize="30dp"
        test:mText="Hello World!"
        test:mTextColor="#f00"
        test:mTextSize="20sp"/>

    <com.nobita.customimageview.MyImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        test:mImage="@mipmap/ic_launcher"
        test:mImageSize="30dp"
        test:mText="Hello Worldfffffffffffffffffff!"
        test:mTextColor="#f00"
        test:mTextSize="20sp"/>

</LinearLayout>

attrs.xml

<resources>
    <declare-styleable name="MyImageView">
        <attr name="mImage" format="reference"></attr>
        <attr name="mImageSize" format="dimension"></attr>
        <attr name="mText" format="string"></attr>
        <attr name="mTextSize" format="dimension"></attr>
        <attr name="mTextColor" format="color"></attr>
    </declare-styleable>
</resources>

自定义View代码

public class MyImageView extends View {

    private String mText;
    private int mTextColor;
    private float mTextSize;
    private float mImageSize;
    private int mImageSrc;
    private Paint mPaint;
    private final Bitmap mBitmap;
    private int mTextWidthSize;
    private int mTextHeightSize;
    private int mImageWidthSize;
    private int mImageHeightSize;

    public MyImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint();

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyImageView);

        mText = a.getString(R.styleable.MyImageView_mText);
        mTextSize = a.getDimension(R.styleable.MyImageView_mTextSize, 30);
        mTextColor = a.getColor(R.styleable.MyImageView_mTextColor, Color.GREEN);

        mImageSize = a.getDimension(R.styleable.MyImageView_mImageSize, 30);
        mBitmap = BitmapFactory.decodeResource(getResources(), a.getResourceId(R.styleable.MyImageView_mImage, 0));
        a.recycle();

        mPaint.setColor(mTextColor);
        mPaint.setTextSize(mTextSize);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        int width;
        int height;

        //计算字体的长宽
        Rect mBound = new Rect();
        mPaint.getTextBounds(mText, 0, mText.length(), mBound);
        mTextWidthSize = mBound.width();
        mTextHeightSize = mBound.height();

        //计算图片的长宽
        mImageWidthSize = mBitmap.getWidth();
        mImageHeightSize = mBitmap.getHeight();

        //根据widthMode的确定长宽
        if (widthMode == MeasureSpec.EXACTLY) {
            width = widthSize;
        } else {
            width = mTextWidthSize > mImageWidthSize ? mTextWidthSize : mImageWidthSize + getPaddingLeft() + getPaddingRight();
        }

        //根据heightMode的确定长宽
        if (heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;
        } else {
            height = mTextHeightSize + mImageHeightSize + getPaddingBottom() + getPaddingTop();
        }

        setMeasuredDimension(width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {

        //画边框
        Paint mBorderPaint = new Paint();
        mBorderPaint.setStrokeWidth(4);
        mBorderPaint.setStyle(Paint.Style.STROKE);
        mBorderPaint.setColor(Color.GREEN);
        canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mBorderPaint);

        //TextView坐标
        int mTextX = getMeasuredWidth() / 2 - mTextWidthSize / 2;
        int mTextY = getMeasuredHeight() / 2 + mTextHeightSize / 2 + mImageHeightSize / 2;
        //ImageView坐标
        int mImageX = getMeasuredWidth() / 2 - mImageWidthSize / 2;
        int mImageY = getMeasuredHeight() / 2 - mImageHeightSize / 2 - mTextHeightSize / 2;

        //过长的TextView后面加...
        Rect bound = new Rect();
        int length = 0;
        if (mTextWidthSize > getMeasuredWidth()) {
            for (int i = 0; i < mText.length(); i++) {
                mPaint.getTextBounds(mText + "...", 0, i + 3, bound);
                if (bound.width() >= getMeasuredWidth()) {
                    length = i > 0 ? --i : 0;
                    break;
                }
            }
            mText = mText.substring(0, length) + "...";
            mTextX = 0;
        }


        canvas.drawText(mText, mTextX, mTextY, mPaint);
        canvas.drawBitmap(mBitmap, mImageX, mImageY, new Paint());
    }
}

构造函数

  • 在构造函数中获取自定义属性的值

onMeasure(…)

  • 通过字符串和图片的长宽,根据Mode的样式来确定View长宽,最后setMeasuredDimension(width, height);

onDraw(…)

  • 计算字符串和图片应该放置的位置
  • 计算字符串是否需要结尾省略号
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值