Android ImageView加载圆形图片且同时绘制圆形图片的外部边缘边线及边框

简介: Android ImageView加载圆形图片且同时绘制圆形图片的外部边缘边线及边框在Android早期的开发中,如果涉及到圆形图片的处理,往往需要借助于第三方的实现,见附录文章1,2。


Android ImageView加载圆形图片且同时绘制圆形图片的外部边缘边线及边框


在Android早期的开发中,如果涉及到圆形图片的处理,往往需要借助于第三方的实现,见附录文章1,2。Android本身并未从SDK层面支持圆形图。但是在后来最新的Android SDK中,增加了对于圆形、圆角图的支持,引入了RoundedBitmapDrawable,RoundedBitmapDrawable的作用是将一个常规图片修剪成圆形或圆角图。RoundedBitmapDrawable的出现,从此在处理简单圆形、圆角图时候简单多了。
但是,对于复杂设计效果的实现,仅仅有一个RoundedBitmapDrawable是不够的,比如,有这样一种设计要求:把一个常规图片修剪成圆形,同时在圆形图边缘部分描出一定宽度的圆形边框,在圆形边框外在描绘出一圈边线,边线与边框之间还要求透明,这种需求,可能要重写ImageView来实现了。
把这个需求分解:
1,首先把常规图片处理成圆形图简单,直接RoundedBitmapDrawable完成。
2,圆形图外部边缘的圆形边框,则需要重写ImageView,在onDraw里面画圆,画一定宽度的圆,但是这一步在计算圆半径时候容易出问题,因为使用getWidth或getHeight这样的方法获得长度除以2算半径时候,整数除法在计算时候要取整,导致圆半径有一定偏差,进而导致画圆的半径不是刚好与圆形图的外部边缘紧密咬合在一起。故需要引入一个平衡因子消除误差。
3,画最外层的圆形边线不用考虑那么复杂,和最内层的圆形边框在半径上拉开一定间距即可。


处理常规图片为圆角的关键代码:

ImageView imageView= (ImageView) findViewById(R.id.imageView);

        RoundedBitmapDrawable circleDrawable = RoundedBitmapDrawableFactory.create(getResources(), BitmapFactory.decodeResource(getResources(), R.drawable.art));
        circleDrawable.getPaint().setAntiAlias(true);
        circleDrawable.setCircular(true);

        imageView.setImageDrawable(circleDrawable);


重写ImageView描绘内层的圆形边框以及最外层的圆形边线:

package cn.migu.musicplayer.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.ImageView;

/**
 * Created by Phil on 2016/7/15.
 */
public class ImageViewWithStroke extends ImageView {

    //外圈白线和内圈黑线边框之间的间隔。
    private int gap = 25;

    //平衡在计算半径时候因为除以2导致半径计算的误差
    private int balance_factor = 2;

    public ImageViewWithStroke(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public ImageViewWithStroke(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ImageViewWithStroke(Context context) {
        super(context);
    }

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

        drawInnerBlackCircle(canvas, 4);
        drawOutWhiteCircle(canvas, 1);
    }


    //画最外层的白色边线
    private void drawOutWhiteCircle(Canvas canvas, int strokeWidth) {
        Paint paint = new Paint();
        paint.setColor(Color.WHITE);
        paint.setStrokeWidth(strokeWidth);
        paint.setStyle(Paint.Style.STROKE);
        paint.setAntiAlias(true);

        int w = this.getPaddingLeft() + this.getPaddingRight();
        int x = getWidth() - w;
        int r = x / 2;

        canvas.drawCircle(getWidth() / 2, getHeight() / 2, r + strokeWidth + gap, paint);
    }

    //画最内层的黑色边框
    private void drawInnerBlackCircle(Canvas canvas, int strokeWidth) {
        Paint paint = new Paint();
        paint.setColor(Color.BLACK);
        paint.setStrokeWidth(strokeWidth);
        paint.setStyle(Paint.Style.STROKE);
        paint.setAntiAlias(true);

        int w = this.getPaddingLeft() + this.getPaddingRight();
        float x = getWidth() - w;
        float r = x / 2;

        //半径减去平衡因子是因为在取整时候四舍五入
        canvas.drawCircle(getWidth() / 2, getHeight() / 2, (r - balance_factor) + strokeWidth, paint);
    }
}



需要处理和加载的目标图片art.jpg:



代码运行结果:


背景的绿色图是在ImageView的background加载一张Android自带的小机器人图。


附录:
1,《Android圆形头像图Circle ImageView》链接地址:http://blog.csdn.net/zhangphil/article/details/44960551 
2,《Android CustomShapeImageView对图片进行各种样式裁剪:圆形、星形、心形、花瓣形等》链接地址:http://blog.csdn.net/zhangphil/article/details/50119921

相关文章
|
2月前
|
XML 前端开发 Android开发
Android:UI:Drawable:View/ImageView与Drawable
通过本文的介绍,我们详细探讨了Android中Drawable、View和ImageView的使用方法及其相互关系。Drawable作为图像和图形的抽象表示,提供了丰富的子类和自定义能力,使得开发者能够灵活地实现各种UI效果。View和ImageView则通过使用Drawable实现了各种图像和图形的显示需求。希望本文能为您在Android开发中使用Drawable提供有价值的参考和指导。
49 2
|
6月前
|
Java Android开发
Android面试题经典之Glide取消加载以及线程池优化
Glide通过生命周期管理在`onStop`时暂停请求,`onDestroy`时取消请求,减少资源浪费。在`EngineJob`和`DecodeJob`中使用`cancel`方法标记任务并中断数据获取。当网络请求被取消时,`HttpUrlFetcher`的`cancel`方法设置标志,之后的数据获取会返回`null`,中断加载流程。Glide还使用定制的线程池,如AnimationExecutor、diskCacheExecutor、sourceExecutor和newUnlimitedSourceExecutor,其中某些禁止网络访问,并根据CPU核心数动态调整线程数。
178 2
|
3月前
|
Android开发 UED
Android 中加载 Gif 动画
【10月更文挑战第20天】加载 Gif 动画是 Android 开发中的一项重要技能。通过使用第三方库或自定义实现,可以方便地在应用中展示生动的 Gif 动画。在实际应用中,需要根据具体情况进行合理选择和优化,以确保用户体验和性能的平衡。可以通过不断的实践和探索,进一步掌握在 Android 中加载 Gif 动画的技巧和方法,为开发高质量的 Android 应用提供支持。
|
4月前
|
存储 缓存 编解码
Android经典面试题之图片Bitmap怎么做优化
本文介绍了图片相关的内存优化方法,包括分辨率适配、图片压缩与缓存。文中详细讲解了如何根据不同分辨率放置图片资源,避免图片拉伸变形;并通过示例代码展示了使用`BitmapFactory.Options`进行图片压缩的具体步骤。此外,还介绍了Glide等第三方库如何利用LRU算法实现高效图片缓存。
83 20
Android经典面试题之图片Bitmap怎么做优化
|
5月前
|
数据处理 开发工具 数据安全/隐私保护
Android平台RTMP推送|轻量级RTSP服务|GB28181接入之文字、png图片水印的精进之路
本文探讨了Android平台上推流模块中添加文字与PNG水印的技术演进。自2015年起,为了满足应急指挥及安防领域的需求,逐步发展出三代水印技术:第一代为静态文字与图像水印;第二代实现了动态更新水印内容的能力,例如实时位置与时间信息;至第三代,则优化了数据传输效率,直接使用Bitmap对象传递水印数据至JNI层,减少了内存拷贝次数。这些迭代不仅提升了用户体验和技术效率,也体现了开发者追求极致与不断创新的精神。
|
5月前
|
自然语言处理 定位技术 API
Android经典实战之如何获取图片的经纬度以及如何根据经纬度获取对应的地点名称
本文介绍如何在Android中从图片提取地理位置信息并转换为地址。首先利用`ExifInterface`获取图片内的经纬度,然后通过`Geocoder`将经纬度转为地址。注意操作需在子线程进行且考虑多语言支持。
300 4
|
5月前
|
存储 缓存 Java
Android项目架构设计问题之优化业务接口数据的加载效率如何解决
Android项目架构设计问题之优化业务接口数据的加载效率如何解决
61 0
|
5月前
|
Java Android开发 Kotlin
Android项目架构设计问题之要在Glide库中加载网络图片到ImageView如何解决
Android项目架构设计问题之要在Glide库中加载网络图片到ImageView如何解决
46 0
|
5月前
|
XML 前端开发 Android开发
Android经典实战之Kotlin中实现圆角图片和圆形图片
本文介绍两种实现圆角图像视图的方法。第一种是通过自定义Kotlin `AppCompatImageView`,重写`onDraw`方法使用`Canvas`和`Path`进行圆角剪裁。第二种利用Android Material库中的`ShapeableImageView`,简单配置即可实现圆角效果。两种方法均易于实现且提供动态调整圆角半径的功能。
104 0
|
Android开发
Android圆形扩展动画
今天学习了一个实现圆形扩展Activity切换动画效果 工具类代码 public class CircularAnimUtil { public static final long PERFECT_MILLS = 618; public static final int MINI_RADIUS = 0; /** * 向四周伸张,直到完成显示。
1469 0