Кнопки разных цветов и одинаковых стилей

Я работаю над приложением, которое содержит некоторые кнопки, определенные с помощью layout.xml, как это

<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/largebutton" >
</Button>

@drawable/largebutton выглядит так

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

    <item android:state_pressed="true" >
        <shape>
            <gradient android:startColor="@color/menu_button_active_start" android:endColor="@color/menu_button_active_end" android:angle="270" />
            <stroke android:width="@dimen/largebutton_stroke" android:color="@color/menu_button_stroke" />
            <corners android:radius="@dimen/largebutton_radius" />
            <padding android:left="@dimen/largebutton_padding_leftright" android:top="@dimen/largebutton_padding_topbottom" android:right="@dimen/largebutton_padding_leftright" android:bottom="@dimen/largebutton_padding_topbottom" />
        </shape>
    </item>

    <item android:state_focused="true" >
        <shape>
            <gradient android:startColor="@color/menu_button_focused_start" android:endColor="@color/menu_button_focused_end" android:angle="270" />
            <stroke android:width="@dimen/largebutton_stroke" android:color="@color/menu_button_focused_stroke" />
            <corners android:radius="@dimen/largebutton_radius" />
            <padding android:left="@dimen/largebutton_padding_leftright" android:top="@dimen/largebutton_padding_topbottom" android:right="@dimen/largebutton_padding_leftright" android:bottom="@dimen/largebutton_padding_topbottom" />
        </shape>
    </item>
 .....
</selector>

Все свойства, такие как отступы, обводка, радиус, одинаковы, за исключением цветов градиента в разных состояниях. Моя проблема в том, что мое приложение должно иметь больше стилей. Вы можете себе представить, что у вас есть список цветов, и когда вы выбираете один, приложение меняет все цвета на выбранный. Итак, если у вас есть 20 цветов, 20 разных XML-файлов - это неправильный путь.

Значения startColor и endColor для всех состояний android: загружаются из Интернета и сохраняются в БД, и я не знаю, сколько их там.

Есть ли способ добиться такого поведения? Я облазил все форумы, и большинство ответов были о том, что это невозможно. Я нашел одно «решение», перезаписывающее colors.xml, но оно не кажется мне лучшим решением.

Итак, мой вопрос: могу ли я динамически менять цвет в colors.xml? Что-то вроде этого

List<Colors> colors = downloadColorsFromWeb();

Button b = new Button;
b.setDrawable(drawable.with(colors));

Спасибо всем заранее.

носко.


person Noskovic Michal    schedule 13.06.2012    source источник


Ответы (2)


Вероятно, вы могли бы динамически генерировать рисунок для каждого цвета, который вы загружаете. Проверьте класс GradientDrawable. Я думаю, вы можете указать начальный/конечный цвета во время инициализации и после этого установить свойства штриха и радиуса угла. Но вам придется узнать о прокладке самостоятельно. Я не уверена.

После того, как вы создадите drawable, вы можете использовать его в кнопке setBackgroundDrawable

редактировать: возможно, установка отступов кнопки поможет

edit2: вы можете setState рисовать, но я не уверен, как установить другой фон для каждого состояния кнопки.

person stan0    schedule 13.06.2012

Спасибо, @stan0, за ответ, он очень помог, особенно класс GradientDrawable.

Я написал простой класс, который создает кнопку и может задавать стиль в зависимости от ее состояния. Может кому поможет :)

import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.GradientDrawable.Orientation;
import android.util.AttributeSet;
import android.widget.Button;

/**
 * @author nosko
 *
 */
public class TabButton extends Button {

    private Context c;
    private GradientDrawable selected, focused, pressed, normal;

    public void setNormalState(GradientDrawable gd) {
        this.normal = gd;
    }

    public void setSelectedState(GradientDrawable gd) {
        this.selected = gd;
    }

    public void setFocusedState(GradientDrawable gd) {
        this.focused = gd;
    }

    public void setPressedState(GradientDrawable gd) {
        this.pressed = gd;
    }

    public TabButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub

        selected = pressed = focused = normal = new GradientDrawable(Orientation.TOP_BOTTOM, new int[] { Color.WHITE, Color.DKGRAY });

        this.c          = context;
        this.setPadding(8, 8, 8, 8);        
    }


    /**
     * Change colors when button's state changes
     */
    protected void drawableStateChanged() {

        normal.setCornerRadius(8);
        normal.setStroke(2, Color.parseColor(c.getResources().getString(R.color.tab_button_border)));
        normal.setShape(GradientDrawable.RECTANGLE);
        this.setBackgroundDrawable(normal);

        if (isSelected()) {

            selected.setCornerRadius(8);
            selected.setStroke(2, Color.parseColor(c.getResources().getString(R.color.tab_button_border)));
            selected.setShape(GradientDrawable.RECTANGLE);
            this.setBackgroundDrawable(selected);
        }

        if (isFocused()) {
            focused.setCornerRadius(8);
            focused.setStroke(2, Color.parseColor(c.getResources().getString(R.color.tab_button_border)));
            focused.setShape(GradientDrawable.RECTANGLE);
            this.setBackgroundDrawable(focused);
        }

        if (isPressed()) {
            pressed.setCornerRadius(8);
            pressed.setStroke(2, Color.parseColor(c.getResources().getString(R.color.tab_button_border)));
            pressed.setShape(GradientDrawable.RECTANGLE);
            this.setBackgroundDrawable(pressed);
        }
    }

}

и использовать его так

TabButton b = new TabButton(context, null);

b.setNormalState(new GradientDrawable(Orientation.TOP_BOTTOM, new int[] { Color.RED, Color.CYAN }));
b.setSelectedState(new GradientDrawable(Orientation.TOP_BOTTOM, new int[] { Color.YELLOW, Color.BLUE }));
b.setFocusedState(new GradientDrawable(Orientation.TOP_BOTTOM, new int[] { Color.YELLOW, Color.GREEN }));
b.setPressedState(new GradientDrawable(Orientation.TOP_BOTTOM, new int[] { Color.YELLOW, Color.BLACK }));
person Noskovic Michal    schedule 14.06.2012