Android基于Fresco实现圆角和圆形图片
YX_BB 人气:0Fresco是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通常会给我们这样一张图作为默认图片
理论上来讲,只需要加入下列这行代码,就可以完成这部分工作了
app:placeholderImage="@drawable/ic_avatar_default"
然而圆形图片本身已经是圆形的了,在有些机型上就出现了这个样式。
搜索了一波,自带的属性都不能解决这个问题,干脆自己来定义这个圆形的实现吧,同时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>
加载全部内容