Material Design 系列
博客创建时间:2022.08.23
博客更新时间:2023.05.07
以Android studio build=7.0.0,SDKVersion 31来分析讲解。如图文和网上其他资料不一致,可能是别的资料版本较低而已。
前言
继承自ImageView,可以为image添加描边大小、颜色,以及圆角、裁切等,这得益于它新增了一个属性shapeAppearance,具体实现在ShapeAppearanceModel,可以通过style来配置,也可以通过代码实现。
属性&方法
首先可以看出它是继承于AppCompatImageView的,它的特性设置一般保存在ShapeAppearanceModel中。实际它的属性值都是保存在ShapeAppearanceModel中的。
属性 | 说明 | 参数及含义 |
---|---|---|
shapeAppearance | ShapeableImageView的形状外观样式 | |
shapeAppearanceOverlay | ShapeableImageView的形状外观叠加样式 | |
strokeColor | 描边颜色 | |
strokeWidth | 描边宽度 | |
cornerFamily | 四个角shape属性/样式 | -rounded: 圆角0、-cut: 切角1 |
cornerSize | 四个角弧度 | 可以是具体DP,也可以是%,以控件高为准 |
cornerFamilyTopLeft | 左上shape属性/样式 | -rounded: 圆角0、-cut: 切角1 |
cornerFamilyTopRight | 右上shape属性/样式 | -rounded: 圆角0、-cut: 切角1 |
cornerFamilyBottomRight | 右下shape属性/样式 | -rounded: 圆角0、-cut: 切角1 |
cornerFamilyBottomLeft | 左下shape属性/样式 | -rounded: 圆角0、-cut: 切角1 |
cornerSizeTopLeft | 左上弧度 | |
cornerSizeTopRight | 右上弧度 | |
cornerSizeBottomRight | 右下弧度 | |
cornerSizeBottomLeft | 左下弧度 |
样式控制
ShapeableImageView 的样式只要由shapeAppearanceOverlay或shapeAppearance控制。
ShapeableImageView本质是通过ViewOutlineProvider实现剪裁的。ViewOutlineProvider的效率比传统的Xfermode进行剪裁的方式高很多。
<!-- 圆角图片 -->
<!-- shapeAppearanceOverlay或shapeAppearance 加载style -->
<!-- strokeColo描边颜色 -->
<!-- strokeWidth描边宽度 -->
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/image1"
android:layout_width="100dp"
android:layout_height="100dp"
android:padding="1dp"
android:src="@mipmap/home3"
app:shapeAppearanceOverlay="@style/roundedCornerImageStyle"
app:strokeColor="#F44336"
app:strokeWidth="2dp" />
1. 圆形图
<!-- 圆形图片 -->
<style name="circleImageStyle">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">50%</item>
</style>
2、 菱形
<!-- 菱形图片 -->
<style name="diamondImageStyle">
<item name="cornerFamily">cut</item>
<item name="cornerSize">50%</item>
</style>
3. 水滴形
<!-- 水滴 -->
<style name="waterImageStyle">
<item name="cornerFamilyBottomLeft">rounded</item>
<item name="cornerFamilyBottomRight">rounded</item>
<item name="cornerFamilyTopLeft">rounded</item>
<item name="cornerFamilyTopRight">rounded</item>
<item name="cornerSizeBottomLeft">25dp</item>
<item name="cornerSizeBottomRight">25dp</item>
<item name="cornerSizeTopLeft">70%</item>
<item name="cornerSizeTopRight">70%</item>
</style>
4. 火箭头
<!-- 火箭头图片 -->
<style name="rocketImageStyle">
<item name="cornerFamilyTopLeft">rounded</item>
<item name="cornerFamilyTopRight">rounded</item>
<item name="cornerSizeTopLeft">70%</item>
<item name="cornerSizeTopRight">70%</item>
</style>
5. 叶子形
<!-- 叶子图片 -->
<style name="leafImageStyle">
<item name="cornerFamilyTopLeft">rounded</item>
<item name="cornerFamilyBottomRight">rounded</item>
<item name="cornerSizeTopLeft">70%</item>
<item name="cornerSizeBottomRight">70%</item>
</style>
6. 八角形
<!-- 切角图片 -->
<style name="cutImageStyle">
<item name="cornerFamily">cut</item>
<item name="cornerSize">28%</item>
</style>
7. 圆角
<!-- 圆角图片 -->
<style name="roundedCornerImageStyle">
<item name="cornerFamily">rounded</item>
<!-- 可以是具体的Dp-->
<item name="cornerSize">25dp</item>
<!-- 也可以是%,以高为基准-->
<!-- <item name="cornerSize">15%</item>-->
</style>
8. tip形
<!-- tip图片 -->
<style name="tipImageStyle">
<item name="cornerFamilyTopLeft">rounded</item>
<item name="cornerSizeTopLeft">50%</item>
<item name="cornerFamilyBottomLeft">rounded</item>
<item name="cornerSizeBottomLeft">50%</item>
<item name="cornerFamilyTopRight">cut</item>
<item name="cornerSizeTopRight">50%</item>
<item name="cornerFamilyBottomRight">cut</item>
<item name="cornerSizeBottomRight">50%</item>
</style>
<!--ShapeableImageView 半圆 -->
<style name="SemicircleStyle">
<item name="cornerFamily">rounded</item>
<item name="cornerSizeTopLeft">50%</item>
<item name="cornerSizeTopRight">50%</item>
</style>
<!--ShapeableImageView 六边形 -->
<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>
9.代码控制
mBinding.roundedImage.shapeAppearanceModel = ShapeAppearanceModel.builder()
.setAllCorners(CornerFamily.ROUNDED, 60f)// 设置圆角
.build()
mBinding.cutImage.shapeAppearanceModel = ShapeAppearanceModel.builder()
.setTopLeftCorner(CornerFamily.CUT, RelativeCornerSize(0.4f))//设置指定方向圆角
.setTopRightCorner(CornerFamily.CUT, RelativeCornerSize(0.4f))//设置指定方向圆角
.setBottomRightCorner(CornerFamily.CUT, RelativeCornerSize(0.3f))//设置指定方向圆角
.setBottomLeftCorner(CornerFamily.CUT, RelativeCornerSize(0.3f))//设置指定方向圆角
.build()
mBinding.randomImage.shapeAppearanceModel = ShapeAppearanceModel.builder()
.setAllCornerSizes(ShapeAppearanceModel.PILL)
.setTopLeftCornerSize(100f)//设置指定方向圆角大小
.setTopRightCornerSize(RelativeCornerSize(0.5f))//设置指定方向圆角大小
.setBottomLeftCornerSize(20f)//设置指定方向圆角大小
.setBottomRightCornerSize(AbsoluteCornerSize(50f))//设置指定方向圆角大小
.build()
//绘制圆角
mBinding.roundedImage1.apply {
outlineProvider = object : ViewOutlineProvider() {
override fun getOutline(view: View, outline: Outline) {
outline.setRoundRect(0, 0, view.width, view.height, 80f)
}
}
clipToOutline = true
}
//绘制圆形
mBinding.cutImage2.apply {
outlineProvider = object : ViewOutlineProvider() {
override fun getOutline(view: View, outline: Outline) {
outline.setOval(0, 0, view.width, view.width)
}
}
clipToOutline = true
}
mBinding.randomImage2.apply {
outlineProvider = object : ViewOutlineProvider() {
override fun getOutline(view: View, outline: Outline) {
view.elevation = 10F
val gap = 20F
val path = Path()
path.moveTo(-gap, -gap)
path.lineTo(-gap, view.measuredHeight.toFloat() + gap) //左下点
path.lineTo(
(view.measuredWidth / 2).toFloat(),
(view.measuredHeight + 50).toFloat()
)
path.lineTo(
view.measuredWidth.toFloat() + gap,
view.measuredHeight.toFloat() + gap
)
path.lineTo(view.measuredWidth.toFloat() + gap, -gap) //右上点
path.close()
outline.setConvexPath(path)
view.scaleX = 0.5F
view.scaleY = 0.5F
}
}
}
关于Stroke
ShapeableImageView指定strokeWidth描边的时候,其描边会被覆盖掉一半,如strokeWidth=4dp,上下左右会被覆盖,实际的效果是只有2dp被显示。
ShapeableImageView指定strokeWidth描边的时候,没有设置padding,那笔画可能一半看不见,需要设置padding, 设置描边的时候,需要添加padding属性,padding的值为strokeWidth的一半。
总结
有兴趣可以查看源码源码Demo:https://gitee.com/luofaxin/CodeAanalysis.git
相关链接:
扩展链接:
博客书写不易,您的点赞收藏是我前进的动力,千万别忘记点赞、 收藏 ^ _ ^ !