Upgrade the SettingsActivity to the PreferenceFragmentCompat.

Old SettingsActivity was deleted and replaced.
This upgrade fixes the bugs with DarkMode.
This commit is contained in:
ErikWaegerle 2020-08-20 19:29:17 +02:00
parent c6371e700f
commit 5fd14d86dc
6 changed files with 127 additions and 271 deletions

View file

@ -33,6 +33,7 @@ android {
dependencies { dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs') implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.preference:preference:1.1.0-rc01'
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
implementation 'androidx.core:core:1.2.0' implementation 'androidx.core:core:1.2.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0'

View file

@ -2,15 +2,18 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.secuso.privacyfriendlysudoku.ui.view"> package="org.secuso.privacyfriendlysudoku.ui.view">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application <application
android:name="org.secuso.privacyfriendlysudoku.SudokuApp"
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme" android:theme="@style/AppTheme">
android:name="org.secuso.privacyfriendlysudoku.SudokuApp"> <activity
android:name=".SettingsActivity"
android:label="@string/title_activity_settings_new"></activity>
<activity <activity
android:name="org.secuso.privacyfriendlysudoku.ui.SplashActivity" android:name="org.secuso.privacyfriendlysudoku.ui.SplashActivity"
android:theme="@style/SplashTheme"> android:theme="@style/SplashTheme">
@ -23,23 +26,19 @@
<activity <activity
android:name="org.secuso.privacyfriendlysudoku.ui.MainActivity" android:name="org.secuso.privacyfriendlysudoku.ui.MainActivity"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar"> android:theme="@style/AppTheme.NoActionBar"></activity>
</activity>
<activity <activity
android:name="org.secuso.privacyfriendlysudoku.ui.TutorialActivity" android:name="org.secuso.privacyfriendlysudoku.ui.TutorialActivity"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar"> android:theme="@style/AppTheme.NoActionBar"></activity>
</activity>
<activity <activity
android:name="org.secuso.privacyfriendlysudoku.ui.DailySudokuActivity" android:name="org.secuso.privacyfriendlysudoku.ui.DailySudokuActivity"
android:label="@string/Sudoku" android:label="@string/Sudoku"
android:theme="@style/AppTheme.NoActionBar"> android:theme="@style/AppTheme.NoActionBar"></activity>
</activity>
<activity <activity
android:name="org.secuso.privacyfriendlysudoku.ui.CreateSudokuActivity" android:name="org.secuso.privacyfriendlysudoku.ui.CreateSudokuActivity"
android:label="@string/Sudoku" android:label="@string/Sudoku"
android:theme="@style/AppTheme.NoActionBar"> android:theme="@style/AppTheme.NoActionBar"></activity>
</activity>
<activity <activity
android:name="org.secuso.privacyfriendlysudoku.ui.SettingsActivity" android:name="org.secuso.privacyfriendlysudoku.ui.SettingsActivity"
android:label="@string/title_activity_settings" android:label="@string/title_activity_settings"
@ -49,22 +48,24 @@
android:label="@string/title_activity_game_view" android:label="@string/title_activity_game_view"
android:launchMode="singleTask" android:launchMode="singleTask"
android:theme="@style/AppTheme.NoActionBar"> android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<intent-filter >
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http"
android:host="sudoku.secuso.org" /> <data
android:host="sudoku.secuso.org"
android:scheme="http" />
</intent-filter> </intent-filter>
<intent-filter>
<intent-filter >
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="sudoku.secuso.org" /> <data android:scheme="sudoku.secuso.org" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name="org.secuso.privacyfriendlysudoku.ui.AboutActivity" /> <activity android:name="org.secuso.privacyfriendlysudoku.ui.AboutActivity" />
<activity android:name="org.secuso.privacyfriendlysudoku.ui.LoadGameActivity" /> <activity android:name="org.secuso.privacyfriendlysudoku.ui.LoadGameActivity" />
@ -74,6 +75,7 @@
<activity <activity
android:name="org.secuso.privacyfriendlysudoku.ui.HelpActivity" android:name="org.secuso.privacyfriendlysudoku.ui.HelpActivity"
android:label="@string/title_activity_help" /> android:label="@string/title_activity_help" />
<service <service
android:name="org.secuso.privacyfriendlysudoku.controller.GeneratorService" android:name="org.secuso.privacyfriendlysudoku.controller.GeneratorService"
android:enabled="true" android:enabled="true"

View file

@ -1,109 +1,58 @@
/*
* qqwing - Sudoku solver and generator
* Copyright (C) 2014 Stephen Ostermiller
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.secuso.privacyfriendlysudoku.ui; package org.secuso.privacyfriendlysudoku.ui;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatDelegate;
import android.preference.PreferenceFragment; import android.preference.PreferenceFragment;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.Switch;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen;
import org.secuso.privacyfriendlysudoku.ui.SettingsActivity;
import org.secuso.privacyfriendlysudoku.ui.view.R; import org.secuso.privacyfriendlysudoku.ui.view.R;
import java.util.List; public class SettingsActivity extends AppCompatActivity {
import java.util.Map;
/**
* A {@link PreferenceActivity} that presents a set of application settings. On
* handset devices, settings are presented as a single list. On tablets,
* settings are split by category, with category headers shown to the left of
* the list of settings.
* <p>
* See <a href="http://developer.android.com/design/patterns/settings.html">
* Android Design: Settings</a> for design guidelines and the <a
* href="http://developer.android.com/guide/topics/ui/settings.html">Settings
* API Guide</a> for more information on developing a Settings UI.
*
* The SettingsActivity is extended by AppCompatPreferenceActivity
* The activity is responsible for the different app settings.
*/
public class SettingsActivity extends AppCompatPreferenceActivity { private static PreferenceScreen prefScreen;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setupActionBar();
overridePendingTransition(0, 0); private static void recheckNightModeProperties(SharedPreferences sharedPreferences) {
View mainContent = findViewById(R.id.main_content); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (mainContent != null) {
mainContent.setAlpha(0); if (sharedPreferences.getBoolean("pref_dark_mode_setting", false)) {
mainContent.animate().alpha(1).setDuration(BaseActivity.MAIN_CONTENT_FADEIN_DURATION); prefScreen.findPreference("pref_dark_mode_automatically_by_system").setEnabled(false);
prefScreen.findPreference("pref_dark_mode_automatically_by_battery").setEnabled(false);
} else {
if (sharedPreferences.getBoolean("pref_dark_mode_automatically_by_battery", false) && sharedPreferences.getBoolean("pref_dark_mode_automatically_by_system", false) ) {
sharedPreferences.edit().putBoolean("pref_dark_mode_automatically_by_battery", false).commit();
} }
/**
* Set up the {@link android.app.ActionBar}, if the API is available.
*/
SharedPreferences preferenceManager = PreferenceManager prefScreen.findPreference("pref_dark_mode_automatically_by_system").setEnabled(!sharedPreferences.getBoolean("pref_dark_mode_automatically_by_battery", false));
.getDefaultSharedPreferences(this); prefScreen.findPreference("pref_dark_mode_automatically_by_battery").setEnabled(!sharedPreferences.getBoolean("pref_dark_mode_automatically_by_system", false));
}}
SharedPreferences.OnSharedPreferenceChangeListener x = new SharedPreferences.OnSharedPreferenceChangeListener() {
/**
* Case differentiation for the different Night Mode options
* @param sharedPreferences
*/
public void recheckNightModeProperties(SharedPreferences sharedPreferences){
if (sharedPreferences.getBoolean("pref_dark_mode_setting", false )) { if (sharedPreferences.getBoolean("pref_dark_mode_setting", false )) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
restartActivity();
} else if (sharedPreferences.getBoolean("pref_dark_mode_automatically_by_system", false)) { } else if (sharedPreferences.getBoolean("pref_dark_mode_automatically_by_system", false)) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM); AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
restartActivity();
} else if(sharedPreferences.getBoolean("pref_dark_mode_automatically_by_battery", false)){ } else if(sharedPreferences.getBoolean("pref_dark_mode_automatically_by_battery", false)){
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY); AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY);
restartActivity();
} else { } else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
restartActivity(); }
} }
} static SharedPreferences.OnSharedPreferenceChangeListener x = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override @Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals("pref_dark_mode_setting")|| key.equals("pref_dark_mode_automatically_by_system")||key.equals("pref_dark_mode_automatically_by_battery")) { if (key.equals("pref_dark_mode_setting")|| key.equals("pref_dark_mode_automatically_by_system")||key.equals("pref_dark_mode_automatically_by_battery")) {
@ -111,179 +60,46 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
} }
} }
}; };
preferenceManager.registerOnSharedPreferenceChangeListener(x);
} @Override
protected void onCreate(Bundle savedInstanceState) {
/** super.onCreate(savedInstanceState);
* is responsible for closing and opening the activity setContentView(R.layout.settings_activity);
*/ getSupportFragmentManager()
public void restartActivity() { .beginTransaction()
Intent i = new Intent(getApplicationContext(), MainActivity.class); .replace(R.id.settings, new SettingsFragment())
recreate(); .commit();
finish();
startActivity(i);
}
private void setupActionBar () {
ActionBar actionBar = getSupportActionBar(); ActionBar actionBar = getSupportActionBar();
if (actionBar != null) { if (actionBar != null) {
// Show the Up button in the action bar.
actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setDisplayHomeAsUpEnabled(true);
} }
}
@Override SharedPreferences preferenceManager = PreferenceManager
public boolean onMenuItemSelected(int featureId, MenuItem item) { .getDefaultSharedPreferences(this);
int id = item.getItemId();
if (id == android.R.id.home) {
if (!super.onMenuItemSelected(featureId, item)) {
finish();
//NavUtils.navigateUpFromSameTask(this);
}
return true;
}
return super.onMenuItemSelected(featureId, item);
}
/** preferenceManager.registerOnSharedPreferenceChangeListener(x);
* {@inheritDoc}
*/
@Override
public boolean onIsMultiPane() {
return isXLargeTablet(this);
}
/**
* Helper method to determine if the device has an extra-large screen. For
* example, 10" tablets are extra-large.
*/
private static boolean isXLargeTablet(Context context) {
return (context.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
}
/**
* {@inheritDoc}
*/
@Override
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.pref_settings_headers, target);
}
/**
* A preference value change listener that updates the preference's summary
* to reflect its new value.
*/
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
if (preference instanceof ListPreference) {
// For list preferences, look up the correct display value in
// the preference's 'entries' list.
ListPreference listPreference = (ListPreference) preference;
int index = listPreference.findIndexOfValue(stringValue);
// Set the summary to reflect the new value.
preference.setSummary(
index >= 0
? listPreference.getEntries()[index]
: null);
} else {
// For all other preferences, set the summary to the value's
// simple string representation.
preference.setSummary(stringValue);
}
return true;
}
};
/**
* Binds a preference's summary to its value. More specifically, when the
* preference's value is changed, its summary (line of text below the
* preference title) is updated to reflect the value. The summary is also
* immediately updated upon calling this method. The exact display format is
* dependent on the type of preference.
*
* @see #sBindPreferenceSummaryToValueListener
*/
private static void bindPreferenceSummaryToValue(Preference preference) {
// Set the listener to watch for value changes.
preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
// Trigger the listener immediately with the preference's
// current value.
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
PreferenceManager
.getDefaultSharedPreferences(preference.getContext())
.getString(preference.getKey(), ""));
}
/**
* This method stops fragment injection in malicious applications.
* Make sure to deny any unknown fragments here.
*/
protected boolean isValidFragment(String fragmentName) {
return PreferenceFragment.class.getName().equals(fragmentName)
|| GamePreferenceFragment.class.getName().equals(fragmentName);
}
/**
* This fragment shows general preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class GamePreferenceFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_settings_general);
setHasOptionsMenu(true);
PreferenceManager preferenceManager = getPreferenceManager();
SharedPreferences sp = preferenceManager.getSharedPreferences();
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (sp.getBoolean("pref_dark_mode_setting", false)) {
//TwoStatePreference x = (TwoStatePreference) findPreference("pref_dark_mode_automatically_by_system");
//x.setEnabled(false);
findPreference("pref_dark_mode_automatically_by_system").setEnabled(false);
findPreference("pref_dark_mode_automatically_by_battery").setEnabled(false);
} else {
if (sp.getBoolean("pref_dark_mode_automatically_by_battery", false) && sp.getBoolean("pref_dark_mode_automatically_by_system", false) ) {
sp.edit().putBoolean("pref_dark_mode_automatically_by_battery", false).commit();
}
findPreference("pref_dark_mode_automatically_by_system").setEnabled(!sp.getBoolean("pref_dark_mode_automatically_by_battery", false));
findPreference("pref_dark_mode_automatically_by_battery").setEnabled(!sp.getBoolean("pref_dark_mode_automatically_by_system", false));
}
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
// to their values. When their values change, their summaries are
// updated to reflect the new value, per the Android Design
// guidelines.
//bindPreferenceSummaryToValue(findPreference("example_text"));
//bindPreferenceSummaryToValue(findPreference("example_list"));
}
} }
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId(); int id = item.getItemId();
if (id == android.R.id.home) { if (id == android.R.id.home) {
getActivity().finish(); finish();
//startActivity(new Intent(getActivity(), SettingsActivity.class));
return true; return true;
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
public static class SettingsFragment extends PreferenceFragmentCompat {
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.pref_settings_general, rootKey);
prefScreen = getPreferenceScreen();
SharedPreferences preferenceManager = PreferenceManager
.getDefaultSharedPreferences(getActivity());
recheckNightModeProperties(preferenceManager);
}
} }
} }

View file

@ -0,0 +1,9 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/settings"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

View file

@ -0,0 +1,12 @@
<resources>
<!-- Reply Preference -->
<string-array name="reply_entries">
<item>Reply</item>
<item>Reply to all</item>
</string-array>
<string-array name="reply_values">
<item>reply</item>
<item>reply_all</item>
</string-array>
</resources>

View file

@ -178,5 +178,21 @@
<string name="verify_custom_sudoku_process_toast">Verifying&#8230;</string> <string name="verify_custom_sudoku_process_toast">Verifying&#8230;</string>
<string name="finished_verifying_custom_sudoku_toast">Done verifying!</string> <string name="finished_verifying_custom_sudoku_toast">Done verifying!</string>
<string name="failed_to_verify_custom_sudoku_toast">Verification failed: Your sudoku cannot be solved.</string> <string name="failed_to_verify_custom_sudoku_toast">Verification failed: Your sudoku cannot be solved.</string>
<string name="title_activity_settings_new">Settings</string>
<!-- Preference Titles -->
<string name="messages_header">Messages</string>
<string name="sync_header">Sync</string>
<!-- Messages Preferences -->
<string name="signature_title">Your signature</string>
<string name="reply_title">Default reply action</string>
<!-- Sync Preferences -->
<string name="sync_title">Sync email periodically</string>
<string name="attachment_title">Download incoming attachments</string>
<string name="attachment_summary_on">Automatically download attachments for incoming emails
</string>
<string name="attachment_summary_off">Only download attachments when manually requested</string>
</resources> </resources>