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

Работя върху приложение, което съдържа някои бутони, дефинирани чрез 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:states се изтеглят от мрежата и се записват в DB и не знам колко от тях има.

Има ли някакъв начин да се постигне това поведение? Прерових всички форуми и повечето отговори бяха, че е невъзможно. Намерих едно „решение“, презаписващо 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. Мисля, че можете да предоставите начални/крайни цветове по време на инициализацията и да зададете свойствата на щриха и радиуса на ъгъла след това. Но ще трябва да разберете сами за подложката. Не съм сигурен.

След като създадете чертежа, можете да го използвате в 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