2011-09-01 14 views
45

W systemie Android można uzyskać bieżący motyw działania jako obiekt Resource.Theme z getTheme(). Możesz również ustawić motyw na inny za pomocą tego identyfikatora zasobu innej kompozycji, np. setTheme(R.style.Theme_MyTheme).Android: jak uzyskać identyfikator zasobu bieżącego motywu?

Ale jak mogę sprawdzić, czy to jest tego warte - czy obecny temat jest już tym, który chciałbym ustawić? Szukam czegoś podobnego getTheme().getResourceId(), aby napisać coś takiego:

protected void onResume() { 
    int newThemeId = loadNewTheme(); 
    if (newThemeId != getTheme().getResourceId()) { // !!!! How to do this? 
     setTheme(newThemeId); 
     // and rebuild the gui, which is expensive 
    } 
} 

jakieś pomysły?

+0

Nie sądzę, że identyfikator zasobu jest atrybutem klasy kompozycji. Temat może zostać utworzony z pliku XML źródła, ale wówczas utracone zostanie odniesienie do identyfikatora. Temat sam mógł zostać zmieniony, a wtedy nie miałoby sensu być związany z pewnym identyfikatorem zasobu. Co więcej, motyw może być tworzony w locie w kodzie. Będziesz musiał śledzić, który identyfikator źródła został użyty do bieżącego motywu. – Anderson

+0

Ta odpowiedź pomoże. Sprawdź to http://stackoverflow.com/a/26302184/4639479 –

Odpowiedz

34

OK oto jeden kawałek układanki: możemy uzyskać domyślny temat, jak ustawić w AndroidManifest.xml, jak context.getApplicationInfo().theme do tematu ustalona na poziomie aplikacji oraz z poziomu aktywności, jak getPackageManager().getActivityInfo(getComponentName(), 0).theme dla tej działalności.

Sądzę, że to daje nam punkt wyjścia do stworzenia własnego opakowania dla niestandardowych getTheme() i setTheme().

Nadal czujesz się jak pracując pod numerem pod numerem zamiast z z API. Pozostawię więc pytanie otwarte, aby sprawdzić, czy ktoś wymyśli lepszy pomysł.

+0

To samo przeczucie o tym i +1 o znalezieniu go. –

+12

Istnieje metoda 'getThemeResId()' na 'Context' ale niestety nie jest ona publiczna :-( –

27

Znalazłem sposób na rozwiązanie wymagania bez uzyskania identyfikatora zasobu.

Dodaję element do każdego z moich tematów z nazwą wyrażenie:

<item name="themeName">dark</item> 

I w kodzie sprawdzić nazwę tak:

TypedValue outValue = new TypedValue(); 
getTheme().resolveAttribute(R.attr.themeName, outValue, true); 
if ("dark".equals(outValue.string)) { 
    ... 
} 
+1
+1

To naprawdę ciekawy pomysł. Dzięki! – LoungeKatt

7

Jest sposób zrobić to poprzez refleksję. Umieścić to w swojej działalności:

int themeResId = 0; 
try { 
    Class<?> clazz = ContextThemeWrapper.class; 
    Method method = clazz.getMethod("getThemeResId"); 
    method.setAccessible(true); 
    themeResId = (Integer) method.invoke(this); 
} catch (NoSuchMethodException e) { 
    Log.e(TAG, "Failed to get theme resource ID", e); 
} catch (IllegalAccessException e) { 
    Log.e(TAG, "Failed to get theme resource ID", e); 
} catch (IllegalArgumentException e) { 
    Log.e(TAG, "Failed to get theme resource ID", e); 
} catch (InvocationTargetException e) { 
    Log.e(TAG, "Failed to get theme resource ID", e); 
} 
// use themeResId ... 

[Wstaw tu zastrzeżenie dotyczące apis niepublicznych]

+0

Działa poprawnie. –

3

Według sources Activity.setTheme jest wywoływana przed Activity.onCreate, więc można zapisać themeId kiedy android ustaw :

public class MainActivity extends Activity { 
    private int themeId; 

    @Override 
    public void setTheme(int themeId) { 
     super.setTheme(themeId); 
     this.themeId = themeId; 
    } 

    public int getThemeId() { 
     return themeId; 
    } 
} 
Powiązane problemy