2
0
mirror of https://github.com/KDE/kdeconnect-android synced 2025-08-29 21:27:40 +00:00

New way to support dark theme to improve integration with system

This commit is contained in:
Anjani Kumar 2020-05-11 23:07:25 +00:00 committed by Nicolas Fella
parent e315cbd9ef
commit c318d60916
24 changed files with 105 additions and 144 deletions

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/primary" android:state_checked="true" />
<item android:drawable="@color/darkStatusBarBackground" android:state_checked="false" />
</selector>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="primaryDark">#333333</color>
<color name="darkGrey">#555555</color>
<color name="darkToolbarBackground">#222222</color>
<color name="darkStatusBarBackground">#333333</color>
<color name="on_secondary">@android:color/black</color>
<color name="on_high_contrast">@android:color/white</color>
<color name="text_color_primary">@android:color/white</color>
<color name="text_color">@android:color/white</color>
<color name="toolbar_color">#222222</color>
<!-- This is for dark theme. In dark theme both selected and unselected text in the
navigation bar should be white. This is different from the light theme as both states have
different colors so light theme has a selector for this value-->
<color name="state_list_drawer_text">@android:color/white</color>
</resources>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="KdeConnectTheme.Dark" parent="KdeConnectThemeBase.Dark">
<item name="android:colorEdgeEffect">@color/darkGrey</item>
</style>
<style name="KdeConnectTheme.Dark.NoActionBar" parent="KdeConnectThemeBase.Dark.NoActionBar">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:colorEdgeEffect">@color/darkGrey</item>
<item name="android:navigationBarColor">@android:color/black</item>
</style>
</resources>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="theme_list">
<item>System Default</item>
<item>Light</item>
<item>Dark</item>
</string-array>
</resources>

12
res/values/colors.xml Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="primary">#F67400</color>
<color name="primaryDark">#BD5900</color>
<color name="accent">#4ebffa</color>
<color name="disabled_grey">#EEEEEE</color>
<color name="on_secondary">@android:color/white</color>
<color name="on_high_contrast">@android:color/black</color>
<color name="text_color_primary">@android:color/black</color>
<color name="text_color">@android:color/black</color>
<color name="toolbar_color">#F67400</color>
</resources>

View File

@ -368,4 +368,17 @@
<string name="bigscreen_down">Down</string>
<string name="pref_plugin_bigscreen">Bigscreen remote</string>
<string name="pref_plugin_bigscreen_desc">Use your device as a remote for Plasma Bigscreen</string>
<string name="theme_dialog_title">Choose theme</string>
<string-array name="theme_list">
<item>Set by Battery Saver</item>
<item>Light</item>
<item>Dark</item>
</string-array>
<string-array name="theme_list_values" translatable="false">
<item>default</item>
<item>light</item>
<item>dark</item>
</string-array>
</resources>

View File

@ -1,43 +0,0 @@
<resources>
<color name="darkGrey">#555555</color>
<color name="darkToolbarBackground">#222222</color>
<color name="darkStatusBarBackground">#333333</color>
<!-- KdeConnectThemeBase styles must only be defined in the main res/values/ folder -->
<style name="KdeConnectThemeBase.Dark" parent="Theme.MaterialComponents">
<item name="colorPrimary">@color/primary</item>
<item name="colorPrimaryDark">@color/darkStatusBarBackground</item>
<item name="colorSecondary">@color/primary</item>
<item name="colorOnSecondary">@android:color/black</item>
<item name="colorAccent">@color/accent</item>
<item name="android:windowBackground">@android:color/black</item>
<item name="toolbarStyle">@style/KdeConnectTheme.Toolbar.Dark</item>
<item name="popupTheme">@style/ThemeOverlay.AppCompat</item>
<item name="mainNavigationViewStyle">@style/MainNavigationView.Dark</item>
<item name="colorHighContrast">@android:color/white</item>
<item name="android:textColorPrimary">@android:color/white</item>
<item name="android:textColor">@android:color/white</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
</style>
<style name="KdeConnectThemeBase.Dark.NoActionBar" parent="KdeConnectThemeBase.Dark">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<!-- KdeConnectTheme styles (without the 'Base' on the end) can be redefined in other 'values' folders. like res/values-v21/ -->
<style name="KdeConnectTheme.Toolbar.Dark">
<item name="android:background">@color/darkToolbarBackground</item>
</style>
<style name="KdeConnectTheme.Dark" parent="KdeConnectThemeBase.Dark" />
<style name="KdeConnectTheme.Dark.NoActionBar" parent="KdeConnectThemeBase.Dark.NoActionBar" />
<style name="MainNavigationView.Dark">
<item name="android:background">@drawable/state_list_drawer_background_dark</item>
<item name="itemBackground">@drawable/state_list_drawer_background_dark</item>
<item name="itemIconTint">@android:color/white</item>
<item name="itemTextColor">@android:color/white</item>
</style>
</resources>

View File

@ -1,24 +1,19 @@
<resources>
<color name="primary">#F67400</color>
<color name="primaryDark">#BD5900</color>
<color name="accent">#4ebffa</color>
<color name="disabled_grey">#EEEEEE</color>
<!-- NoActionBar because we use a Toolbar widget as ActionBar -->
<style name="KdeConnectThemeBase" parent="Theme.MaterialComponents.Light.DarkActionBar">
<style name="KdeConnectThemeBase" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- The three colors used by system widgets, according to https://chris.banes.me/2014/10/17/appcompat-v21/ -->
<item name="colorPrimary">@color/primary</item>
<item name="colorPrimaryDark">@color/primaryDark</item>
<item name="colorSecondary">@color/primary</item>
<item name="colorOnSecondary">@android:color/white</item>
<item name="colorOnSecondary">@color/on_secondary</item>
<item name="colorAccent">@color/accent</item>
<item name="toolbarStyle">@style/KdeConnectTheme.Toolbar</item>
<item name="popupTheme">@style/ThemeOverlay.AppCompat.Light</item>
<item name="popupTheme">@style/ThemeOverlay.AppCompat.DayNight</item>
<item name="mainNavigationViewStyle">@style/MainNavigationView</item>
<item name="colorHighContrast">@android:color/black</item>
<item name="colorHighContrast">@color/on_high_contrast</item>
<!-- TODO: The 2 items below change to much (eg snackbar text is now black, should be white) -->
<item name="android:textColorPrimary">@android:color/black</item>
<item name="android:textColor">@android:color/black</item>
<item name="android:textColorPrimary">@color/text_color_primary</item>
<item name="android:textColor">@color/text_color</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
<item name="actionModeStyle">@style/ActionModeStyle</item>
</style>
@ -31,7 +26,7 @@
<style name="KdeConnectTheme" parent="KdeConnectThemeBase" />
<style name="KdeConnectTheme.Toolbar" parent="Widget.AppCompat.Toolbar">
<item name="android:background">?attr/colorPrimary</item>
<item name="android:background">@color/toolbar_color</item>
</style>
<style name="KdeConnectTheme.NoActionBar" parent="KdeConnectThemeBase.NoActionBar" />

View File

@ -34,7 +34,6 @@ public class BigscreenActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ThemeUtil.setUserPreferredTheme(this);
setContentView(R.layout.activity_bigscreen);

View File

@ -40,7 +40,6 @@ public class FindMyPhoneActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ThemeUtil.setUserPreferredTheme(this);
setContentView(R.layout.activity_find_my_phone);
if (!getIntent().hasExtra(EXTRA_DEVICE_ID)) {

View File

@ -86,7 +86,6 @@ public class MousePadActivity extends AppCompatActivity implements GestureDetect
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ThemeUtil.setUserPreferredTheme(this);
setContentView(R.layout.activity_mousepad);

View File

@ -375,7 +375,6 @@ public class MprisActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ThemeUtil.setUserPreferredTheme(this);
setContentView(R.layout.activity_mpris);
ButterKnife.bind(this);

View File

@ -39,7 +39,6 @@ import android.widget.CheckedTextView;
import android.widget.ListView;
import org.kde.kdeconnect.BackgroundService;
import org.kde.kdeconnect.UserInterface.ThemeUtil;
import org.kde.kdeconnect_tp.R;
import java.util.Arrays;
@ -104,7 +103,6 @@ public class NotificationFilterActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ThemeUtil.setUserPreferredTheme(this);
setContentView(R.layout.activity_notification_filter);
appDatabase = new AppDatabase(NotificationFilterActivity.this, false);

View File

@ -37,7 +37,6 @@ import android.view.MotionEvent;
import android.view.View;
import org.kde.kdeconnect.BackgroundService;
import org.kde.kdeconnect.UserInterface.ThemeUtil;
import org.kde.kdeconnect_tp.R;
import androidx.appcompat.app.AppCompatActivity;
@ -93,7 +92,6 @@ public class PresenterActivity extends AppCompatActivity implements SensorEventL
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ThemeUtil.setUserPreferredTheme(this);
setContentView(R.layout.activity_presenter);

View File

@ -41,7 +41,6 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.kde.kdeconnect.BackgroundService;
import org.kde.kdeconnect.UserInterface.List.ListAdapter;
import org.kde.kdeconnect.UserInterface.ThemeUtil;
import org.kde.kdeconnect_tp.R;
import java.util.ArrayList;
@ -102,7 +101,6 @@ public class RunCommandActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ThemeUtil.setUserPreferredTheme(this);
setContentView(R.layout.activity_runcommand);
deviceId = getIntent().getStringExtra("deviceId");

View File

@ -30,7 +30,6 @@ import android.util.Log;
import android.widget.Toast;
import org.kde.kdeconnect.BackgroundService;
import org.kde.kdeconnect.UserInterface.ThemeUtil;
import org.kde.kdeconnect_tp.R;
import java.util.ArrayList;
@ -45,7 +44,6 @@ public class SendFileActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ThemeUtil.setUserPreferredTheme(this);
mDeviceId = getIntent().getStringExtra("deviceId");

View File

@ -32,7 +32,6 @@ import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.UserInterface.List.EntryItem;
import org.kde.kdeconnect.UserInterface.List.ListAdapter;
import org.kde.kdeconnect.UserInterface.List.SectionItem;
import org.kde.kdeconnect.UserInterface.ThemeUtil;
import org.kde.kdeconnect_tp.R;
import java.util.ArrayList;
@ -125,7 +124,6 @@ public class ShareActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ThemeUtil.setUserPreferredTheme(this);
setContentView(R.layout.devices_list);
ActionBar actionBar = getSupportActionBar();

View File

@ -47,7 +47,6 @@ public abstract class AppCompatPreferenceActivity extends PreferenceActivity {
getDelegate().installViewFactory();
getDelegate().onCreate(savedInstanceState);
// The superclass's onCreate() method calls setContentView, so this ThemeUtil call must be before that
ThemeUtil.setUserPreferredTheme(this);
super.onCreate(savedInstanceState);
}

View File

@ -74,7 +74,6 @@ public class CustomDevicesActivity extends AppCompatActivity implements CustomDe
@Override
protected void onCreate(Bundle savedInstanceState) {
ThemeUtil.setUserPreferredTheme(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_devices);

View File

@ -69,8 +69,6 @@ public class MainActivity extends AppCompatActivity implements SharedPreferences
@Override
protected void onCreate(Bundle savedInstanceState) {
// We need to set the theme before the call to 'super.onCreate' below
ThemeUtil.setUserPreferredTheme(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

View File

@ -44,7 +44,6 @@ public class PluginSettingsActivity
@Override
public void onCreate(Bundle savedInstanceState) {
ThemeUtil.setUserPreferredTheme(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_plugin_settings);

View File

@ -2,11 +2,10 @@ package org.kde.kdeconnect.UserInterface;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import androidx.preference.EditTextPreference;
@ -15,6 +14,7 @@ import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreferenceCompat;
import androidx.preference.TwoStatePreference;
import androidx.preference.ListPreference;
import com.google.android.material.snackbar.Snackbar;
@ -25,17 +25,13 @@ import org.kde.kdeconnect_tp.R;
public class SettingsFragment extends PreferenceFragmentCompat {
private MainActivity mainActivity;
private EditTextPreference renameDevice;
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
mainActivity = (MainActivity)getActivity();
Context context = getPreferenceManager().getContext();
PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(context);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
// Rename device
renameDevice = new EditTextPreference(context);
@ -54,7 +50,8 @@ public class SettingsFragment extends PreferenceFragmentCompat {
if (TextUtils.isEmpty(name)) {
if (getView() != null) {
Snackbar snackbar = Snackbar.make(getView(), R.string.invalid_device_name, Snackbar.LENGTH_LONG);
if (!prefs.getBoolean("darkTheme", false)) {
int currentTheme = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
if (currentTheme != Configuration.UI_MODE_NIGHT_YES) {
// white color is set to the background of snackbar if dark mode is off
snackbar.getView().setBackgroundColor(Color.WHITE);
}
@ -69,23 +66,21 @@ public class SettingsFragment extends PreferenceFragmentCompat {
screen.addPreference(renameDevice);
// Dark mode
final TwoStatePreference darkThemeSwitch = new SwitchPreferenceCompat(context);
darkThemeSwitch.setPersistent(false);
darkThemeSwitch.setChecked(ThemeUtil.shouldUseDarkTheme(context));
darkThemeSwitch.setTitle(R.string.settings_dark_mode);
darkThemeSwitch.setOnPreferenceChangeListener((preference, newValue) -> {
boolean isChecked = (Boolean)newValue;
boolean isDarkAlready = prefs.getBoolean("darkTheme", false);
if (isDarkAlready != isChecked) {
prefs.edit().putBoolean("darkTheme", isChecked).apply();
if (mainActivity != null) {
mainActivity.recreate();
}
}
return true;
// Theme Selector
ListPreference themeSelector = new ListPreference(context);
themeSelector.setKey("theme_pref");
themeSelector.setTitle(R.string.theme_dialog_title);
themeSelector.setDialogTitle(R.string.theme_dialog_title);
themeSelector.setEntries(R.array.theme_list);
themeSelector.setEntryValues(R.array.theme_list_values);
themeSelector.setDefaultValue("default");
themeSelector.setSummaryProvider(ListPreference.SimpleSummaryProvider.getInstance());
themeSelector.setOnPreferenceChangeListener((preference, newValue) -> {
String themeValue = (String) newValue;
ThemeUtil.applyTheme(themeValue);
return true;
});
screen.addPreference(darkThemeSwitch);
screen.addPreference(themeSelector);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

View File

@ -1,46 +1,38 @@
package org.kde.kdeconnect.UserInterface;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatDelegate;
import org.kde.kdeconnect_tp.R;
/**
* Utilities for working with android {@link android.content.res.Resources.Theme Themes}.
*/
public class ThemeUtil {
/**
* This method should be called from the {@code activity}'s onCreate method, before
* any calls to {@link Activity#setContentView} or
* {@link android.preference.PreferenceActivity#setPreferenceScreen}.
*
* @param activity any Activity on screen
*/
public static void setUserPreferredTheme(Activity activity) {
boolean useDarkTheme = shouldUseDarkTheme(activity);
public static final String LIGHT_MODE = "light";
public static final String DARK_MODE = "dark";
public static final String DEFAULT_MODE = "default";
// Only MainActivity sets its own Toolbar as the ActionBar.
boolean usesOwnActionBar = activity instanceof MainActivity;
if (useDarkTheme) {
activity.setTheme(usesOwnActionBar ? R.style.KdeConnectTheme_Dark_NoActionBar : R.style.KdeConnectTheme_Dark);
} else {
activity.setTheme(usesOwnActionBar ? R.style.KdeConnectTheme_NoActionBar : R.style.KdeConnectTheme);
public static void applyTheme(@NonNull String themePref) {
switch (themePref) {
case LIGHT_MODE: {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
break;
}
case DARK_MODE: {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
break;
}
default: {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY);
}
break;
}
}
}
/**
* Checks {@link SharedPreferences} to figure out whether we should use the light
* theme or the dark theme. The app defaults to light theme.
*
* @param context any active context (Activity, Service, Application, etc.)
* @return true if the dark theme should be active, false otherwise
*/
public static boolean shouldUseDarkTheme(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getBoolean("darkTheme", false);
}
}

View File

@ -44,7 +44,6 @@ public class TrustedNetworksActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
ThemeUtil.setUserPreferredTheme(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.trusted_network_list);
trustedNetworksView = findViewById(android.R.id.list);