Android 渐变形状边框

问题描述 投票:0回答:6

我想为线性布局创建边框。所以我决定创建一个形状。我希望边框有渐变。下面就不做了。它填充矩形,然后创建描边。我不需要填充的矩形,只想要描边。我想将渐变应用于笔画。

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <gradient
        android:angle="360"
        android:centerColor="#e95a22"
        android:endColor="#ff00b5"
        android:gradientRadius="360"
        android:startColor="#006386"
        android:type="sweep" />

    <stroke
        android:width="2dp"
        android:color="#ff207d94" />

</shape>
android android-layout android-drawable xml-drawable
6个回答
58
投票

尝试这样的事情:

<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

    <item>
        <shape android:shape="rectangle" >
            <gradient
                android:angle="360"
                android:centerColor="#e95a22"
                android:endColor="#ff00b5"
                android:gradientRadius="360"
                android:startColor="#006386"
                android:type="sweep" />

            <stroke
                android:width="2dp"
                android:color="#ff207d94" />
        </shape>
    </item>
    <item
        android:bottom="2dp"
        android:left="2dp"
        android:right="2dp"
        android:top="2dp">
        <shape android:shape="rectangle" >
            <solid android:color="#fff" />
        </shape>
    </item>

</layer-list>

42
投票

由于接受的答案并不完全按照我希望的方式工作,我也会发布我的解决方案,也许它对其他人有帮助:)

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

<item>
<!-- create gradient you want to use with the angle you want to use -->
    <shape android:shape="rectangle" >
        <gradient
            android:angle="0"
            android:centerColor="@android:color/holo_blue_bright"
            android:endColor="@android:color/holo_red_light"
            android:startColor="@android:color/holo_green_light" />

    </shape>
</item>
<!-- create the stroke for top, left, bottom and right with the dp you want -->
<item
    android:bottom="2dp"
    android:left="2dp"
    android:right="2dp"
    android:top="2dp">
    <shape android:shape="rectangle" >
        <!-- fill the inside in the color you want (could also be a gradient again if you want to, just change solid to gradient and enter angle, start, maybe center, and end color) -->
        <solid android:color="#fff" />
    </shape>
</item>

</layer-list>

5
投票

这将创建一个顶部边框为 2dp 的布局。 只需将其设置为布局的背景

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <gradient
                android:startColor="#4fc949"
                android:centerColor="#0c87c5"
                android:endColor="#b4ec51"
                android:angle="180" />
        </shape>
    </item>
    <item android:top="2dp">
        <shape android:shape="rectangle">
            <solid android:color="@color/background_color"/>
        </shape>
    </item>
</layer-list>

3
投票

这个额外的来源应该可以解决你的问题

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <gradient
                android:angle="360"
                android:centerColor="#e95a22"
                android:endColor="#ff00b5"
                android:gradientRadius="360"
                android:startColor="#006386"
                android:type="sweep" />
            <size android:height="170dp"
                android:width="170dp"/>
        </shape>
    </item>
    <item android:top="2dp" android:bottom="2dp" android:right="2dp" android:left="2dp">
        <shape android:shape="rectangle">
            <size android:width="140dp"
                android:height="140dp"/>
            <solid android:color="@color/colorAccent"/>
            <solid android:color="@color/white"/>
        </shape>
    </item>
</layer-list>

3
投票

这将是您想要做的事情的适当解决方案。它包括描边渐变以及填充颜色渐变。

<?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item>
            <shape >
                <gradient
                    android:startColor="#2196F3"
                    android:endColor="#673AB7"
                    android:angle="270" />
                <stroke
                    android:width="0dp"
                    android:color="@color/transparentColor" />
                <corners
                    android:radius="8dp" />
                <padding
                    android:left="2dp"
                    android:right="2dp"
                    android:top="2dp"
                    android:bottom="2dp" />
            </shape>
        </item>
        <item>
            <shape android:shape="rectangle">

            </shape>
        </item>
        <item android:top="0dp">
            <shape>
                <gradient
                    android:startColor="#FBB100"
                    android:endColor="#FF9900"
                    android:angle="270"/>

                <corners
                    android:radius="8dp" />
            </shape>
        </item>
    </layer-list>

0
投票

我认为仅使用 XML 无法实现带圆角的渐变边框。 您必须构建一个自定义视图才能实现此目的。

这是我构建的一个示例,您可以使用它设置渐变边框和自定义填充颜色。

enter image description here

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.LinearGradient
import android.graphics.Paint
import android.graphics.Path
import android.graphics.PorterDuff
import android.graphics.PorterDuffXfermode
import android.graphics.RectF
import android.graphics.Shader
import android.util.AttributeSet
import android.view.View
import com.example.helper.ui.utils.dpToPx

class GradientViewWithBorders : View {

    private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
    private var porterDuffXfermode_SRC_OVER = PorterDuffXfermode(PorterDuff.Mode.SRC_OVER)
    private var viewWidth = 0
    private var viewHeight = 0

    var startColor = Color.parseColor("#FFFFFF")
    var endColor = Color.parseColor("#50FFFFFF")

    var startFillColor = Color.parseColor("#50FFFFFF")

    var endFillColor = Color.parseColor("#00FFFFFF")

    var lineStrokeWidth = 1f

    val strokeGradient: LinearGradient by lazy {
        LinearGradient(
            0f,
            0f,
            this.viewWidth.toFloat(),
            this.viewHeight.toFloat(),
            startColor,
            endColor,
            Shader.TileMode.CLAMP
        )
    }


    val fillGradient: LinearGradient by lazy {
        LinearGradient(
            0f,
            0f,
            this.viewWidth.toFloat(),
            this.viewHeight.toFloat(),
            startFillColor,
            endFillColor,
            Shader.TileMode.CLAMP
        )
    }

    var rect = RectF()
    val corners = floatArrayOf(
        0f, 0f,  // Top, left in px
        0f, 0f,  // Top, right in px
        context.dpToPx(12f), context.dpToPx(12f),  // Bottom, right in px
        context.dpToPx(12f), context.dpToPx(12f) // Bottom,left in px
    )

    val outlinePath = Path()
    val innerPath = Path()


    constructor(context: Context) : super(context)

    constructor(context: Context, attributeSet: AttributeSet?) : super(context, attributeSet)

    constructor(context: Context, attributeSet: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attributeSet,
        defStyleAttr
    )


    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)

        this.viewWidth = w
        this.viewHeight = h

    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        paint.apply {
            style = Paint.Style.STROKE
            maskFilter = null
            shader = strokeGradient
            xfermode = porterDuffXfermode_SRC_OVER
            strokeWidth = context.dpToPx(lineStrokeWidth)
        }

        rect.set(
            context.dpToPx(lineStrokeWidth) + paddingLeft,
            context.dpToPx(lineStrokeWidth) + paddingTop,
            viewWidth.toFloat() - context.dpToPx(lineStrokeWidth) - paddingRight,
            viewHeight.toFloat() - context.dpToPx(lineStrokeWidth) - paddingBottom
        )


        outlinePath.addRoundRect(rect, corners, Path.Direction.CW);
        canvas.drawPath(outlinePath, paint)





        paint.apply {
            style = Paint.Style.FILL
            maskFilter = null
            shader = fillGradient
            xfermode = porterDuffXfermode_SRC_OVER
            strokeWidth = 0f
        }


        rect.set(
            context.dpToPx(lineStrokeWidth) + paddingLeft + context.dpToPx(0.5f),
            context.dpToPx(lineStrokeWidth) + paddingTop + context.dpToPx(0.5f),
            viewWidth.toFloat() - context.dpToPx(lineStrokeWidth) - paddingRight - context.dpToPx(
                0.5f
            ),
            viewHeight.toFloat() - context.dpToPx(lineStrokeWidth) - paddingBottom - context.dpToPx(
                0.5f
            )
        )


        innerPath.addRoundRect(rect, corners, Path.Direction.CW);

        canvas.drawPath(innerPath, paint)

    }
}

© www.soinside.com 2019 - 2024. All rights reserved.