2017-01-26 88 views
7

wiem, że jest to sposób, aby ustawić tematów definiując w styles.xml i używać go jak tenJak zmienić motyw z innego zasobu aplikacji w systemie Android?

setTheme(android.R.style.MyTheme); 

Jednak chcę się tematy z innej aplikacji, które ja rozwiniętym, jak również. Znam nazwy zasobów i faktycznie jestem w stanie uzyskać identyfikator tematu z tym blokiem kodu;

Resources res = getPackageManager().getResourcesForApplication("com.example.theme"); 
int resThemeId = res.getIdentifier("my_theme","style","com.example.theme"); 

Kiedy debuguję, widzę, że resThemeId nie jest zero.

Następnie potrzebuję końcowego polecenia, aby ustawić ten temat. Przed super.onCreate function(), staram się wdrożyć tę metodę, ale wydaje się, że nie działa

setTheme(resThemeId); 

Ale zamiast tego, jeśli piszę poniżej oświadczenie, że działa dobrze

setTheme(android.R.style.Theme_Holo_Light); 

Tak , co powinienem zrobić, aby użyć motywu z innego zasobu paczki?

+3

Możesz pobrać identyfikator zasobu z innego pakietu, ale te zasoby nie istnieją w pliku APK. Ładowanie zasobów przy użyciu 'PackageManager # getResourcesForApplication (String nazwaPakietu)' powinno działać dla rysunków, łańcuchów, znaków itd. Jednak nie sądzę, aby było możliwe, i zdecydowanie nie zalecane, aby załadować inny motyw APK. –

+0

Mimo że mogę uzyskać rysunki, łańcuchy, booleany z innych zasobów pakietu, również oczekuję motywów. Dlaczego to niemożliwe? – Berkay92

+0

Jest to możliwe (patrz moja odpowiedź). Musisz nadpisać getResrouces, aby zwrócić zasoby drugiej aplikacji, aby móc zastosować motyw. Spowoduje to również zwrócenie wszystkich łańcuchów, układów, rysunków i innych zasobów z drugiej aplikacji, dlatego nie jest zalecane. –

Odpowiedz

3

Co należy zrobić, aby użyć motywu z innego zasobu paczki?

Nie powinieneś tego robić z wielu powodów. Napisałem prosty projekt, który pokazuje, że jest to rzeczywiście możliwe, o ile pakiet zawiera zasoby, z których korzysta twoja działalność.

Patrz: https://github.com/jaredrummler/SO-41872033


Zasadniczo trzeba by powrócić zasobów z pakietami z działalności:

public class MainActivity extends AppCompatActivity { 

    Resources resources; 

    @Override protected void onCreate(Bundle savedInstanceState) { 

    int themeResId = getResources().getIdentifier("AppTheme", "style", "com.example.theme"); 
    if (themeResId != 0) { 
     setTheme(themeResId); 
    } 

    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    } 

    @Override public Resources getResources() { 
    if (resources == null) { 
     try { 
     resources = getPackageManager().getResourcesForApplication("com.example.theme"); 
     } catch (PackageManager.NameNotFoundException e) { 
     resources = super.getResources(); 
     } 
    } 
    return resources; 
    } 

} 

To jest po prostu pokazać, że jest to możliwe. Ponownie zalecam unikanie tego.

+0

Czy w ten sposób można zmienić zasoby w czasie wykonywania? Mam na myśli, chcę ustawić oryginalne zasoby po ustawieniu motywu z innego zasobu? – Berkay92

+0

Nie sądzę, że jest to możliwe, ale nie sądziłem, że możliwe jest zastosowanie motywu z innego pakietu. Dlatego nie poleciłbym tego rozwiązania. Nie chcesz używać zasobów innego pakietu do układu i żadnych rysunków w swojej aktywności. Co dokładnie chcesz osiągnąć dzięki temu? –

+0

Właściwie to próbuję napisać menedżera motywów i różne apki, które zawierają pewne motywy (Motywy zawierają obrazy tła, domyślne dźwięki, ikony aplikacji itp.) Po uruchomieniu aplikacji do zarządzania motywami mogę odzyskać rysunki i wyświetlić je odpowiednio w apk. Jednak po zmianie motywu chcę też zmienić niektóre motywy aplikacji (takie jak aplikacja Ustawienia). (Chcę ustawić kolory podstawowe, akcentujące itp.) Przy okazji, pracuję nad projektem AOSP i mogę łatwo zmienić kod ustawień. Wszystko, czego chcę, to zmiana motywu ustawień z jednego z moich zasobów aplikacji motywu. – Berkay92

4

Jak już wspomniano w komentarzu, można uzyskać dostęp do zasobów z innych aplikacji, ale korzystanie z innego motywu aplikacji nie będzie działać.


Ponieważ posiadające dowód jest zawsze dobra rzecz rzućmy okiem na kod źródłowy (użyłem API 24 sources)

Wywołanie setTheme() na Activity wywoła initializeTheme() w klasie ContextThemeWrapper macierzystej, która będzie skończyć się nazywając onApplyThemeResource(..) który z kolei będzie próbował odczytać aktualne dane motyw z zasobów poprzez wywołanie theme.applyStyle(resId, true)

po łańcucha poprzez owinięcie Resources.Theme widzimy w ResourcesImpl.ThemeImpl następujące, w tutaj AssetManager nazywa się załadować styl do tematu:

void applyStyle(int resId, boolean force) { 
    synchronized (mKey) { 
     AssetManager.applyThemeStyle(mTheme, resId, force); 

     mThemeResId = resId; 
     mKey.append(resId, force); 
    } 
} 

tym miejscu można spróbować i nie załadować obcego motywu z innej aplikacji.


Ponieważ większość metod trzeba by użyć są statyczne wywołania lub pakiet metod lokalnych nie wydaje się, że istnieje jakiś sposób, aby osiągnąć to, co chcesz (np stosowaniu lub tworzeniu nowego tematu)

Nawet jeśli uzyskasz blokadę aplikacji innej aplikacji AssetManager, używając getAssets() w kontekście there is no accessible method to create or apply themes.

Jedynym sposobem na wykorzystanie zasobów innej aplikacji byłoby dodanie zasobów do twojego.

+0

Co powiesz na sharedUserId? Jeśli wstawię sharedUserId dla obu aplikacji i podpisuję się z tym samym certyfikatem, co by się stało? Próbowałem, ale bez powodzenia. Być może robię źle gdzieś w kodzie – Berkay92

1

Widzieliście to demo: Multiple Theme Material Design

Można to sprawdzić demo zmian Runtime motywu.

Mam nadzieję, że ci to pomoże.

+0

Pytanie o zmianę motywu z innego pakietu zainstalowanego na urządzeniu. Spowoduje to zmianę kompozycji aplikacji zgodnie z wcześniejszymi ustawieniami stylu bieżącego pakietu. Chociaż jest to zalecany sposób stosowania tematów, nie odpowiada na pytanie PO. –