首页 文章详情

Material Components——ShapeableImageView

Android群英传 | 495 2020-10-26 09:19 0 0 0
UniSMS (合一短信)

书接前文,我们讲了在MD Component中的MaterialShapeDrawable,今天则继续讲解在此基础上,MDC封装的一个Image组件——ShapeableImageView。它的作用就是让开发者方便的对Imageview加载的图像进行Shape的处理。

老规矩,官网文档镇楼。

https://developer.android.com/reference/com/google/android/material/imageview/ShapeableImageView

使用

ShapeableImageView的使用非常简单,与传统的Imageview类似,当然前提是需要引入MD Library。

implementation 'com.google.android.material:material:<version>'

首先,需要在xml中引入ShapeableImageView,并指定shapeAppearanceOverlay,代码如下所示。

<com.google.android.material.imageview.ShapeableImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@drawable/test"
    app:shapeAppearanceOverlay="@style/ShapeAppearance.circle"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

这个指定的shapeAppearanceOverlay,就是具体的Shape的处理,它是一个Style,下面通过几个例子来演示下如何创建这个Style。

Round Cut

在style中的内容即为需要处理的效果,这里指定了Corner的处理效果类型为rounded,同时指定了Corner大小为Image的10%(当然你也可以指定其它单位)。

<style name="ShapeAppearance.circle" parent="">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSize">10%</item>
</style>

展示效果如图所示,即最简单的圆角图像。

773b7d33e2b0f0895ebbb9ddefdb17a1.webp

cornerSize可以设置多种不同的数值,比如百分百,dp等等。例如50%,即为圆形。

另外,在代码中可以这样设置。

val model = ShapeAppearanceModel.builder().setAllCornerSizes(ShapeAppearanceModel.PILL).build()
test.shapeAppearanceModel = model

同时,这样会覆盖xml中的shapeAppearanceOverlay。

在代码中的处理应该更为常用,而且从这里我们也可以发现,ShapeableImageView实际上就是采用的ShapeAppearanceModel来进行Shape的处理的。

直线Cut

再看下另一种Corner处理,代码如下所示。

<style name="ShapeAppearance.cut" parent="">
    <item name="cornerFamily">cut</item>
    <item name="cornerSize">10%</item>
</style>

即对Corner进行直角裁剪,效果如图所示。

c5a6eb9e205e2b845393020b1797482c.webp

例如设置50%,即为裁剪成菱形。

混合

多种效果,在Style中可以和具体指定的Corner混合作用,产生不同的效果,代码如下所示。

<style name="ShapeAppearance.mix" parent="">
    <item name="cornerFamilyTopLeft">rounded</item>
    <item name="cornerFamilyBottomRight">cut</item>
    <item name="cornerSizeTopLeft">24%</item>
    <item name="cornerSizeBottomRight">36%</item>
</style>

效果如图所示。

d15781cb4bd77ead8f307f35fd5b34cb.webp

描边

除了对Corner的处理之外,ShapeableImageView同样可以对边界进行描边处理,在ShapeableImageView中指定strokeWidth和strokeColor即可,代码如下所示。

<com.google.android.material.imageview.ShapeableImageView
    android:id="@+id/test"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:strokeColor="@color/colorAccent"
    app:strokeWidth="4dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:srcCompat="@drawable/test" />

效果如图所示。

d9d329301e49a324ab00b744be795582.webp

同时,描边是可以和裁剪结合起来用的,代码如下所示。

<com.google.android.material.imageview.ShapeableImageView
    android:id="@+id/test"
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:padding="4dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:shapeAppearanceOverlay="@style/ShapeAppearance.circle"
    app:srcCompat="@drawable/test"
    app:strokeColor="@color/colorAccent"
    app:strokeWidth="4dp" />

效果如图所示。

f68b54eb1917cb99e16083e6e78acf3a.webp

关于描边宽度需要注意的是,和自定义View一样,描边的宽度是中心点在Layout边界,所以是Layout边界内外均分strokeWidth的,所以描边是可能超出Layout边界的,造成截断的效果,所以可以设置内padding来处理溢出。

ShapeableImageView裁剪的原理

ShapeableImageView的源码并不复杂,核心代码如下。

b6fe99cd0cf3c49e7c8dd88cdbf10200.webp

实际上,就是在5.0之上,使用ViewOutlineProvider来对Image进行裁剪。

ViewOutlineProvider

ViewOutlineProvider是Android在5.0之后提出的对Shape处理的标准API,其效率会比传统的通过Xfermode进行裁剪的方式高很多,代码如下所示。

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        test.outlineProvider = object : ViewOutlineProvider() {
            override fun getOutline(view: View, outline: Outline) {
//                outline.setRoundRect(0, 0, view.width, view.height, 32f)
//                outline.setOval(0, 0, view.width, view.height)
            }
        }
        test.clipToOutline = true
    }
}

其中的两行注释代码,分别用于绘制圆角矩形和圆形,效果如下所示。

293140df8e479341171f6734840a2fcf.webp05ca3cdb1df1d4d4cca4d3f424cbd0d7.webp

除了这种最简单的处理外,ViewOutlineProvider还支持外凸多边形的设置,代码如下所示。

val path = Path()
view.elevation = 4f
path.moveTo(-20f, -20f)
path.lineTo(-20f, view.height.toFloat() + 20)
path.lineTo(view.width.toFloat() + 20, view.height.toFloat() + 20)
path.lineTo(view.width.toFloat() + 20, -20f)
path.close()
outline.setConvexPath(path)

可以用于绘制外边框、气泡边角和elevation阴影等效果。

138121b30da2cb645c8fea1bbd17fcb9.webp

修仙

对于Android和Flutter相关技术感兴趣的朋友,可以添加我的微信,拉你进Flutter修仙群和Android开发群,微信号 Tomcat_xu。

这是我的网站 https://xuyisheng.top 这里有Flutter、Android、Kotlin的优质内容,欢迎大家访问。点击原文,一键直达。

good-icon 0
favorite-icon 0
收藏
回复数量: 0
    暂无评论~~
    Ctrl+Enter