android - 如何渐变填充按钮的背景?

标签 android android-ui

我必须创建一个带有渐变填充的彩色按钮(从按钮中间沿 Y 轴开始)。如果我将按钮的背景属性设置为我想要的颜色,我将失去按钮的 rounded 外观和感觉以及渐变填充(它看起来像一个 TextView有背景)。

此外,我希望在用户按下按钮时更改此颜色。我可以通过选择器 XML ( Color State Lists ) 指定它吗?

感谢任何可以帮助我的教程或链接。

谢谢。

最佳答案

我相信你想要做的是让你的按钮在正常状态、按下状态、聚焦状态等时显示不同的渐变。这可以使用 XML 来完成(在 res/中创建一个 selector.xml 文件drawable 引用 res/drawable 中的 shape.xml 文件,每个文件都包含一个渐变元素,然后将按钮的背景设置为您创建的 selector.xml 文件。)但是,XML 路由只允许您使用两个定义渐变(或可选的三)静态颜色,并且无法控制颜色停止点的位置。程序化解决方案将为您提供更大的灵 active ,并允许您动态更改颜色。下面是一个名为 GradientLab 的 Android 项目示例。

res/layouts 中的 main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical"
  style="@style/LayoutArea"
>
 <TextView
  style="@style/LayoutRow"
  android:text="@string/hello" />
 <Button
  style="@style/RowButton"
  android:id="@+id/btn1"
  android:text="1" />
 <Button
  style="@style/RowButton"
  android:id="@+id/btn2"
  android:text="2" />
 <Button
  style="@style/RowButton"
  android:id="@+id/btn3"
  android:text="3" />
</LinearLayout>

res/values 中的 styles.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <style name="LayoutArea">
  <item name="android:layout_width">fill_parent</item>
  <item name="android:layout_height">fill_parent</item>
 </style>
 <style name="LayoutRow">
  <item name="android:layout_width">fill_parent</item>
  <item name="android:layout_height">wrap_content</item>
 </style>
 <style name="LayoutColumn">
  <item name="android:layout_width">wrap_content</item>
  <item name="android:layout_height">fill_parent</item>
 </style>
 <style name="LayoutItem">
  <item name="android:layout_width">wrap_content</item>
  <item name="android:layout_height">wrap_content</item>
 </style>
 <style name="RowButton" parent="LayoutRow">
  <item name="android:layout_weight">1</item>
  <item name="android:layout_margin">8dp</item>
  <item name="android:gravity">center_horizontal</item>
 </style>
</resources>

android.examples 中的 GradientLab.java 演示使用带按钮的渐变:

package android.example;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.widget.Button;
import android.widget.LinearLayout;

public class GradientLab extends Activity {
    // Layout fields
    protected LinearLayout mainLayout;
    public static Button btn1 = null;
    public static Button btn2 = null;
    public static Button btn3 = null;

    // Members
    private int[] normalColors = new int[4];
    private int[] focusedColors = new int[2];
    private int[] disabledColors = new int[1];
    private int defaultSkinR = 94;
    private int defaultSkinG = 128;
    private int defaultSkinB = 219;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        /*
         * This creates View objects from the xml file. The xml file should
         * define all views and all static attributes.
         */
        mainLayout = (LinearLayout) getLayoutInflater().inflate(R.layout.main,
                null);

        normalColors[0] = Color.argb(255, defaultSkinR, defaultSkinG,
                defaultSkinB);
        normalColors[1] = Color.argb(255, 217, 217, 217);
        normalColors[2] = Color.argb(191, defaultSkinR, defaultSkinG,
                defaultSkinB);
        normalColors[3] = Color.argb(140, defaultSkinR, defaultSkinG,
                defaultSkinB);

        focusedColors[0] = Color.argb(229, 242, 242, 242);
        focusedColors[1] = Color.BLUE;

        UIGradientSelector gradientSelector1 = new UIGradientSelector(
                normalColors, focusedColors, null);
        UIGradientSelector gradientSelector2 = new UIGradientSelector(
                normalColors, focusedColors, null);

        disabledColors[0] = Color.argb(153, 216, 216, 216);
        UIGradientDrawable disabledGradient = new UIGradientDrawable(
                disabledColors);

        btn1 = (Button) mainLayout.findViewById(R.id.btn1);
        btn1.setBackgroundDrawable(gradientSelector1);

        btn2 = (Button) mainLayout.findViewById(R.id.btn2);
        btn2.setBackgroundDrawable(gradientSelector2);

        btn3 = (Button) mainLayout.findViewById(R.id.btn3);
        btn3.setBackgroundDrawable(disabledGradient);

        setContentView(mainLayout);
    }
}

android.examples 中的 UIGradientSelector.java 根据按钮状态选择渐变:

package android.example;

import android.graphics.drawable.StateListDrawable;

/**
 * {@link StateListDrawable} that controls selection of
 * {@link UIGradientDrawable} based on the three basic button states.
 */
public class UIGradientSelector extends StateListDrawable {

    /**
     * {@link UIGradientSelector} that selects the {@link UIGradientDrawable}
     * defined by the colors for the three basic button states.
     * 
     * @param normalColors
     *            Array of primitive ints that define the gradient colors for a
     *            button in its normal state.
     * @param focusedColors
     *            Array of primitive ints that define the gradient colors for a
     *            button in its focused state.
     * @param pressedColors
     *            Array of primitive ints that define the gradient colors for a
     *            button in its pressed state. If the array is null, then
     *            focusedColors will be used for the pressed state.
     */
    public UIGradientSelector(int[] normalColors, int[] focusedColors,
            int[] pressedColors) {
        int stateFocused = android.R.attr.state_focused;
        int statePressed = android.R.attr.state_pressed;
        UIGradientDrawable normalGradient = new UIGradientDrawable(normalColors);
        UIGradientDrawable focusedGradient = new UIGradientDrawable(
                focusedColors);
        UIGradientDrawable pressedGradient;

        if (pressedColors == null) {
            pressedGradient = focusedGradient;
        } else {
            pressedGradient = new UIGradientDrawable(pressedColors);
        }

        addState(new int[] { stateFocused }, focusedGradient);
        addState(new int[] { statePressed }, pressedGradient);
        addState(new int[] { -statePressed, -stateFocused }, normalGradient);
    }
}

绘制表面的 android.examples 中的 UIGradientDrawable.java:

package android.example;

import android.graphics.drawable.PaintDrawable;
import android.graphics.drawable.shapes.RectShape;

/**
 * {@link PaintDrawable} that paints the surface via a {@link UIGradientShader}.
 */
public class UIGradientDrawable extends PaintDrawable {

    /**
     * {@link UIGradientDrawable} with an initial shape of a rounded rectangle
     * that transitions evenly between the specified colors.
     * 
     * @param colors
     *            Array of primitive ints that contain the argb values of the
     *            color to use for transitioning.
     */
    public UIGradientDrawable(int[] colors) {
        UIGradientShader gradientShader = new UIGradientShader(colors);
        setShape(new RectShape());
        setCornerRadius(8);
        setShaderFactory(gradientShader);
        setDither(true);
    }

}

android.examples 中处理实际转换的 UIGradientShader.java:

package android.example;

import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Shader;
import android.graphics.drawable.ShapeDrawable.ShaderFactory;

/**
 * {@link ShaderFactory} that uses a {@link LinearGradient} to transition
 * between specified colors. Any number of colors may be specified.
 */
public class UIGradientShader extends ShaderFactory {
    private int[] colors;
    private float[] positions;

    /**
     * {@link UIGradientShader} that spaces color transitions evenly across the
     * painting surface.
     * 
     * @param colors
     *            Array of primitive ints that contain the argb values of the
     *            color to use for transitioning. If the array contains only one
     *            color, then an argb of (0, 0, 0, 0) will be used for the end
     *            color of the transition. If the array is set to null or
     *            contains zero colors, then the transition will be from an argb
     *            of (255, 255, 255, 255) to and argb of (0, 0, 0, 0).
     * 
     * @see Color
     */
    public UIGradientShader(int[] colors) {
        init(colors, null);
    }

    /**
     * {@link UIGradientShader} that spaces color transitions across the
     * painting surface as specified.
     * 
     * @param colors
     *            Array of primitive ints that contain the argb values of the
     *            color to use for transitioning. If the array contains only one
     *            color, then an argb of (0, 0, 0, 0) will be used for the end
     *            color of the transition. If the array is set to null or
     *            contains zero colors, then the transition will be from an argb
     *            of (255, 255, 255, 255) to and argb of (0, 0, 0, 0).
     * @param positions
     *            Array of primitive floats that contain the position of the
     *            transition points. If the array is null, then the color
     *            transitions will be spaced evenly.
     */
    public UIGradientShader(int[] colors, float[] positions) {
        init(colors, positions);
    }

    private void init(int[] colors, float[] positions) {
        if (colors == null || colors.length == 0) {
            this.colors = new int[2];
            this.colors[0] = Color.argb(255, 255, 255, 255);
            this.colors[1] = Color.argb(0, 0, 0, 0);
        } else if (colors.length == 1) {
            this.colors = new int[2];
            this.colors[0] = colors[0];
            this.colors[1] = Color.argb(0, 0, 0, 0);
        } else {
            this.colors = colors;
        }

        this.positions = positions;
    }

    public Shader resize(int width, int height) {
        LinearGradient lg = new LinearGradient(0, 0, 0, height, colors,
                positions, Shader.TileMode.REPEAT);
        return lg;
    }

}

关于android - 如何渐变填充按钮的背景?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2401009/

相关文章:

android - 对于 6220816 字节分配错误,将堆( fragment 情况)增加到 8.837MB

android - 如何知道点击的小部件 ID?

android - 如何设置 android Horizo​​ntalScrollView 从右到左的行为(默认从右侧选择选项卡,而不是左侧)

android - 是否有适用于 Android 的自定义 UI 工具包?

android - 无法在 Android Studio 中解析符号 'LocationClient'

android - TextView.setMaxLines 不起作用?

java - 使用 CustomAdapter 更改 ListView 的显示方式

android - 如何在样式表中指定 progressBarStyleHorizo​​ntal 属性

android - 有没有更简单/更好的方法在我的 TextView 周围放置边框/轮廓?

android - 在 Android 中,跨多个 View 使用相同的工具栏(RelativeLayout 元素)