Android:如何仅修剪顶部圆角

时间:2019-05-02 19:32:46

标签: android clip

我正在创建一个内部带有FrameLayout的ScrollView。我想对其进行设计,以便在ScrollView上仅将顶角修圆。我创建了一个可绘制的形状,如下所示

<shape>
    <solid android:color="@color/white"/>
    <corners
        android:bottomLeftRadius="0dp"
        android:bottomRightRadius="0dp"
        android:topLeftRadius="16dp"
        android:topRightRadius="16dp"/>
    <padding android:padding="0dp"/>
</shape>

然后在ScrollView上设置以下内容

 scrollView.setOutlineProvider(ViewOutlineProvider.BACKGROUND);
 scrollView.setClipToOutline(true);

当我尝试滚动时,FrameLayout中的元素最终会突出到滚动视图的轮廓中

Excuse the drawing, but what i'm looking to achieve

但是,如果我改用这样的形状

<shape>
    <solid android:color="@color/white"/>
    <corners
        android:radius="16dp"/>
    <padding android:padding="0dp"/>
</shape> 

将其剪切就可以了。

所以,如果我只希望顶部弯曲,我将如何剪裁。

3 个答案:

答案 0 :(得分:4)

这是@Jankers答案的Kotlin变体,也回答@Tony的问题。说明如何只放置一个圆角或两个相邻的圆角。

  fun setCorners() {
        
        val mOutlineProvider = object : ViewOutlineProvider() {
            override fun getOutline(view: View, outline: Outline) {

                val left = 0
                val top = 0;
                val right = view.width
                val bottom = view.height
                val cornerRadiusDP = 16f
                val cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, cornerRadiusDP, resources.displayMetrics).toInt()

                // all corners
                outline.setRoundRect(left, top, right, bottom, cornerRadius.toFloat())

                /* top corners
                outline.setRoundRect(left, top, right, bottom+cornerRadius, cornerRadius.toFloat())*/

                /* bottom corners
                outline.setRoundRect(left, top - cornerRadius, right, bottom, cornerRadius.toFloat())*/

                /* left corners
                outline.setRoundRect(left, top, right + cornerRadius, bottom, cornerRadius.toFloat())*/

                /* right corners
                outline.setRoundRect(left - cornerRadius, top, right, bottom, cornerRadius.toFloat())*/

                /* top left corner
                outline.setRoundRect(left , top, right+ cornerRadius, bottom + cornerRadius, cornerRadius.toFloat())*/

                /* top right corner
                outline.setRoundRect(left - cornerRadius , top, right, bottom + cornerRadius, cornerRadius.toFloat())*/

                /* bottom left corner
                outline.setRoundRect(left, top - cornerRadius, right + cornerRadius, bottom, cornerRadius.toFloat())*/

                /* bottom right corner
                outline.setRoundRect(left - cornerRadius, top - cornerRadius, right, bottom, cornerRadius.toFloat())*/

            }
        }

        myView.outlineProvider = mOutlineProvider
        myView.clipToOutline = true

    }

答案 1 :(得分:0)

我设法通过创建自定义ViewOutlineProvider并使用它而不是背景值来使其正常工作

ViewOutlineProvider mViewOutlineProvider = new ViewOutlineProvider() {
    @Override
    public void getOutline(final View view, final Outline outline) {
        float cornerRadiusDP = 16f;
        float cornerRadius = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, cornerRadiusDP, getResources().getDisplayMetrics());
            outline.setRoundRect(0, 0, view.getWidth(), (int)(view.getHeight() + cornerRadius), cornerRadius);
        }
};
scrollView.setOutlineProvider(mViewOutlineProvider);
scrollView.setClipToOutline(true);

答案 2 :(得分:0)

我从@Jankers 和@Dragan 那里得到了解决方案并对其进行了浓缩,并添加了数据绑定,以便它可以从 xml 中完成。

<块引用>

注意:用轮廓剪裁不支持角不同 尺寸!

class RoundedCornersOutlineProvider( val radius: Float? = null, val topLeft: Float? = null, val topRight: Float? = null, val bottomLeft: Float? = null, val bottomRight: Float? = null, ) : ViewOutlineProvider() { private val topCorners = topLeft != null && topLeft == topRight private val rightCorners = topRight != null && topRight == bottomRight private val bottomCorners = bottomLeft != null && bottomLeft == bottomRight private val leftCorners = topLeft != null && topLeft == bottomLeft private val topLeftCorner = topLeft != null private val topRightCorner = topRight != null private val bottomRightCorner = bottomRight != null private val bottomLeftCorner = bottomLeft != null override fun getOutline(view: View, outline: Outline) { val left = 0 val top = 0 val right = view.width val bottom = view.height if (radius != null) { val cornerRadius = radius //.typedValue(resources).toFloat() outline.setRoundRect(left, top, right, bottom, cornerRadius) } else { val cornerRadius = topLeft ?: topRight ?: bottomLeft ?: bottomRight ?: 0F when { topCorners -> outline.setRoundRect(left, top, right, bottom + cornerRadius.toInt(), cornerRadius) bottomCorners -> outline.setRoundRect(left, top - cornerRadius.toInt(), right, bottom, cornerRadius) leftCorners -> outline.setRoundRect(left, top, right + cornerRadius.toInt(), bottom, cornerRadius) rightCorners -> outline.setRoundRect(left - cornerRadius.toInt(), top, right, bottom, cornerRadius) topLeftCorner -> outline.setRoundRect( left, top, right + cornerRadius.toInt(), bottom + cornerRadius.toInt(), cornerRadius ) bottomLeftCorner -> outline.setRoundRect( left, top - cornerRadius.toInt(), right + cornerRadius.toInt(), bottom, cornerRadius ) topRightCorner -> outline.setRoundRect( left - cornerRadius.toInt(), top, right, bottom + cornerRadius.toInt(), cornerRadius ) bottomRightCorner -> outline.setRoundRect( left - cornerRadius.toInt(), top - cornerRadius.toInt(), right, bottom, cornerRadius ) } } } } class CircleOutlineProvider : ViewOutlineProvider() { override fun getOutline(view: View, outline: Outline) { val size = view.run { min(width, height) } outline.setRoundRect(0, 0, size, size, (size).toFloat()) } }

Data Binding (@BindingAdapter):

@BindingAdapter("clipCircle") fun View.bindClipCircle(clipCircle: Boolean?) { outlineProvider = CircleOutlineProvider() clipToOutline = true } @BindingAdapter("clipRadius", "clipTopLeft", "clipTopRight", "clipBottomLeft", "clipBottomRight", requireAll = false) fun View.bindClipCorners(radius: Float?, topLeft: Float?, topRight: Float?, bottomLeft: Float?, bottomRight: Float?) { this.outlineProvider = RoundedCornersOutlineProvider(radius, topLeft, topRight, bottomLeft, bottomRight) this.clipToOutline = true }

Clipping in xml

<androidx.constraintlayout.widget.ConstraintLayout clipCircle="@{@bool/const_true}" ... <ImageView clipBottomLeft="@{@dimen/green_tab_corner_radius}" clipBottomRight="@{@dimen/green_tab_corner_radius}" ...

{{1}}