ColorStateList'i programlı olarak nasıl oluştururum?


158

Bunu ColorStateListkullanarak bir programlı oluşturmaya çalışıyorum :

ColorStateList stateList = new ColorStateList(states, colors); 

Ama iki parametrenin ne olduğundan emin değilim.

Belgelere göre:

public ColorStateList (int[][] states, int[] colors) 

API seviye 1'de eklendi

Durumlardan renklere belirtilen eşlemeyi döndüren bir ColorStateList oluşturur.

Birisi bana bunu nasıl oluşturacağımı açıklayabilir mi?

Durumlar için iki boyutlu dizinin anlamı nedir?

Yanıtlar:


344

Kullanılabilir durumların listesi için http://developer.android.com/reference/android/R.attr.html#state_above_anchor adresine bakın .

Devre dışı, odaklanmamış, denetlenmeyen durumlar vb. İçin renkler ayarlamak istiyorsanız, yalnızca durumları reddedin:

int[][] states = new int[][] {
    new int[] { android.R.attr.state_enabled}, // enabled
    new int[] {-android.R.attr.state_enabled}, // disabled
    new int[] {-android.R.attr.state_checked}, // unchecked
    new int[] { android.R.attr.state_pressed}  // pressed
};

int[] colors = new int[] {
    Color.BLACK,
    Color.RED,
    Color.GREEN,
    Color.BLUE
};

ColorStateList myList = new ColorStateList(states, colors);

45
"Zıt" durumlar hakkında bilgi için teşekkürler!
BVB

Bu, tasarım kitaplığından bir fab'ın rengini değiştirmek için kullanılabilir.
Tapirboy

5
DİKKAT: Buradaki durumların sırasının kötü olduğunu anlamak için Roger Alien'in cevabına (ve ilk yorumuna) bakın: "etkin" ilk olduğundan, bir düğme etkinleştirildiğinde genellikle ortaya çıkan diğer durumları geçersiz kılar. Son "etkin" koymak daha iyidir. (Ya da "etkin" yerine, boş / varsayılan bir öğe son olarak
kalır

2
Devlet tutmaz bir düğme (DEĞİL bir geçiş / onay kutusu) olabilir için devletlerin temel listesi {pressed}, {focused}, {-enabled}, {}. Bunun durumlu bir olabilir için {checked, pressed}, {pressed}, {checked, focused}, {focused}, {checked}, {-enabled}, {}. Ya yoksaydıklarınız odak bir geçiş: {checked, pressed}, {pressed}, {checked}, {-enabled}, {}.
ToolmakerSteve

Birisi bu çözümlerden herhangi birini deneyecekse, selector.xml'deki gibi durumlara dikkat edin!
Anton Makov

75

İlk boyut bir durum kümeleri dizisidir, ikincisi durumun kendisi isterse. Colors dizisi, eşleşen her durum kümesi için renkleri listeler, bu nedenle colors dizisinin uzunluğu durum dizisinin ilk boyutuyla eşleşmelidir (veya durum "kullanıldığında" çökecektir). Burada ve örnek:

ColorStateList myColorStateList = new ColorStateList(
                        new int[][]{
                                new int[]{android.R.attr.state_pressed}, //1
                                new int[]{android.R.attr.state_focused}, //2
                                new int[]{android.R.attr.state_focused, android.R.attr.state_pressed} //3
                        },
                        new int[] {
                            Color.RED, //1
                            Color.GREEN, //2
                            Color.BLUE //3
                        }
                    );

Bu yardımcı olur umarım.

EDIT örneği: şunun gibi bir xml renk durumu listesi:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:color="@color/white"/>
    <item android:color="@color/black"/>
</selector>

böyle görünecek

ColorStateList myColorStateList = new ColorStateList(
        new int[][]{
                new int[]{android.R.attr.state_pressed},
                new int[]{}
        },
        new int[] {
                context.getResources().getColor(R.color.white),
                context.getResources().getColor(R.color.black)
        }
);

Aşağıdaki xml "<selector xmlns: android =" schemas.android.com/apk/res/android "> <item android: state_pressed =" true "android: color =" @ color / white "/ > <item android: color = "@ color / black" /> </selector> "renk belirleyicisini kullanarak.
Satish

@SatishKumar düzenlememi kontrol et, yine de test etmedim.
Su-Au Hwang

3
Yanlış bir durum belirtmek için değerini düşürebileceğinizi söylemeye değer, bu yüzden basılmadığı zaman için bir renk belirtmek istiyorsanız şunu kullanmalısınız: new int [] {- ​​android.R.attr.state_pressed}
tinsukE

1
@TinsukE'nin söylediklerine eklemek için: Ancak, listenin ilerleyen kısımlarında bir öğeyi yanlışlıkla bastırmaktan kaçınmak için, çoğu eyalet için bir olumsuzlama koymak mantıklı olmaz - bunun yerine tüm "diğer" olasılıkları varsayılan (boş) bir öğeyle işlemek new int[]{}son - bu cevabın son kod bloğunda gösterildiği gibi. Tipik olarak kullandığım sadece reddedilen değer "etkin" dir. Eğer üç farklı renk isterseniz başka örnek,:,, "basılı değil + odaklı" sadece koyabilirsiniz, "+ odaklı değil preslenmiş" "+ basılı odaklı" {focused, pressed}, {focused}, {pressed}. İlk "doğru" olan kullanılır.
ToolmakerSteve

2
... Eğer hale getirebileceğini hata gibi bir dizi sahip olmaktır {pressed}, {-pressed}, {focused}, {-focused}. Sorun şu ki {pressed}, {-pressed}TÜM olasılıkları kapsamaktadır (düğmeye basılır ya da basılmaz), bu nedenle daha sonra listelenen hiçbir renk kullanılmayacaktır.
ToolmakerSteve

65

Bazen bu yeterli olacaktır:

int colorInt = getResources().getColor(R.color.ColorVerificaLunes);
ColorStateList csl = ColorStateList.valueOf(colorInt);

20

Ne yazık ki çözümlerin hiçbiri benim için çalışmıyor.

  1. İlk başta basılı durumu ayarlamazsanız, algılamaz.
  2. Ayarladıysanız, varsayılan renk eklemek için boş durum tanımlamanız gerekir
ColorStateList themeColorStateList = new ColorStateList(
        new int[][]{
                new int[]{android.R.attr.state_pressed},
                new int[]{android.R.attr.state_enabled},
                new int[]{android.R.attr.state_focused, android.R.attr.state_pressed},
                new int[]{-android.R.attr.state_enabled},
                new int[]{} // this should be empty to make default color as we want
        },
        new int[]{
                pressedFontColor,
                defaultFontColor,
                pressedFontColor,
                disabledFontColor,
                defaultFontColor
        }
);

Bu kaynak kodundan yapıcıdır:

/**
 * Creates a ColorStateList that returns the specified mapping from
 * states to colors.
 */
public ColorStateList(int[][] states, int[] colors) {
    mStateSpecs = states;
    mColors = colors;

    if (states.length > 0) {
        mDefaultColor = colors[0];

        for (int i = 0; i < states.length; i++) {
            if (states[i].length == 0) {
                mDefaultColor = colors[i];
            }
        }
    }
}

5
Tıpkı bir sidenote gibi: Buna if-elseif gibi davranmalısınız. Doğru olan ilk durumu seçer. Dolayısıyla, state_enabled öğesini ilk durum olarak etkinleştirdiyseniz, görünüm devre dışı bırakılmadığı sürece state_pressed'den önce seçilir.
LeoFarage

FWIW, en son varsayılan bir öğeye sahip olduğunuz için, ilk "etkin" öğenin size hiçbir faydası olduğunu düşünmüyorum. Neden tamamen kaldırmıyorsunuz?
ToolmakerSteve

18

İşte ColorListKotlin'de programlı olarak nasıl oluşturulacağına dair bir örnek :

val colorList = ColorStateList(
        arrayOf(
                intArrayOf(-android.R.attr.state_enabled),  // Disabled
                intArrayOf(android.R.attr.state_enabled)    // Enabled
        ),
        intArrayOf(
                Color.BLACK,     // The color for the Disabled state
                Color.RED        // The color for the Enabled state
        )
)

Ayrıca, bir Kotlin yardımcı işlevi için cevabımı aşağıya bakın .
arekolek

7

Jonathan Ellis'in cevabından sekerek, Kotlin'de kodu biraz daha deyimsel ve okunması daha kolay hale getirmek için bir yardımcı işlev tanımlayabilirsiniz, böylece bunu yazabilirsiniz:

val colorList = colorStateListOf(
    intArrayOf(-android.R.attr.state_enabled) to Color.BLACK,
    intArrayOf(android.R.attr.state_enabled) to Color.RED
)

colorStateListOf şu şekilde uygulanabilir:

fun colorStateListOf(vararg mapping: Pair<IntArray, Int>): ColorStateList {
    val (states, colors) = mapping.unzip()
    return ColorStateList(states.toTypedArray(), colors.toIntArray())
}

Ayrıca:

fun colorStateListOf(@ColorInt color: Int): ColorStateList {
    return ColorStateList.valueOf(color)
}

Seçici ya da tek renk olsun, aynı işlev adını çağırabilirim.


3

Oluşturmak için oluşturucu sınıfım ColorStateList

private class ColorStateListBuilder {
    List<Integer> colors = new ArrayList<>();
    List<int[]> states = new ArrayList<>();

    public ColorStateListBuilder addState(int[] state, int color) {
        states.add(state);
        colors.add(color);
        return this;
    }

    public ColorStateList build() {
        return new ColorStateList(convertToTwoDimensionalIntArray(states),
                convertToIntArray(colors));
    }

    private int[][] convertToTwoDimensionalIntArray(List<int[]> integers) {
        int[][] result = new int[integers.size()][1];
        Iterator<int[]> iterator = integers.iterator();
        for (int i = 0; iterator.hasNext(); i++) {
            result[i] = iterator.next();
        }
        return result;
    }

    private int[] convertToIntArray(List<Integer> integers) {
        int[] result = new int[integers.size()];
        Iterator<Integer> iterator = integers.iterator();
        for (int i = 0; iterator.hasNext(); i++) {
            result[i] = iterator.next();
        }
        return result;
    }
}

Kullanım Örneği

ColorStateListBuilder builder = new ColorStateListBuilder();
builder.addState(new int[] { android.R.attr.state_pressed }, ContextCompat.getColor(this, colorRes))
       .addState(new int[] { android.R.attr.state_selected }, Color.GREEN)
       .addState(..., some color);

if(// some condition){
      builder.addState(..., some color);
}
builder.addState(new int[] {}, colorNormal); // must add default state at last of all state

ColorStateList stateList = builder.build(); // ColorStateList created here

// textView.setTextColor(stateList);

2

eğer kaynağı Colors.xml dosyası kullanırsanız

int[] colors = new int[] {
                getResources().getColor(R.color.ColorVerificaLunes),
                getResources().getColor(R.color.ColorVerificaMartes),
                getResources().getColor(R.color.ColorVerificaMiercoles),
                getResources().getColor(R.color.ColorVerificaJueves),
                getResources().getColor(R.color.ColorVerificaViernes)

        };

ColorStateList csl = new ColorStateList(new int[][]{new int[0]}, new int[]{colors[0]}); 

    example.setBackgroundTintList(csl);

2
olarak getResources()şimdi, bir itiraz edildi ContextCompat.getColor(this,R.color.colorname);ya ContextCompat.getColor(getActivity(),R.color.colorname);Fragment kullanım için
iBobb

Diğer okuyucular için açıklığa kavuşturmak için new int[0](ilk parametre listesindeki bir öğe olarak) sıfır uzunluklu bir dizidir ve varsayılan rengin ayarlanmasını temsil eder. Burada tek unsurdur, yani renk tonu düğmenin tüm durumlarına uygulanır . Bu new int[]{}Roger Alien'in cevabında görülene eşdeğerdir .
ToolmakerSteve
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.