Android基于Fresco实现圆角和圆形图片


Posted in Java/Android onApril 01, 2022

Fresco是FaceBook开源的Android平台图片加载库,可以从网络,从本地文件系统,本地资源加载图片

Fresco本身已经实现了圆角以及圆形图片的功能。

<!--圆形图片,一般用作头像-->
<com.facebook.drawee.view.SimpleDraweeView
    android:id="@+id/iv_avatar"
    android:layout_width="40dp"
    android:layout_height="40dp"
    app:placeholderImage="@drawable/ic_avatar_default"
    app:roundAsCircle="true"/>
<!--圆角图片,为了美观大多数图片都会有这样的处理。-->
<!--当图片为正方形的时候,将roundedCornerRadius设置为边长的一半,也可以形成圆形图片的效果-->
<com.facebook.drawee.view.SimpleDraweeView
    android:id="@+id/iv_avatar"
    android:layout_width="40dp"
    android:layout_height="40dp"
    app:placeholderImage="@drawable/ic_avatar_default"
    app:roundedCornerRadius="5dp"/>

工作中,遇到圆形头像的时候,UI通常会给我们这样一张图作为默认图片

Android基于Fresco实现圆角和圆形图片

理论上来讲,只需要加入下列这行代码,就可以完成这部分工作了

app:placeholderImage="@drawable/ic_avatar_default"

然而圆形图片本身已经是圆形的了,在有些机型上就出现了这个样式。

Android基于Fresco实现圆角和圆形图片

搜索了一波,自带的属性都不能解决这个问题,干脆自己来定义这个圆形的实现吧,同时Fresco自带的圆角效果只能保证使用统一的半径,想要让四个圆角的半径不同,只能在java文件中设置,不够灵活,定义圆角半径的属性也需要做些变更。

思路:自定义RoundImageView继承自 SimpleDraweeVie,具备其所有的功能。
Canvas的clipPath(Path path)可以根据Path,将Canvas剪裁成我们想要的图形。

public class RoundImageView extends SimpleDraweeView {
    
    private final static int DEFAULT_VALUE = 0;

    private float mWidth;
    private float mHeight;
    private Path mPath;

    // 圆角角度
    private float mCornerRadius;
    // 左上角圆角角度
    private float mLeftTopRadius;
    // 右上角圆角角度
    private float mRightTopRadius;
    // 右下角圆角角度
    private float mRightBottomRadius;
    // 左下角圆角角度
    private float mLeftBottomRadius;

    // 是否使用圆形图片
    private boolean mAsCircle;
    // 圆形图片半径
    private float mRadius;
    
    public RoundImageView(Context context) {
        this(context, null);
    }

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

    public RoundImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initData();
        initAttrs(context, attrs);
    }
    
    private void initData() {
        mPath = new Path();
    }

    private void initAttrs(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundImageView);
        mCornerRadius = typedArray.getDimension(R.styleable.RoundImageView_cornerRadius, DEFAULT_VALUE);
        mAsCircle = typedArray.getBoolean(R.styleable.RoundImageView_asCircle, false);
        if (mCornerRadius <= 0) {
            // 说明用户没有设置四个圆角的有效值,此时四个圆角各自使用自己的值
            mLeftTopRadius = typedArray.getDimension(R.styleable.RoundImageView_leftTopRadius, DEFAULT_VALUE);
            mRightTopRadius = typedArray.getDimension(R.styleable.RoundImageView_rightTopRadius, DEFAULT_VALUE);
            mRightBottomRadius = typedArray.getDimension(R.styleable.RoundImageView_rightBottomRadius, DEFAULT_VALUE);
            mLeftBottomRadius = typedArray.getDimension(R.styleable.RoundImageView_leftBottomRadius, DEFAULT_VALUE);
        } else {
            // 使用了统一的圆角,因此使用mCornerRadius统一的值
            mLeftTopRadius = mCornerRadius;
            mRightTopRadius = mCornerRadius;
            mRightBottomRadius = mCornerRadius;
            mLeftBottomRadius = mCornerRadius;
        }
        
        typedArray.recycle();
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        mWidth = getWidth();
        mHeight = getHeight();
        // 如果开启了圆形标记
        if (mAsCircle) {
            mRadius = Math.min(mWidth / 2, mHeight / 2);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // 如果开启了圆形标记,圆形图片的优先级高于圆角图片
        if(mAsCircle) {
            drawCircleImage(canvas);
        } else {
            drawCornerImage(canvas);
        }
        super.onDraw(canvas);
    }

    /**
     * 画中间圆形
     * @param canvas
     */
    private void drawCircleImage(Canvas canvas) {
        mPath.addCircle(mWidth / 2, mHeight / 2, mRadius, Path.Direction.CW);
        canvas.clipPath(mPath);
    }

    /**
     * 画圆角
     * @param canvas
     */
    private void drawCornerImage(Canvas canvas) {
        if (mWidth > mCornerRadius && mHeight > mCornerRadius) {
            // 设置四个角的x,y半径值
            float[] radius = {mLeftTopRadius, mLeftTopRadius, mRightTopRadius, mRightTopRadius, mRightBottomRadius, mRightBottomRadius, mLeftBottomRadius, mLeftBottomRadius};
            mPath.addRoundRect(new RectF(0,0, mWidth, mHeight), radius, Path.Direction.CW);
            canvas.clipPath(mPath);
        }
    }
}

attr属性如下

<!--适配android10的图片控件-->
    <declare-styleable name="RoundImageView">
        <!--圆形图片-->
        <attr name="asCircle" format="boolean"/>
        <!--左上角圆角半径-->
        <attr name="leftTopRadius" format="dimension"/>
        <!--右上角圆角半径-->
        <attr name="rightTopRadius" format="dimension"/>
        <!--右下角圆角半径-->
        <attr name="rightBottomRadius" format="dimension"/>
        <!--左下角圆角半径-->
        <attr name="leftBottomRadius" format="dimension"/>
        <!--四个圆角半径,会覆盖上边四个圆角值-->
        <attr name="cornerRadius" format="dimension"/>
</declare-styleable>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Java/Android 相关文章推荐
springboot如何初始化执行sql语句
Jun 22 Java/Android
Java多条件判断场景中规则执行器的设计
Jun 26 Java/Android
Java 数组内置函数toArray详解
Jun 28 Java/Android
springboot项目以jar包运行的操作方法
Jun 30 Java/Android
Java基础-封装和继承
Jul 02 Java/Android
使用@Value值注入及配置文件组件扫描
Jul 09 Java/Android
关于springboot配置druid数据源不生效问题(踩坑记)
Sep 25 Java/Android
剑指Offer之Java算法习题精讲二叉树的构造和遍历
Mar 21 Java/Android
SpringBoot2零基础到精通之数据库专项精讲
Mar 22 Java/Android
Android开发手册Chip监听及ChipGroup监听
Jun 10 Java/Android
详解Spring Bean的配置方式与实例化
Jun 10 Java/Android
SpringBoot项目部署到阿里云服务器的实现步骤
Jun 28 Java/Android
Android自定义scrollview实现回弹效果
Apr 01 #Java/Android
Android自定义ScrollView实现阻尼回弹
Java实战之课程信息管理系统的实现
Android超详细讲解组件ScrollView的使用
Spring Boot DevTools 全局配置学习指南
Spring事务管理下synchronized锁失效问题的解决方法
Mar 31 #Java/Android
Spring依赖注入多种类型数据的示例代码
Mar 31 #Java/Android
You might like
PHP连接access数据库
2008/03/27 PHP
php 带逗号千位符数字的处理方法
2012/01/10 PHP
php实现汉字验证码和算式验证码的方法
2015/03/07 PHP
PHP递归实现文件夹的复制、删除、查看大小操作示例
2017/08/11 PHP
Laravel项目中timeAgo字段语言转换的改善方法示例
2019/09/16 PHP
JavaScript高级程序设计
2006/12/29 Javascript
用tip解决Ext列宽度不够的问题
2008/12/13 Javascript
jQuery 源码分析笔记(7) Queue
2011/06/19 Javascript
iframe 异步加载技术及性能分析
2011/07/19 Javascript
jquery设置元素的readonly和disabled的写法
2013/09/22 Javascript
浅析Javascript使用include/require
2013/11/13 Javascript
js+html5通过canvas指定开始和结束点绘制线条的方法
2015/06/05 Javascript
node.js微信公众平台开发教程
2016/03/04 Javascript
jQuery EasyUI框架中的Datagrid数据表格组件结构详解
2016/06/09 Javascript
JS实现仿微信支付弹窗功能
2018/06/25 Javascript
浅谈Node 异步IO和事件循环
2019/05/05 Javascript
JavaScript JSON数据处理全集(小结)
2019/08/15 Javascript
如何在JavaScript中等分数组的实现
2020/12/13 Javascript
[03:45]Newbee战队出征西雅图 决战2016国际邀请赛
2016/08/02 DOTA
[01:15:56]2018DOTA2亚洲邀请赛3月30日 小组赛A组 TNC VS Newbee
2018/03/31 DOTA
[41:17]VG vs Optic 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
python简单的函数定义和用法实例
2015/05/07 Python
解决python matplotlib imshow无法显示的问题
2018/05/24 Python
Python批处理删除和重命名文件夹的实例
2018/07/11 Python
简单了解python的break、continue、pass
2019/07/08 Python
Python模块常用四种安装方式
2020/10/20 Python
python实现发送QQ邮件(可加附件)
2020/12/23 Python
如何让IE9以下版本(ie6/7/8)认识html5元素
2013/04/01 HTML / CSS
有趣的睡衣和礼物:LazyOne
2019/11/27 全球购物
计算机专业个人求职自荐信
2013/09/21 职场文书
建筑个人求职信范文
2014/01/25 职场文书
海飞丝广告词
2014/03/20 职场文书
给校长的建议书400字
2014/05/15 职场文书
财务人员个人工作总结
2015/02/27 职场文书
高中班长竞选稿
2015/11/20 职场文书
python 单机五子棋对战游戏
2022/04/28 Python