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 相关文章推荐
Java新手教程之ArrayList的基本使用
Jun 20 Java/Android
解决SpringCloud Feign传对象参数调用失败的问题
Jun 23 Java/Android
Spring整合Mybatis的全过程
Jun 28 Java/Android
logback 实现给变量指定默认值
Aug 30 Java/Android
springboot如何接收application/x-www-form-urlencoded类型的请求
Nov 02 Java/Android
解析mybatis-plus中的resultMap简单使用
Nov 23 Java/Android
Android基于Fresco实现圆角和圆形图片
Apr 01 Java/Android
详解Flutter和Dart取消Future的三种方法
Apr 07 Java/Android
Java 数组的使用
May 11 Java/Android
springboot集成redis存对象乱码的问题及解决
Jun 16 Java/Android
SpringBoot项目多数据源及mybatis 驼峰失效的问题解决方法
Jul 07 Java/Android
Spring Boot优化后启动速度快到飞起技巧示例
Jul 23 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
一个图形显示IP的PHP程序代码
2007/10/19 PHP
PHP实现多图片上传类实例
2014/07/26 PHP
PHP人民币金额转大写实例代码
2015/10/02 PHP
封装好的省市地区联动控件附下载
2007/08/13 Javascript
js为鼠标添加右击事件防止默认的右击菜单弹出
2013/07/29 Javascript
各浏览器对document.getElementById等方法的实现差异解析
2013/12/05 Javascript
JavaScript 常见安全漏洞和自动化检测技术
2015/08/21 Javascript
全系IE支持Bootstrap的解决方法
2015/10/19 Javascript
前端js文件合并的三种方式推荐
2016/05/19 Javascript
怎样判断jQuery当前元素是隐藏还是显示
2016/11/23 Javascript
分分钟玩转Vue.js组件(二)
2017/03/01 Javascript
Web开发中客户端的跳转与服务器端的跳转的区别
2017/03/05 Javascript
Angular.js组件之input mask对input输入进行格式化详解
2017/07/10 Javascript
bootstrap下拉框动态赋值方法
2018/08/10 Javascript
Vue作用域插槽slot-scope实例代码
2018/09/05 Javascript
vue实现的下拉框功能示例
2019/01/29 Javascript
vue2.0自定义指令示例代码详解
2019/04/25 Javascript
微信小程序自定义可滑动顶部TabBar选项卡实现页面切换功能示例
2019/05/14 Javascript
python实现class对象转换成json/字典的方法
2016/03/11 Python
利用ctypes提高Python的执行速度
2016/09/09 Python
Python 3.x 判断 dict 是否包含某键值的实例讲解
2018/07/06 Python
Python快速转换numpy数组中Nan和Inf的方法实例说明
2019/02/21 Python
django 微信网页授权认证api的步骤详解
2019/07/30 Python
python获取天气接口给指定微信好友发天气预报
2020/12/28 Python
HTML5 canvas基本绘图之图形变换
2016/06/27 HTML / CSS
中国专业的音频分享平台:喜马拉雅
2019/05/24 全球购物
MATCHESFASHION澳大利亚/亚太地区:英国时尚奢侈品电商
2020/01/14 全球购物
为什么group by 和order by会使查询变慢
2014/05/16 面试题
管理科学大学生求职信
2013/11/13 职场文书
大学生村官任职感言
2014/01/09 职场文书
财务主管自我鉴定
2014/01/17 职场文书
《谁的本领大》教后反思
2014/04/25 职场文书
党的群众路线教育实践活动制度建设计划
2014/11/03 职场文书
四大名著读书笔记
2015/06/25 职场文书
2016年大学生实习单位评语
2015/12/01 职场文书
2016见义勇为事迹材料汇总
2016/03/01 职场文书