写点什么

Android ShapeableImageView 使用详解,告别 shape、三方库 (1)

用户头像
Android架构
关注
发布于: 1 小时前

=============================================================


先来看一下ShapeableImageView是什么



由上图可以看到ShapeableImageView也没有什么神秘的,不过是ImageView的一个子类而已,但是从效果图来看,在不写shape、不引入三方库的情况下,还是挺容易实现预期效果的,而且扩展性良好。


[](


)使用


=============================================================

[](

)引入 material 包


implementation 'com.google.android.material:material:1.2.1'

[](

)常规



<com.google.android.material.imageview.ShapeableImageView


android:layout_width="wrap_content"


android:layout_height="wrap_content"


android:layout_margin="10dp"


android:src="@mipmap/ic_avatar" />


  • 和 ImageView 正常使用没有区别

[](

)圆角



<com.google.android.material.imageview.ShapeableImageView


android:layout_width="wrap_content"


android:layout_height="wrap_content"


android:layout_margin="10dp"


android:src="@mipmap/ic_avatar"


app:shapeAppearance="@style/RoundedStyle" />


<style name="RoundedStyle">


<item name="cornerFamily">rounded</item>


<item name="cornerSize">10dp</item>


</style>


  • 没有直接设置圆角的属性,需要用到app:shapeAppearance,后面会说

  • cornerFamily 角的处理方式,rounded 圆角,cut 裁剪

  • cornerSize 圆角大小

[](

)圆



<com.google.android.material.imageview.ShapeableImageView


android:layout_width="wrap_content"


android:layout_height="wrap_content"


android:layout_margin="10dp"


android:src="@mipmap/ic_avatar"


app:shapeAppearance="@style/CircleStyle" />


<style name="CircleStyle">


<item name="cornerFamily">rounded</item>


<item name="cornerSize">50%</item>


</style>


  • 圆角的大小可以用百分比,也可以自己计算,比如宽高 100dp,圆角 50dp

[](

)描边



<com.google.android.material.imageview.ShapeableImageView


android:layout_width="wrap_content"


android:layout_height="wrap_content"


android:layout_margin="10dp"


android:padding="2dp"


android:src="@mipmap/ic_avatar"


app:shapeAppearance="@style/CircleStyle"


app:strokeColor="@color/red"


app:strokeWidth="4dp" />


  • app:strokeColor 描边颜色

  • app:strokeWidth 描边宽度

  • 注意这里 padding 的数值是描边宽度的一半,后面会说

[](

)切角



<com.google.android.material.imageview.ShapeableImageView


android:layout_width="wrap_content"


android:layout_height="wrap_content"


android:layout_margin="10dp"


android:padding="2dp"


android:src="@mipmap/ic_avatar"


app:shapeAppearance="@style/CutS


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


tyle"


app:strokeColor="@color/red"


app:strokeWidth="4dp" />


<style name="CutStyle">


<item name="cornerFamily">cut</item>


<item name="cornerSize">10dp</item>


</style>


  • cornerFamily:cut 处理模式变为裁剪

[](

)菱形



<com.google.android.material.imageview.ShapeableImageView


android:layout_width="wrap_content"


android:layout_height="wrap_content"


android:layout_margin="10dp"


android:padding="2dp"


android:src="@mipmap/ic_avatar"


app:shapeAppearance="@style/RhombusStyle"


app:strokeColor="@color/red"


app:strokeWidth="4dp" />


<style name="RhombusStyle">


<item name="cornerFamily">cut</item>


<item name="cornerSize">50%</item>


</style>


  • 同样,裁剪模式下圆角大小也可以计算

[](

)叶子



<com.google.android.material.imageview.ShapeableImageView


android:layout_width="wrap_content"


android:layout_height="wrap_content"


android:layout_margin="10dp"


android:padding="2dp"


android:src="@mipmap/ic_avatar"


app:shapeAppearance="@style/LeafStyle"


app:strokeColor="@color/red"


app:strokeWidth="4dp" />


<style name="LeafStyle">


<item name="cornerFamily">rounded</item>


<item name="cornerSizeTopLeft">50%</item>


<item name="cornerSizeBottomRight">50%</item>


</style>


  • cornerSizeTopLeft 左上圆角

  • cornerSizeBottomRight 右下圆角

  • 以此类推,左上、左下、右上、右下等

[](

)半圆



<com.google.android.material.imageview.ShapeableImageView


android:layout_width="wrap_content"


android:layout_height="wrap_content"


android:layout_margin="10dp"


android:padding="2dp"


android:src="@mipmap/ic_avatar"


app:shapeAppearance="@style/SemicircleStyle"


app:strokeColor="@color/red"


app:strokeWidth="4dp" />


<style name="SemicircleStyle">


<item name="cornerFamily">rounded</item>


<item name="cornerSizeTopLeft">50%</item>


<item name="cornerSizeTopRight">50%</item>


</style>

[](

)六边形



<com.google.android.material.imageview.ShapeableImageView


android:layout_width="wrap_content"


android:layout_height="50dp"


android:layout_margin="10dp"


android:padding="2dp"


android:scaleType="centerCrop"


android:src="@mipmap/ic_avatar"


app:shapeAppearance="@style/HexagonStyle"


app:strokeColor="@color/red"


app:strokeWidth="4dp" />


<style name="HexagonStyle">


<item name="cornerFamily">cut</item>


<item name="cornerSizeTopLeft">50%</item>


<item name="cornerSizeTopRight">50%</item>


<item name="cornerSizeBottomLeft">50%</item>


<item name="cornerSizeBottomRight">50%</item>


</style>


author:[yechaoa](


)


[](


)属性


=============================================================


关于 xml 属性,我也做了一个整理,属性不多,只有 4 个


| 属性 | 描述 |


| --- | --- |


| strokeWidth | 描边宽度 |


| strokeColor | 描边颜色 |


| shapeAppearance | 外观样式 |


| shapeAppearanceOverlay | 同上,叠加层 |


[](


)扩展


=============================================================


前面为了整体的排版,埋了几个伏笔,下面来一一解答。


会涉及到源码,但是经过去繁从简,看起来也非常轻松的。

[](

)shapeAppearance


Shape appearance overlay style reference for ShapeableImageView.


ShapeableImageView 的形状外观覆盖样式参考。


前面可以看到我们设置圆角其实是用的style,那为什么不直接用attrs呢,不是更加直观方便吗,带着疑问来看看源码是怎么处理的。


直接看ShapeableImageView的次构造方法:


public class ShapeableImageView extends AppCompatImageView implements Shapeable {


...


public ShapeableImageView(Context context, @Nullable AttributeSet attrs, int defStyle) {


super(wrap(context, attrs, defStyle, DEF_STYLE_RES), attrs, defStyle);


// Ensure we are using the correctly themed context rather than the context that was passed in.


context = getContext();


clearPaint = new Paint();


clearPaint.setAntiAlias(true);


clearPaint.setColor(Color.WHITE);


clearPaint.setXfermode(new PorterDuffXfermode(Mode.DST_OUT));


destination = new RectF();


maskRect = new RectF();


maskPath = new Path();


TypedArray attributes =


context.obtainStyledAttributes(


attrs, R.styleable.ShapeableImageView, defStyle, DEF_STYLE_RES);


strokeColor =


MaterialResources.getColorStateList(


context, attributes, R.styleable.ShapeableImageView_strokeColor);


strokeWidth = attributes.getDimensionPixelSize(R.styleable.ShapeableImageView_strokeWidth, 0);


borderPaint = new Paint();


borderPaint.setStyle(Style.STROKE);


borderPaint.setAntiAlias(true);


shapeAppearanceModel =


ShapeAppearanceModel.builder(context, attrs, defStyle, DEF_STYLE_RES).build();


shadowDrawable = new MaterialShapeDrawable(shapeAppearanceModel);


if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {


setOutlineProvider(new OutlineProvider());


}


}


}


常规操作,获取自定义属性。


关键的两行代码:


shapeAppearanceModel = ShapeAppearanceModel.builder(context, attrs, defStyle, DEF_STYLE_RES).build();


shadowDrawable = new MaterialShapeDrawable(shapeAppearanceModel);


也就是说我们给shapeAppearance设置的 style,并不是ShapeableImageView自己来处理的,而是由ShapeAppearanceModel来构建的,然后又交给MaterialShapeDrawable来绘制的。

[](

)ShapeAppearanceModel


这个类就厉害了,有点像Flutter中的 Decoration,可以构建出花里胡哨的效果。


来看ShapeAppearanceModel部分源码:


public class ShapeAppearanceModel {


/** Builder to create instances of {@link ShapeAppearanceModel}s. */


public static final class Builder {


@NonNull


private CornerTreatment topLeftCorner = MaterialShapeUtils.createDefaultCornerTreatment();


@NonNull


private CornerTreatment topRightCorner = MaterialShapeUtils.createDefaultCornerTreatment();


@NonNull


private CornerTreatment bottomRightCorner = MaterialShapeUtils.createDefaultCornerTreatment();


@NonNull


private CornerTreatment bottomLeftCorner = MaterialShapeUtils.createDefaultCornerTreatment();


@NonNull private CornerSize topLeftCornerSize = new AbsoluteCornerSize(0);


@NonNull private CornerSize topRightCornerSize = new AbsoluteCornerSize(0);


@NonNull private CornerSize bottomRightCornerSize = new AbsoluteCornerSize(0);


@NonNull private CornerSize bottomLeftCornerSize = new AbsoluteCornerSize(0);

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Android ShapeableImageView使用详解,告别shape、三方库(1)