自定义带描述的ImageView

  1. 在values/attrs.xml文件中创建自定义的属性。设置了自定义的属性。
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="texttitle" format="string"/>
    <attr name="texttitlesize" format="dimension"/>
    <attr name="texttitlecolor" format="color"/>
    <attr name="iamge" format="reference"/>
    <attr name="imageScaleType" format="enum">
        <enum name="fillXY" value="0"/>
        <enum name="center" value="1"/>
    </attr>

    <declare-styleable name="MyCustomImageView">
        <attr name="texttitle"/>
        <attr name="texttitlesize"/>
        <attr name="texttitlecolor"/>
        <attr name="iamge"/>
        <attr name="imageScaleType"/>
    </declare-styleable>
</resources>
  1. 布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:keke="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.best.keke.mycustomimageview.MyCustomImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="15dp"
        android:padding="10dp"
        keke:texttitle="你好啊aaaaa"
        keke:imageScaleType="center"
        keke:iamge="@mipmap/ic_launcher"
        keke:texttitlecolor="#ff1231"
        keke:texttitlesize="20sp"/>

    <com.best.keke.mycustomimageview.MyCustomImageView
        android:layout_width="130dp"
        android:layout_height="wrap_content"
        android:layout_margin="15dp"
        android:padding="10dp"
        keke:texttitle="helloword!android ios java"
        keke:imageScaleType="center"
        keke:iamge="@mipmap/ic_launcher"
        keke:texttitlecolor="#ff1231"
        keke:texttitlesize="20sp"/>

    <com.best.keke.mycustomimageview.MyCustomImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="15dp"
        android:padding="10dp"
        keke:texttitle="你"
        keke:imageScaleType="center"
        keke:iamge="@mipmap/ic_launcher"
        keke:texttitlecolor="#ff1231"
        keke:texttitlesize="20sp"/>
</LinearLayout>

3.自定义view,在view的构造方法中获取到自定义的属性

    private String textTitle;   // 图片下的字体
    private Bitmap image;
    private int imageScale;
    private int textColor;
    private int textSize;

    private Rect rect;  // 整个控件的边界
    private Paint paint;
    private Rect textBound;     // 文本的边界

    // 控件的宽高
    private int width;
    private int height;

    private static final int IMAGE_SCALE_FITXY = 0;
    private static final int IMAGE_SCALE_CENTER = 1;

    public MyCustomImageView(Context context) {
        this(context, null);
    }

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

    public MyCustomImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        // 初始化属性
        TypedArray typedArray =
                context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyCustomImageView, defStyleAttr, 0);
        // 获取到属性值的个数
        int indexCount = typedArray.getIndexCount();
        Log.i("tag", "属性值的个数:" + indexCount);
        for (int i = 0; i < indexCount; i++) {
            // 获取到每一个属性
            int attr = typedArray.getIndex(i);
            switch (attr) {
                case R.styleable.MyCustomImageView_iamge:
                    image = BitmapFactory.decodeResource(getResources(), typedArray.getResourceId(attr, 0));
                    break;
                case R.styleable.MyCustomImageView_texttitle:
                    textTitle = typedArray.getString(attr);
                    Log.e("tag", textTitle + "texttitle");
                    break;
                case R.styleable.MyCustomImageView_imageScaleType:
                    imageScale = typedArray.getInt(attr, 0);
                    break;
                case R.styleable.MyCustomImageView_texttitlesize:
                    textSize = typedArray.getDimensionPixelSize(attr, (int) TypedValue.applyDimension
                            (TypedValue.COMPLEX_UNIT_DIP, 16, getResources().getDisplayMetrics()));
                    break;
                case R.styleable.MyCustomImageView_texttitlecolor:
                    textColor = typedArray.getColor(attr, Color.BLACK);
                    break;
            }
        }
            typedArray.recycle();
            rect = new Rect();
            textBound = new Rect();
            paint = new Paint();
            // 设置字体的大小
            paint.setTextSize(textSize);
            // 设置字体需要的大小范围
            Log.e("tag", textTitle + "texttitle");
            Log.e("tag", textBound + "textBound");
            paint.getTextBounds(textTitle, 0, textTitle.length(), textBound);
        }

4.重写onMeasure()方法

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        // 设置宽度
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);

        if (widthMode == MeasureSpec.EXACTLY) {
            width = widthSize;
        } else {
            // 当图片宽度大于字体宽度的时候,由图片决定宽度
            int desiredWidthByImage = getPaddingLeft() + getPaddingRight() + image.getWidth();
            // 当字体宽度大于图片宽度的时候,由字体决定宽度
            int desiredWidthByTitle = getPaddingLeft() + getPaddingRight() + textBound.width();

            // 当属性值为wrap_content的时候
            // 取两者较大的
            int desiredWidth = Math.max(desiredWidthByImage, desiredWidthByTitle);
            width = Math.min(desiredWidth, widthSize);
        }

        // 设置高度
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        if (heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;
        } else {
            int desiredHeight = getPaddingBottom() + getPaddingTop()
                    + image.getHeight() + textBound.height();
            height = Math.min(desiredHeight, heightSize);
        }
        // 设置测量的尺寸
        setMeasuredDimension(width, height);
    }

5.重写onDraw()方法

@Override
    protected void onDraw(Canvas canvas) {
        //super.onDraw(canvas);
        // 设置画笔的样式
        paint.setStrokeWidth(3);    // 边框线的粗细
        paint.setStyle(Paint.Style.STROKE); // 画笔的风格,空心或者是实心
        paint.setColor(Color.GREEN);    // 设置画笔的颜色
        // 画边框
        canvas.drawRect(0, 0,getMeasuredWidth(),getMeasuredHeight(), paint);

        // 获取到矩形的上下左右边距
        rect.left = getPaddingLeft();
        rect.top = getPaddingTop();
        rect.right = width - getPaddingRight();
        rect.bottom = height - getPaddingBottom();

        paint.setColor(textColor);
        paint.setStyle(Paint.Style.FILL);

        // 若当前的宽度小于字体的宽度,给字体添加带省略号的。
        if (textBound.width() > width) {
            TextPaint textPaint = new TextPaint();
            /**
             * Android TextView中有个内容过长加省略号的属性,即ellipsize
             * TextUtils.TruncateAt.END  表示将省略号添加在结尾处
             */
            String msg = TextUtils.ellipsize(textTitle, textPaint, width - getPaddingLeft() - getPaddingRight(),
                    TextUtils.TruncateAt.END).toString();
            /**
             * Draw the text, with origin at (x,y), using the specified paint. The
             * origin is interpreted based on the Align setting in the paint.
             * @param text  The text to be drawn    要写的文字
             * @param x     The x-coordinate of the origin of the text being drawn  x坐标
             * @param y     The y-coordinate of the baseline of the text being drawn    y坐标
             * @param paint The paint used for the text (e.g. color, size, style)   画笔
             */
            canvas.drawText(msg, getPaddingLeft(), height - getPaddingBottom(), paint);
        } else {
            // 将字体进行居中显示
            canvas.drawText(textTitle, width / 2 - textBound.width() / 2,
                    height - getPaddingBottom() / 2, paint);
        }

        rect.bottom -= textBound.height();

        if (imageScale == IMAGE_SCALE_FITXY) {
            /**
             * drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint);
             * Rect src: 是对图片进行裁截,若是空null则显示整个图片
             * RectF dst:是图片在Canvas画布中显示的区域,
             *              大于src则把src的裁截区放大,
             *              小于src则把src的裁截区缩小。
             */
            canvas.drawBitmap(image, null, rect, paint);
        } else {
            // 计算居中的矩形的范围
            rect.left = width / 2 - image.getWidth() / 2;   //控件的一半 - 图片的一半
            rect.bottom = (height - textBound.height()) / 2 + image.getHeight() / 2;
            rect.top = (height - textBound.height()) / 2 - image.getHeight() / 2;
            rect.right = width / 2 + image.getWidth() / 2;

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

样式图如下:

padding的图示解析:

参考出处:http://blog.csdn.net/lmj623565791/article/details/24300125

时间: 2024-08-03 15:40:35

自定义带描述的ImageView的相关文章

【Android】Android实现自定义带文字和图片的Button

在Android开发中经常会需要用到带文字和图片的button,下面来讲解一下常用的实现办法. 一.用系统自带的Button实现 最简单的一种办法就是利用系统自带的Button来实现,这种方式代码量最小.在Button的属性中有一个是drawableLeft,这个属性可以把图片设置在文字的左边,但是这种方式必须让icon的背景色是透明的,如果icon的背景色不是透明的话,会导致点击按钮时icon部分的背景色不会发生变化. 主要代码: <Button android:id="@+id/bt3

自定义带图片和文字的ImageTextButton

今天我们来讲一下有关自定义控件的问题,今天讲的这篇是从布局自定义开始的,难度不大,一看就明白,估计有的同学或者开发者看了说,这种方式多此一举,但是小编我不这么认为,多一种解决方式,就多一种举一反三的学习.下一次或者过几天我会从自定义属性,在布局文件中使用属性的方式再讲一篇关于自定义控件的文章,希望对大家能够有所帮助. 现在开始讲自定义带图片和文字的ImageTextButton的实现方法. 效果图如下: 第一步:新建一个image_text_buttton.xml的布局文件,供自定义的控件使用

android控件---自定义带文本的ImageButton

由于SDK提供的ImageButton只能添加图片,不能添加文字:而Button控件添加的文字只能显示在图片内部:当我们需要添加文字在图片外部时就不能满足我们的需求了,顾只能自己写个自定义ImageButton.说是ImageButton,其实并不是继承于ImageButton,而是从LinearLayout继承,由于LinearLayout是线性排列,通过setOrientation(LinearLayout.VERTICAL)的方式达到View垂直排列的目的,所以很简单,只需要添加两个Vie

Android 自定义带刻度的seekbar

自定义带刻度的seekbar 1.布局 <span style="font-family:SimHei;font-size:18px;"><com.imibaby.client.views.CustomSeekbar android:id="@+id/myCustomSeekBar" android:layout_width="wrap_content" android:layout_height="wrap_cont

【Android-EditText】自定义带删除功能的EditText

我们经常在一些应用中见到输入框带有删除功能,今天我们就来实现这个功能(文字组织能力不强,大家随便看看).主要是记录一下自己的学习经历,如果对大家有帮助,我会更开心的. 先上图: 实现要点: 1.当输入框为空时,删除按钮隐藏: 2.当输入框不为空时,显示删除按钮. 核心代码: package com.example.view; import com.example.ui.R; import android.content.Context; import android.graphics.Rect;

android自定义view-打造圆形ImageView(四)终结篇

前言: 说实话,这段时间忙着修改毕业论文,好长时间没有碰代码了,真是罪过呀.今天我们就来奉上我们打造圆形ImageView的终结篇,以后如果还有新的创意再说啦.本文是在前面三篇的基础上得来的,详细请戳android自定义view-打造圆形ImageView(一).android自定义view-打造圆形ImageView(二).android自定义view-打造圆形ImageView(三). 效果图: 正文: 其实看了上面的效果图,大家应该都一目了然了,就是很多应用经常见到的带有白色边缘的渐变头像

Android开发之自定义圆角矩形图片ImageView的实现

android中的ImageView只能显示矩形的图片,这样一来不能满足我们其他的需求,比如要显示圆角矩形的图片,这个时候,我们就需要自定义ImageView了,其原理就是首先获取到图片的Bitmap,然后进行裁剪对应的圆角矩形的bitmap,然后在onDraw()进行绘制圆角矩形图片输出. 效果图如下: 自定义的圆形的ImageView类的实现代码如下: package com.xc.xcskin.view; import android.content.Context; import and

Shell的文件描述符操作,包括标准输入,标准输出,自定义文件描述符

Abstract: 1) Linux Shell 命令的标准输入.标准输出.标准错误,及其重定位: 2)Linux Shell 操作自定义文件描述符: 文件描述符是与文件相关联的一些整数,他们保持与已打开文件的关联.众所周知的文件描述符是标准输入stdin.标准输出stdout.标准错误stderr,我们可以重定位这些文件描述符关联文件的内容到另外一个文件文件描述符. 1. Linux Shell 命令的标准输入.标准输出.标准错误 当我们在编写 shell 脚本时,我们会非常频繁地操作执行命令

【Android】Android自定义带board的圆角控件

介绍 圆角控件常用于头像,按钮,图标等,用途十分广泛,而且常常配合board使用. 在IOS中,UIVIew的CALayer层已经提供了圆角和board的方法,所以圆角控件的制作非常简单,只需要类似以下简单代码即可实现: view.layer.cornerRadius = 20; view.layer.borderColor = [UIColor yellowColor].CGColor; view.layer.borderWidth = 10; view.clipsToBounds = YES