Bir referans olduğunda (tema) programlı olarak renk değerini alın


116

Bunu düşün:

styles.xml

<style name="BlueTheme" parent="@android:style/Theme.Black.NoTitleBar">
    <item name="theme_color">@color/theme_color_blue</item>
</style>

attrs.xml

<attr name="theme_color" format="reference" />

color.xml

<color name="theme_color_blue">#ff0071d3</color>

Yani tema rengine tema tarafından referans verilir. Theme_color (referans) 'ı programlı olarak nasıl edinebilirim? Normalde kullanırdım getResources().getColor()ama bu durumda kullanmazdım çünkü referansta bulunuluyor!

Yanıtlar:


257

Bu işi yapmalı:

TypedValue typedValue = new TypedValue();
Theme theme = context.getTheme();
theme.resolveAttribute(R.attr.theme_color, typedValue, true);
@ColorInt int color = typedValue.data;

Ayrıca bu kodu çağırmadan önce temayı Etkinliğinize uyguladığınızdan emin olun. Aşağıdakilerden birini kullanın:

android:theme="@style/Theme.BlueTheme"

bildiriminizde veya aramanızda (aramadan önce setContentView(int)):

setTheme(R.style.Theme_BlueTheme)

içinde onCreate().

Sizin değerlerinizle test ettim ve mükemmel çalıştı.


teşekkürler Henüz çözümünüzü deneyemiyorum çünkü bir hata alıyorum: stackoverflow.com/questions/17278244/… Belki de bu konuda deneyiminiz vardır ...
Seraphim

5
Her neyse, çözümünüzle 0 değerinde bir renk alıyorum (TypedValue {t = 0x0 / d = 0x0}) ... Açıklamalı stil kullanmıyorum, sadece renge bir referans
Seraphim

Temayı aktivitenize uyguluyor musunuz?
Emanuel Moecklin

5
Temayı aktiviteye uygulamak istemiyorsanız ContextThemeWrapper, tema kimliğini kullanarak bir tema oluşturabilir ve ardından temayı buradan alabilirsiniz.
Ted Hopp

1
Bu yöntem android X'de çalışır (malzeme tasarımı)
BlackBlind

43

Kotlin kullanıyorsanız, kabul edilen cevaba eklemek için.

@ColorInt
fun Context.getColorFromAttr(
    @AttrRes attrColor: Int,
    typedValue: TypedValue = TypedValue(),
    resolveRefs: Boolean = true
): Int {
    theme.resolveAttribute(attrColor, typedValue, resolveRefs)
    return typedValue.data
}

ve sonra faaliyetinde yapabilirsin

textView.setTextColor(getColorFromAttr(R.attr.color))


2
oook, "entegrasyon" için teşekkürler. Kotlin kullanmıyorum ama ilginç.
Seraphim

5
TypedValue'yu dış dünya için görünür kılıyor. Ve renkler için her zaman referans bildirimlerini çözmek istersiniz, bu yüzden bu var: @ColorInt fun Context.getThemeColor(@AttrRes attribute: Int) = TypedValue().let { theme.resolveAttribute(attribute, it, true); it.data }(burada kötü biçimlendirilmiş ama sorun değil)
milosmns

1
Kullanım şu şekilde olacaktır:val errorColor = context.getThemeColor(R.attr.colorError)
milosmns

A ColorStateList: @ColorInt fun Context.getThemeColor(@AttrRes attribute: Int) = obtainStyledAttributes(intArrayOf(attribute)).use { it.getColor(0, Color.MAGENTA) }( Nick
Butcher'dan

ColorStateListBaşka bir tema özelliklerine başvursa bile bütünü alan nihai yol : fun Context.getThemeColor(@AttrRes attribute: Int): ColorStateList = TypedValue().let { theme.resolveAttribute(attribute, it, true); AppCompatResources.getColorStateList(this, it.resourceId) }(tek renkler de bir araya getirilecektir ColorStateList).
gmk57

24

Bu benim için çalıştı:

int[] attrs = {R.attr.my_attribute};
TypedArray ta = context.obtainStyledAttributes(attrs);
int color = ta.getResourceId(0, android.R.color.black);
ta.recycle();

hexstring'i bundan çıkarmak istiyorsanız:

Integer.toHexString(color)

Bu bir ColorInt değil, bir ColorRes döndürmelidir.
Miha_x64

Bunu getColorResource (color) ile kullanıp geri dönüşümü çağırmadım.
Zeek Aran

2

Birden fazla renk elde etmek istiyorsanız şunları kullanabilirsiniz:

int[] attrs = {R.attr.customAttr, android.R.attr.textColorSecondary, 
        android.R.attr.textColorPrimaryInverse};
Resources.Theme theme = context.getTheme();
TypedArray ta = theme.obtainStyledAttributes(attrs);

int[] colors = new int[attrs.length];
for (int i = 0; i < attrs.length; i++) {
    colors[i] = ta.getColor(i, 0);
}

ta.recycle();

2

Bunu build.gradle (uygulamanıza) ekleyin:

implementation 'androidx.core:core-ktx:1.1.0'

Ve bu uzantı işlevini kodunuzun herhangi bir yerine ekleyin:

@ColorInt
@SuppressLint("Recycle")
fun Context.themeColor(
    @AttrRes themeAttrId: Int
): Int {
    return obtainStyledAttributes(
        intArrayOf(themeAttrId)
    ).use {
        it.getColor(0, Color.MAGENTA)
    }
}

0

Burada, birden çok özniteliği alan ve bir renk tamsayı dizisi döndüren kısa bir Java yardımcı programı yöntemi verilmiştir. :)

/**
 * @param context    Pass the activity context, not the application context
 * @param attrFields The attribute references to be resolved
 * @return int array of color values
 */
@ColorInt
static int[] getColorsFromAttrs(Context context, @AttrRes int... attrFields) {
    int length = attrFields.length;
    Resources.Theme theme = context.getTheme();
    TypedValue typedValue = new TypedValue();

    @ColorInt int[] colorValues = new int[length];

    for (int i = 0; i < length; ++i) {
        @AttrRes int attr = attrFields[i];
        theme.resolveAttribute(attr, typedValue, true);
        colorValues[i] = typedValue.data;
    }

    return colorValues;
}

Java bunun için Kotlin'den daha mı iyi?
IgorGanapolsky

@IgorGanapolsky Oh, gerçekten bilmiyorum. Kodumu, dışarıdaki birinin işine yarayacağını bildiğim için paylaştım! Kotlin'i bilmiyorum ve Kotlin'in onu daha iyi, belki daha az kod satırı yapmayacağını varsayıyorum! : P
varun

-1

Kullanmanız gereken bir çekilebilir referans arayan olanlar için falsederesolveRefs

theme.resolveAttribute(R.attr.some_drawable, typedValue, **false**);


Referans olarak typedValue değişkeni neye göre?
BENN1TH

. * Değişken teması nedir?
BENN1TH
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.