Android 剪辑到背景

Posted

技术标签:

【中文标题】Android 剪辑到背景【英文标题】:Android clip to background 【发布时间】:2019-03-08 09:27:20 【问题描述】:

我有以下可绘制的squared_card_background.xml,我希望将其用作不同视图的背景,并让视图子项以及视图本身在之后被剪辑。

squared_card_background_left.xml

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:
    android:
    android:viewportHeight="1"
    android:viewportWidth="1">
    <path
        android:name="left"
        android:fillColor="@color/colorSurface"
        android:pathData="M0,1 L1,0 L1,1z" />
    <clip-path android:name="leftClip"
        android:pathData="M0,1 L1,0 L1,1z"/>
</vector>

squared_card_background_right.xml

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:
    android:
    android:viewportHeight="1"
    android:viewportWidth="1" >
    <path
        android:name="v"
        android:fillColor="@color/colorSurface"
        android:pathData="M1,1 L0,0 L0,1z" />
</vector>

squared_card_background.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:gravity="fill|top|clip_horizontal|clip_vertical"
        android:start="16dp"
        android:end="16dp"
        android:>
        <shape android:shape="rectangle"
            android:useLevel="false">
            <solid android:color="@color/colorSurface"/>
        </shape>
    </item>
    <item android:drawable="@drawable/squared_card_background_left"
        android:gravity="start|top|clip_horizontal|clip_vertical"
        android:
        android:>
    </item>
    <item android:drawable="@drawable/squared_card_background_right"
        android:gravity="end|top|clip_horizontal|clip_vertical"
        android:
        android:>
    </item>
    <item android:top="16dp">
        <color android:color="@color/colorSurface"/>
        <scale android:scaleGravity="fill"/>
    </item>
</layer-list>

我尝试将视图设置为剪切子项和轮廓背景,但它似乎无法识别正确的剪切路径,有什么想法吗?

我当前尝试设置视图背景的布局。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_
    android:layout_
    android:background="@color/colorBackground"
    android:orientation="vertical">

    <com.mobile.indico.indicomobile.views.Toolbar
        android:id="@+id/sync_toolbar"
        android:layout_
        android:layout_
        app:toolbarTitle="@string/title_sync"
        app:showNavigationIcon="false"
        app:layout_constraintTop_toTopOf="parent">
        <ImageButton
            android:id="@+id/sync_start"
            android:layout_
            android:layout_
            android:layout_alignParentStart="true"
            android:layout_alignParentTop="true"
            android:background="@drawable/preview_button_background"
            android:tint="@color/colorOnPrimary"
            android:src="@drawable/ic_refresh_white"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"/>
    </com.mobile.indico.indicomobile.views.Toolbar>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/sync_recycler"
        android:layout_
        android:layout_
        app:layout_constraintTop_toBottomOf="@id/sync_toolbar"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:background="@drawable/squared_card_background"
        android:clipChildren="true"/>
</android.support.constraint.ConstraintLayout>

最后,我尝试创建一个父 FrameLayout 将单个子剪辑剪辑到背景,但结果相同,我不知道如何从可绘制对象创建剪辑路径并插入到 onDraw 方法中。

【问题讨论】:

【参考方案1】:

最终使用了这个......感谢我猜的反对

override fun onDraw(canvas: Canvas?) = super.onDraw(canvas?.also 
        it.clipPath(Path().apply
            moveTo(0f, height.toFloat())
            lineTo(0f, _cornerRadius)
            lineTo(_cornerRadius, 0f)
            lineTo(width - _cornerRadius, 0f)
            lineTo(width.toFloat(), _cornerRadius)
            lineTo(width.toFloat(), height.toFloat())
            lineTo(0f, height.toFloat())
            close()
        )
    )

【讨论】:

请注意,每次调用 onDraw 时都会创建一个新的 Path 对象,这对性能非常不利,因为会创建大量对象,而这些对象又需要被垃圾回收。

以上是关于Android 剪辑到背景的主要内容,如果未能解决你的问题,请参考以下文章

Android:将图像剪辑到形状

Android 视图剪辑

Android背景图像大于容器

Android逆剪辑

剪辑按钮不接收触摸输入

如何在android中剪辑圆圈