Reputation: 1244
I am failing to implement a Theme-Selection in my Android App.
This question was asked before, but the solution - call application.setTheme(theme_id) before setContentView - does not work for me.
There are 2 themes defined in styles.xml:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<!-- second theme, hard coded colors for testing -->
<style name="DarkTheme" parent="Theme.AppCompat.DayNight">
<item name="colorPrimary">#ff0000</item>
<item name="colorPrimaryDark">#00ff00</item>
<item name="colorAccent">#0000ff</item>
</style>
Both themes can be used in AndroidManifest.xml:
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
or
<application
...
android:theme="@style/DarkTheme"
>
...
</application>
The result is as expected, the styles are different.
But the theme selection should be done by the user, so I tested the basic functionality by using android:theme="@style/AppTheme"
in the manifest and hard coding this:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// yes, the line appears in the log:
Log.d("MYAPP", "calling application.setTheme(R.style.DarkTheme)")
application.setTheme(R.style.DarkTheme)
setContentView(R.layout.activity_main)
}
}
The result: the theme defined in AndroidManifest.xml is still used, the setTheme call has no effect.
No compile warnings, no runtime messages, no suspicious log entries.
Kotlin is used, but this shouldn't be the cause of the problem.
Upvotes: 2
Views: 2628
Reputation: 1244
Finally I managed to get it work.
To be clear: the code I posted first:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
application.setTheme(R.style.DarkTheme)
setContentView(R.layout.activity_main)
}
}
should work, according to many answers to similar questions on SO.
But it doesn't.
Also this:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
application.setTheme(R.style.DarkTheme)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
or other permutations in the sequence of the function calls doesn't solve the problem.
Not a real solution, but a workaround for the problem is the answer from Björn Kechel, found here: Change Activity's theme programmatically
Overwriting the getTheme method in Activity, instead of calling the none functional setTheme method:
class MainActivity : AppCompatActivity() {
protected var selectedTheme : String = ""
lateinit protected var sharedPreferences : SharedPreferences
var initialized = false
fun init() {
if (!initialized) {
initialized = true
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
}
if ("" == selectedTheme) {
selectedTheme = sharedPreferences.getString("selected_theme", "AppTheme")
}
}
override fun getTheme(): Resources.Theme {
init()
val theme = super.getTheme()
when(selectedTheme) {
"DarkTheme" -> {
theme.applyStyle(R.style.DarkTheme, true)
}
"AppTheme" -> {
theme.applyStyle(R.style.AppTheme, true)
}
}
return theme
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
settings.setOnClickListener {
openSettings()
}
}
fun openSettings() {
val intent = Intent(baseContext, SettingsActivity::class.java)
startActivity(intent)
}
}
Upvotes: 1