Android自定义View温习

在学习了鸿洋老师的自定义View之后接着也自己温习了一遍,主要是熟悉自定义View的步骤和使用,下面是例子,大家可以看看,相互学习和讨论:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="textColor" format="color" />
    <attr name="textSize" format="dimension" />
    <attr name="textContent" format="string" />
    <attr name="imageContent" format="reference" />
    <attr name="imageType" >
        <enum name="fillXY" value="0" />
        <enum name="center" value="1" />
    </attr>

    <declare-styleable name="CustomView">
        <attr name="textColor" />
        <attr name="textSize" />
        <attr name="textContent" />
        <attr name="imageContent" />
        <attr name="imageType" />
    </declare-styleable>
</resources>

这里是自定的集中属性,包括文字,颜色,大小,图片,和图片显示格式
这个大家应该都清楚
接下来就是利用自定义的View来实现一些功能,代码如下

public class CustomView extends View {

    private String textContent;

    private int textSize;

    private int textColor;

    private Bitmap imageContent;

    private int imageType;

    private TypedArray typedArray;

    private Rect rect;

    private Rect textRect;

    private Paint paint;
    public CustomView(Context context) {
        this(context, null);
    }

    public CustomView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomView, defStyleAttr, 0);
        initData();
    }

    private void initData() {
        int count = typedArray.getIndexCount();
        for (int i = 0; i < count; i++) {
            int content = typedArray.getIndex(i);
            switch (content) {
                case R.styleable.CustomView_textColor:
                    textColor = typedArray.getColor(content, Color.BLUE);
                    break;
                case R.styleable.CustomView_textContent:
                    textContent = typedArray.getString(content);
                    break;
                case R.styleable.CustomView_textSize:
                    textSize = typedArray.getDimensionPixelSize(content, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                            16, getResources().getDisplayMetrics()));
                    break;
                case R.styleable.CustomView_imageContent:
                    imageContent = BitmapFactory.decodeResource(getResources(),typedArray.getResourceId(typedArray.getIndex(content),0));
                    break;
                case R.styleable.CustomView_imageType:
                    imageType = typedArray.getInt(content,0);
                    break;
            }
        }
        typedArray.recycle();

        rect = new Rect();
        paint = new Paint();
        textRect = new Rect();
        paint.setTextSize(textSize);
        // 计算了描绘字体需要的范围
        paint.getTextBounds(textContent, 0, textContent.length(), textRect);
    }

    /**
     * EXACTLY:一般是设置了明确的值或者是MATCH_PARENT
     * AT_MOST:表示子布局限制在一个最大值内,一般为WARP_CONTENT
     * UNSPECIFIED:表示子布局想要多大就多大,很少使用
     *
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @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);

        if (widthMode != MeasureSpec.EXACTLY) {
            //宽度为图片和文字较宽的
            int textWidthSize = (int) (getPaddingLeft() + textRect.width() + getPaddingRight());
            int imageWidthSize = (int) (getPaddingLeft() + imageContent.getWidth() + getPaddingRight());
            widthSize = Math.max(textWidthSize,imageWidthSize);
        }

        if (heightMode != MeasureSpec.EXACTLY) {
            //高度是文字和图片的高度之和
            int textHeigetSize = (int) (getPaddingTop() + textRect.height() + getPaddingBottom());
            int imageHeightSize = (int) (getPaddingLeft() + imageContent.getHeight() + getPaddingRight());
            heightSize = Math.min(textHeigetSize,imageHeightSize);
        }

        setMeasuredDimension(widthSize, heightSize);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        /**
         * 边框
         */
        paint.setStrokeWidth(4);
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(Color.CYAN);
        canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), paint);

        rect.left = getPaddingLeft();  //设置绘图左边的坐标
        rect.right = getMeasuredWidth() - getPaddingRight();  //设置绘图右边的坐标
        rect.top = getPaddingTop();  //设置绘图上边的坐标
        rect.bottom = getMeasuredHeight() - getPaddingBottom();   //设置绘图下面的坐标

        paint.setColor(textColor);//设置画笔颜色,开始绘制文字
        paint.setStyle(Paint.Style.FILL);  //设置撑满全布局

        if(textRect.width() > getMeasuredWidth()){
            //重新设置文字的宽度为布局的宽度
            TextPaint textPaint = new TextPaint(paint);
            String msg = TextUtils.ellipsize(textContent, textPaint, (float) getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),
                    TextUtils.TruncateAt.END).toString();
            canvas.drawText(msg, getPaddingLeft(), getMeasuredHeight() - getPaddingBottom(), paint);

        }else {
            //绘制在底部剧中
            canvas.drawText(textContent,getMeasuredWidth()/2 - textRect.width()/2,getMeasuredHeight() - getPaddingBottom(),paint);
        }

        if (imageType == 0)
        {
            //画布剪掉已经绘制的布局
            rect.bottom -= textRect.height();
            canvas.drawBitmap(imageContent, null, rect, paint);
        } else
        {
            //计算居中的矩形范围
            rect.left = getMeasuredWidth() / 2 - imageContent.getWidth() / 2;
            rect.right = getMeasuredWidth() / 2 + imageContent.getWidth() / 2;
            rect.top = (getMeasuredHeight() - textRect.height()) / 2 - imageContent.getHeight() / 2;
            rect.bottom = (getMeasuredHeight() - textRect.height()) / 2 + imageContent.getHeight() / 2;

            canvas.drawBitmap(imageContent, null, rect, paint);
        }
    }
}

这个是核心代码,也很简单,基本都有注释,主要就是一个便利,取出自定义的属性,获取它的值
然后计算画布的宽高,最后就是根据宽高和图片的样式来绘制自定义的布局,基本是对第一次的复习,代码很简单,与鸿洋老师的也很类似,大家有什么不明白的也可以留言
最后附上我的布局文件和最后的效果图

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:zxf="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.example.myapplication.view.CustomView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        zxf:textSize="10dp"
        zxf:textContent="111111111111"
        zxf:textColor="@color/colorAccent"
        zxf:imageContent="@drawable/ic_launcher"
        zxf:imageType="center"/>

    <com.example.myapplication.view.CustomView
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="20dp"
        zxf:textSize="10dp"
        zxf:textContent="5555555"
        zxf:textColor="@android:color/black"
        zxf:imageContent="@drawable/ic_launcher"
        zxf:imageType="fillXY" />

    <com.example.myapplication.view.CustomView
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="20dp"
        zxf:textSize="20dp"
        zxf:textContent="睡觉啦啦啦啦啦啦啦啦"
        zxf:textColor="@android:color/holo_green_light"
        zxf:imageContent="@drawable/a"
        zxf:imageType="fillXY" />

</LinearLayout>

这里写图片描述
好了,就这些了,如果对你有帮助,请留下宝贵的意见。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值