2012-01-10 20 views
22

मैं उपयोगकर्ता को कुछ अलग विषयों के बीच चुनाव देना चाहता हूं, और सोच रहा था कि यह चीजों को करने का एक सही तरीका है या नहीं। मैंने इस विधि के साथ थोड़ा परीक्षण किया और यह काम किया, लेकिन मुझे लगता है कि बेहतर तरीके हो सकते हैं और सोच सकते हैं कि इससे बाद में कुछ समस्याएं हो सकती हैं, इसलिए पूछना चाहता था।विषय की उपयोगकर्ता पसंद को लागू करना

मैं प्रत्येक विषय के लिए एक अलग लेआउट बनाने और onCreate में setContentView() विधि के लिए स्विच करने के बारे में सोच रहा था। मैं पहले सहेजे गए SharedPreference मान (पूर्णांक) को लोड करता हूं और उस मान के आधार पर कि वह मान संबंधित लेआउट को प्रदर्शित करता था। स्पष्ट रूप से उपयोगकर्ता एक बटन या कुछ के साथ SharedPreference मान बदल सकता है।

चूंकि ये लेआउट मूल रूप से समान होंगे लेकिन विभिन्न रंगों के साथ, मैं अपने TextViews और प्रत्येक लेआउट फ़ाइल में अन्य दृश्यों के लिए एक ही आईडी का उपयोग करना चाहता हूं। मेरा मुख्य सवाल यह समस्या पैदा करेगा?

कोई कोड वाले टेक्स्ट की दीवार के लिए खेद है। मैं इस स्थिति के लिए अच्छा अभ्यास का एक सामान्य विचार प्राप्त करना चाहता हूं। अग्रिम में धन्यवाद।

उत्तर

37

मेरे पास वास्तव में मेरे एप्लिकेशन में यह सुविधा है और इसके अतिरिक्त, मैं उपयोगकर्ताओं को रनटाइम पर थीम बदलने की अनुमति देता हूं। वरीयताओं से मूल्य पढ़ने के रूप में कुछ समय लगता है, मुझे वैश्विक रूप से सुलभ फ़ंक्शन के माध्यम से थीम आईडी मिल रही है जिसमें कैश किए गए मान होते हैं।

जैसा कि पहले से ही बताया गया है - this guide का उपयोग करके कुछ एंड्रॉइड थीम बनाएं। आपके styles.xml फ़ाइल में आपके पास कम से कम दो <style> आइटम होंगे। उदाहरण के लिए:

<style name="Theme.App.Light" parent="@style/Theme.Light">...</style> 
<style name="Theme.App.Dark" parent="@style/Theme">...</style> 

अब, आपको इन गतिविधियों में से एक को अपनी गतिविधियों में लागू करना होगा। मैं activitie के onCreate विधि में यह कर रहा हूँ, किसी अन्य कॉल करने से पहले:

setTheme(MyApplication.getThemeId()); 

getThemeId एक तरीका है जिसके कैश्ड विषय आईडी रिटर्न है:

public static int getThemeId() 
{ 
    return themeId; 
} 

इस क्षेत्र किसी अन्य विधि के द्वारा अद्यतन किया जा रहा है:

public static void reloadTheme() 
{ 
    themeSetting = PreferenceManager.getDefaultSharedPreferences(context).getString("defaultTheme", "0"); 
    if(themeSetting.equals("0")) 
     themeId = R.style.Theme_Light; 
    else 
     themeId = R.style.Theme_Dark; 
} 

जब भी प्राथमिकताएं बदल दी जाती हैं (और, पाठ्यक्रम की शुरुआत पर) कहा जा रहा है। ये दो विधियां MyApplication कक्षा में रहती हैं, जो Application तक फैली हुई है। वरीयता परिवर्तन श्रोता इस पोस्ट के अंत में वर्णित है और मुख्य गतिविधि वर्ग में रहता है।

अंतिम और सुंदर महत्वपूर्ण बात - विषय लागू होने पर थीम लागू होती है। मान लीजिए, आप केवल वरीयता स्क्रीन में थीम बदल सकते हैं और वहां केवल एक ही तरीका है, यानी केवल एक (मुख्य) गतिविधि से, जब आप वरीयता स्क्रीन से बाहर निकलेंगे तो यह गतिविधि पुनरारंभ नहीं की जाएगी - पुरानी थीम अभी भी होगी उपयोग किया गया। यहाँ उस के लिए ठीक (आपका मुख्य गतिविधि पुन: प्रारंभ होता) है:

@Override 
protected void onResume() { 
    super.onResume(); 
    if(schduledRestart) 
    { 
     schduledRestart = false; 
     Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage(getBaseContext().getPackageName()); 
     i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
     startActivity(i); 
    } 
} 

scheduledRestart एक बूलियन चर, शुरू में गलत पर सेट है। यह जब विषय इस श्रोता, जो भी अपडेट हो जाता है कैश्ड विषय आईडी पहले उल्लेख द्वारा बदल दिया गया है सही पर सेट किया है:

private class themeListener implements OnSharedPreferenceChangeListener{ 

    @Override 
    public void onSharedPreferenceChanged(SharedPreferences spref, String key) { 
     if(key.equals("defaultTheme") && !spref.getString(key, "0").equals(MyApplication.getThemeSetting())) 
     { 
      MyApplication.reloadTheme(); 
      schduledRestart = true; 
     } 
    } 


sp = PreferenceManager.getDefaultSharedPreferences(this); 

listener = new themeListener(); 
sp.registerOnSharedPreferenceChangeListener(listener); 

श्रोता वस्तु के लिए एक संदर्भ पकड़ करने के लिए याद रखें, अन्यथा यह कचरा colleted (और काम करना बंद कर देगा हो जाएगा)। onCreate से पहले प्रत्येक गतिविधि के लिए

ContextThemeWrapper w = new ContextThemeWrapper(this, <newTHEMEId>); 
getTheme().setTo(w.getTheme()); 

:

+0

उत्कृष्ट जवाब, बहुत बहुत धन्यवाद! –

+0

मैंने सोचा कि मैं एप्लिकेशन को विस्तार किए बिना हल कर सकता हूं, लेकिन समस्या यह है कि 'getAplicationInfo()। थीम' अपडेट नहीं होता है अगर मैं' getAplication()। SetTheme (myThemeId) 'करता हूं ... तो हाँ, आपका तरीका सही है । – vault

+1

ऐसा लगता है कि इन दिनों किसी गतिविधि को पुनरारंभ करने का एक आसान तरीका है: 'recreate' (https://developer.android.com/reference/android/app/Activity.html#recreate%28%29)। – BlueMonkMN

2

यह काम करता है यदि आप इसे इस तरह से करते हैं, और मुझे नहीं लगता कि इससे कोई समस्या आएगी, लेकिन ऐसा लगता है कि यह बहुत परेशानी है (आपको अपने सभी लेआउट को उन सभी विषयों से गुणा करना है जिन्हें आप जोड़ना चाहते हैं यदि बाद में आप किसी लेआउट में संसाधन को संशोधित करना चाहते हैं, तो आपको इसे सभी विषयों में संशोधित करना होगा। आप निश्चित रूप से भूलना चाहते हैं)

एंड्रॉइड की Styles and Themes सुविधा का उपयोग क्यों नहीं कर रहे हैं?

वे आसानी से पूरी गतिविधि के लिए लागू किया जा सकता है:

<activity android:theme="@style/my_theme"> 

तो है कि जब आप SharedPreferences मूल्य में बदलाव का पता लगाने आप (एक प्राथमिकता गतिविधि पर बटन, या कुछ और) का उपयोग आप बस शैली बदल सकते हैं । या बेहतर, आप शैली को रनटाइम पर अपना वरीयता मान पढ़ने के लिए सेट कर सकते हैं (गतिविधि बनाते समय) और तदनुसार सही शैली/विषय लागू करें।

+0

मुझे स्टाइल और थीम्स फीचर के आसपास पढ़ा जाएगा और इस तरह से करने का प्रयास करें, जानकारी के लिए धन्यवाद। आपको एक घंटे में उखाड़ फेंक देगा क्योंकि मैंने कल उन्हें सब कुछ इस्तेमाल किया था: पी –

2

तुम भी गतिशील विषय का उपयोग कर बदल सकते हैं।

संबंधित मुद्दे