前面已经简单介绍过一些自定义View的实现,现在再利用自定义View实现显示一张图片的功能

1、首先编写attrs.xml文件
<resources>
    <declare-styleable name="CustomImageView">
        <attr name="text" format="string" />
        <attr name="textSize" format="dimension" />
        <attr name="textColor" format="color" />
        <attr name="background" format="reference" />
        <attr name="imageScaleType">
            <enum name="fillXY" value="0" />
            <enum name="center" value="1" />
        </attr>
    </declare-styleable>
</resources>

2、在自定义View中获得我们自定义属性:
public class CustomImageView extends View {
    /**
     * 自定义View的宽
     */
    private int mWidth;
    /**
     * 自定义View的高
     */
    private int mHeight;
    /**
     * 自定义View的图片
     */
    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) {
        this(context, null);
    }
    public CustomImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    /**
     * 初始化自定义类型
     * 
     * @param context
     * @param attrs
     * @param defStyle
     */
    public CustomImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        TypedArray typedArray = context.getTheme().obtainStyledAttributes(
                attrs, R.styleable.CustomImageView, defStyle, 0);
        mTitle = typedArray.getString(typedArray.getIndex(0));//获得自定义属性的title
        //获得自定义属性的textSize
        mTextSize = typedArray.getDimensionPixelSize(typedArray.getIndex(1),
                (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16,
                        getResources().getDisplayMetrics()));
        //获得自定义属性的textColor
        mTextColor = typedArray.getColor(typedArray.getIndex(2), Color.BLACK);
        //获得自定义属性的image
        mImage = BitmapFactory.decodeResource(getResources(),
                typedArray.getResourceId(typedArray.getIndex(3), 0));
        //自定义属性的imageScale
        mImageScale = typedArray.getInt(typedArray.getIndex(4), 0);
        typedArray.recycle();
        rect = new Rect();
        mPaint = new Paint();
        mTextBound = new Rect();
        mPaint.setTextSize(mTextSize);
        // 计算描绘字体需要的范围
        mPaint.getTextBounds(mTitle, 0, mTitle.length(), mTextBound);
    }

3、重写onMeasure 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        /**
         * 设置自定义View的宽度
         */
        int specMode = MeasureSpec.getMode(widthMeasureSpec);
        int specSize = MeasureSpec.getSize(widthMeasureSpec);
        if (specMode == MeasureSpec.EXACTLY)// match_parent , accurate
        {
            mWidth = specSize;
        } else {
            // 自定义View的宽度,由左右填充和图片宽度决定
            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);
            }
        }
        /***
         * 设置自定义View
         */
        specMode = MeasureSpec.getMode(heightMeasureSpec);
        specSize = MeasureSpec.getSize(heightMeasureSpec);
        if (specMode == MeasureSpec.EXACTLY)// 设置了明确的值或者是MATCH_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 
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.left = getPaddingLeft();
        rect.right = mWidth - getPaddingRight();
        rect.top = getPaddingTop();
        rect.bottom = mHeight - getPaddingBottom();
        mPaint.setColor(mTextColor);
        mPaint.setStyle(Style.FILL);
        /**
         * 当前设置的宽度小于字体需要的宽度,将字体改为xxx...
         */
        if (mTextBound.width() > mWidth) {
            TextPaint paint = new TextPaint(mPaint);
            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) {
            //绘制image
            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;
            canvas.drawBitmap(mImage, null, rect, mPaint);
        }
    }

做完这些,我们就可以在activity_main.xml文件中引用了
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:custom="http://schemas.android.com/apk/res/com.example.activity"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <com.example.activity.view.CustomImageView
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:padding="10dp"
        custom:background="@drawable/ic_launcher"
        custom:imageScaleType="center"
        custom:text="hello world !"
        custom:textColor="#00ff00"
        custom:textSize="20sp" />
    <com.example.activity.view.CustomImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:padding="10dp"
        custom:background="@drawable/ic_launcher"
        custom:imageScaleType="center"
        custom:text="hello world ! "
        custom:textColor="#ff0000"
        custom:textSize="30sp" />
    <com.example.activity.view.CustomImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:padding="10dp"
        custom:background="@drawable/wheat"
        custom:imageScaleType="fillXY"
        custom:text="麦子"
        custom:textColor="#ff0000"
        custom:textSize="12sp" />
</LinearLayout>

一共有三种效果:
  • View宽度设置为精确值,字体的长度大于此宽度
  • View宽度设置为wrap_content,字体的宽度大于图片
  • View宽度设置为wrap_content, 字体的宽度小于图片
效果如下:

源代码

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

自定义初学5——自定义View显示图片相关推荐

  1. Fullcalendar日历使用,包括视图选择、事件插入、编辑事件、事件状态更改、事件添加和删除、事件拖动调整,自定义头部,加入el-popover显示图片、图片预览、添加附件链接等,支持手机显示。

    Fullcalendar这个插件挺好,就是很多方法感觉官方文档也没怎么说,导致上手难度大,而且有些默认事件真的不太友好...废话不多说,先上效果图! 1.效果GIF 1.1 基本按钮功能 1.2  事 ...

  2. 自定义ViewGroup时子View显示不全的问题

    经检查onMeasure()和onLayout()都没有问题 最后发现原因是在onDraw()和dispatchDraw()方法上.自定义的ViewGroup加上背景就好了. Android的view ...

  3. android中使用自定义View让图片像画卷一样被展开显示

    首先看下效果图,有点卡顿,这是因为我是用android studio的screen record来录制手机视频的,然后找不到合适的mp4->gif的软件,就使用了一个录屏的软件,所以有点卡顿,但 ...

  4. 自定义相册、九宫格显示图片

    一 自定义相册 结合Glide图片库,加载显示本地图片,并可以实现单选,多选,预览功能.特点 加载最近新增图片,GridView显示 分文件夹选择图片 支持单选,多选(最大9张) 支持大图预览 以库的 ...

  5. 自定义view让图片慢慢画出来

    最近看到网上有同志在讲drawBitmap的时候,提到分段画,感觉很有意思便研究了下.大家也可以阅读原博客android中使用自定义View让图片像画卷一样被展开显示,还是博主文采好,起名字就看得出来 ...

  6. 微信js-sdk 微信自定义分享显示图片和描述不显示

    在做h5页面分享时,用到了微信的自定义分享js-sdk  . 有时会不显示自定义的图片和描述.分步骤检查出现的问题: 调用config 接口的时候传入参数 debug: true 可以开启debug模 ...

  7. BannerLayoutSimple 支持图片无限轮播的 BannerLayout,支持自定义小圆点位置以及显示位置等等,反正支持的挺多的,源码也有注释

    BannerLayoutSimple 项目地址: 7449/BannerLayoutSimple 简介:支持图片无限轮播的 BannerLayout,支持自定义小圆点位置以及显示位置等等,反正支持的挺 ...

  8. Flutter长图显示,自定义显示图片的指定区域

    需求 话不多说,直切正题!我们经常会遇到一个需求,在在一个定高的卡片中显示长图,如下图所示. 假如我们要显示这个长图.如果不考虑自定义显示长图的区域,这个很好实现,没什么可说的. Container( ...

  9. ios点击大头针气泡不弹出_iOS高德地图之自定义大头针and泡泡view

    啥都不说先看效果图demo IMG_0270.PNG 先来说说如何自定义大头针以及点击大头针时弹出的泡泡view 一 : 自定义大头针 新建CustomAnnotationView 继承自MAAnno ...

最新文章

  1. CentOS 8 即将停更,未来我们该何去何从?
  2. python读取excel数据并饼图_python生成excel表格以及饼图 示例源码
  3. 【Linux 内核】调度器 ③ ( sched_class 调度类结构体分析 | next 字段 | enqueue_task 函数 | dequeue_task 函数 )
  4. 【重复制造精讲】4、计划初识
  5. 可自动定时切换的选项卡/滑动门导航代码
  6. EFCore 5 新特性 Savepoints
  7. 如何进行正确的SQL性能优化
  8. Python 操作 redis
  9. 在C ++ STL中使用string :: to_string()将数字转换为字符串
  10. 闪光灯slave是什么意思_闪光灯实战讲解 | 室内光线+闪光灯使用配合=完美光效...
  11. 求整数 在二进制表示中有多少个1的方法
  12. 计算机基础知识第三章测试,计计算机应用基础第三章测试题
  13. Oracle 查看 SQL执行计划 SQL性能分析
  14. Android 获取经纬度处理
  15. 计算机软件师社会需求,java软件工程师的社会环境如何?
  16. js函数式编程之柯里化(curry)
  17. 环信java_java环信服务端注册IM代码
  18. Java —— 日期时间 API
  19. excel不显示提示对话框
  20. 文本编辑--程序员专属技能

热门文章

  1. Java21天打卡Day7-循环
  2. Python接口测试
  3. 月薪11.5K 土木人零基础转行软件测试工程师,他都经历了什么?
  4. 从外行到外包,从手工测试到知名互联大厂测开 我经历了我这个年龄段不该经历的事情...
  5. css悬停动画,animate.css:悬停脚本上的动画
  6. java jsfl是什么_java基础之IO2
  7. redis 公网 安全_redis配置之安全配置
  8. Matlab曲线标记间距自定义
  9. 用于he染色组织细胞核分割的两阶段U-Net算法
  10. 任意输入三个英文字母,按照字典顺序输出