From ede05f208ba0fdcd9964b975857b2f216a35111f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gergely=20K=C5=91r=C3=B6ssy?= Date: Thu, 26 Oct 2017 01:10:03 +0200 Subject: [PATCH 1/6] PreferenceCategory's text color can be set from XML and programmatically too --- app/src/main/res/xml/settings.xml | 6 ++-- .../v7/preference/PreferenceCategory.java | 33 ++++++++++++++++--- preference-v7/src/main/res/values/attrs.xml | 4 +++ 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml index 60d22c2..3e8c6c3 100644 --- a/app/src/main/res/xml/settings.xml +++ b/app/src/main/res/xml/settings.xml @@ -39,9 +39,9 @@ android:title="SeekBarPreference" app:showSeekBarValue="false" /> - - - + 0 && typedArray.getIndexCount() > 0) { final int accentColor = typedArray.getColor(typedArray.getIndex(0), 0xff4081); // defaults to pink - titleView.setTextColor(accentColor); + titleView.setTextColor(color == 0 ? accentColor : color); final int marginIdx = typedArray.getIndex(1); final TypedValue marginValue = typedArray.peekValue(marginIdx); diff --git a/preference-v7/src/main/res/values/attrs.xml b/preference-v7/src/main/res/values/attrs.xml index 5b361f4..df5c409 100644 --- a/preference-v7/src/main/res/values/attrs.xml +++ b/preference-v7/src/main/res/values/attrs.xml @@ -4,4 +4,8 @@ + + + + \ No newline at end of file From cce3f03a220fb9eca01abfe39b48633e780f76c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gergely=20K=C5=91r=C3=B6ssy?= Date: Thu, 26 Oct 2017 01:47:48 +0200 Subject: [PATCH 2/6] Added PreferenceActivityResultListener that can be used for starting an Activity for result; added ActivityResultTestPreference for PreferenceActivityResultListener testing; changed the name of "addDialogPreference" to "registerPreferenceFragment" in PreferenceFragmentCompat --- .../ActivityResultTestPreference.java | 49 +++++++++ app/src/main/res/xml/settings.xml | 6 +- .../v7/preference/ColorPickerPreference.java | 2 +- .../v7/preference/DatePickerPreference.java | 2 +- .../v7/preference/TimePickerPreference.java | 2 +- .../v7/preference/RingtonePreference.java | 2 +- .../PreferenceActivityResultListener.java | 33 +++++++ .../preference/PreferenceFragmentCompat.java | 99 ++++++++++++++++--- 8 files changed, 179 insertions(+), 16 deletions(-) create mode 100644 app/src/main/java/com/takisoft/preferencefix/ActivityResultTestPreference.java create mode 100644 preference-v7/src/main/java/com/takisoft/fix/support/v7/preference/PreferenceActivityResultListener.java diff --git a/app/src/main/java/com/takisoft/preferencefix/ActivityResultTestPreference.java b/app/src/main/java/com/takisoft/preferencefix/ActivityResultTestPreference.java new file mode 100644 index 0000000..4d2cab4 --- /dev/null +++ b/app/src/main/java/com/takisoft/preferencefix/ActivityResultTestPreference.java @@ -0,0 +1,49 @@ +package com.takisoft.preferencefix; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v7.preference.Preference; +import android.util.AttributeSet; +import android.widget.Toast; + +import com.takisoft.fix.support.v7.preference.PreferenceActivityResultListener; +import com.takisoft.fix.support.v7.preference.PreferenceFragmentCompat; + +public class ActivityResultTestPreference extends Preference implements PreferenceActivityResultListener { + public static final int RC_GET_CONTENT = 3462; + + public ActivityResultTestPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + public ActivityResultTestPreference(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public ActivityResultTestPreference(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public ActivityResultTestPreference(Context context) { + super(context); + } + + @Override + public void onPreferenceClick(@NonNull PreferenceFragmentCompat fragment, @NonNull Preference preference) { + Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.setType("*/*"); + intent.addCategory(Intent.CATEGORY_OPENABLE); + + fragment.startActivityForResult(intent, RC_GET_CONTENT); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + if (requestCode == RC_GET_CONTENT && resultCode == Activity.RESULT_OK && data != null) { + Toast.makeText(getContext(), data.getDataString(), Toast.LENGTH_LONG).show(); + } + } +} diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml index 3e8c6c3..bb8a79e 100644 --- a/app/src/main/res/xml/settings.xml +++ b/app/src/main/res/xml/settings.xml @@ -41,7 +41,11 @@ + app:pref_categoryColor="#2196f3"> + + resultCode will be + * {@link Activity#RESULT_CANCELED} if the activity explicitly returned that, + * didn't return any result, or crashed during its operation. + * + * @param requestCode The integer request code originally supplied to startActivityForResult(), allowing you to identify who this result came from. + * @param resultCode The integer result code returned by the child activity through its setResult(). + * @param data An Intent, which can return result data to the caller (various data can be attached to Intent "extras"). + */ + void onActivityResult(int requestCode, int resultCode, @Nullable Intent data); +} diff --git a/preference-v7/src/main/java/com/takisoft/fix/support/v7/preference/PreferenceFragmentCompat.java b/preference-v7/src/main/java/com/takisoft/fix/support/v7/preference/PreferenceFragmentCompat.java index 0983c8a..a969219 100644 --- a/preference-v7/src/main/java/com/takisoft/fix/support/v7/preference/PreferenceFragmentCompat.java +++ b/preference-v7/src/main/java/com/takisoft/fix/support/v7/preference/PreferenceFragmentCompat.java @@ -1,13 +1,15 @@ package com.takisoft.fix.support.v7.preference; import android.content.Context; +import android.content.Intent; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.DialogFragment; import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentTransaction; import android.support.v7.preference.DialogPreference; import android.support.v7.preference.Preference; -import android.support.v7.preference.PreferenceDialogFragmentCompat; +import android.support.v7.preference.PreferenceGroup; import android.support.v7.preference.PreferenceManager; import android.support.v7.preference.PreferenceManagerFix; import android.support.v7.preference.PreferenceScreen; @@ -62,8 +64,10 @@ protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen } /** - * @param savedInstanceState If the fragment is being re-created from a previous saved state, this is the state. - * @param rootKey If non-null, this preference fragment should be rooted at the PreferenceScreen with this key. + * @param savedInstanceState If the fragment is being re-created from a previous saved state, + * this is the state. + * @param rootKey If non-null, this preference fragment should be rooted at the + * PreferenceScreen with this key. * @deprecated Use {@link #onCreatePreferencesFix(Bundle, String)} instead. */ @Override @@ -73,10 +77,14 @@ public void onCreatePreferences(@Nullable Bundle savedInstanceState, String root } /** - * Called during onCreate(Bundle) to supply the preferences for this fragment. Subclasses are expected to call setPreferenceScreen(PreferenceScreen) either directly or via helper methods such as addPreferencesFromResource(int). + * Called during onCreate(Bundle) to supply the preferences for this fragment. Subclasses are + * expected to call setPreferenceScreen(PreferenceScreen) either directly or via helper methods + * such as addPreferencesFromResource(int). * - * @param savedInstanceState If the fragment is being re-created from a previous saved state, this is the state. - * @param rootKey If non-null, this preference fragment should be rooted at the PreferenceScreen with this key. + * @param savedInstanceState If the fragment is being re-created from a previous saved state, + * this is the state. + * @param rootKey If non-null, this preference fragment should be rooted at the + * PreferenceScreen with this key. */ public abstract void onCreatePreferencesFix(@Nullable Bundle savedInstanceState, String rootKey); @@ -106,15 +114,84 @@ public void onDisplayPreferenceDialog(Preference preference) { } if (f != null) { - ((DialogFragment) f).setTargetFragment(this, 0); - ((DialogFragment) f).show(this.getFragmentManager(), FRAGMENT_DIALOG_TAG); + if (f instanceof DialogFragment) { + ((DialogFragment) f).setTargetFragment(this, 0); + ((DialogFragment) f).show(this.getFragmentManager(), FRAGMENT_DIALOG_TAG); + } else { + this.getFragmentManager() + .beginTransaction() + .add((Fragment) f, FRAGMENT_DIALOG_TAG) + .commit(); + } } } } - private static HashMap, Class> dialogPreferences = new HashMap<>(); + @Override + public boolean onPreferenceTreeClick(Preference preference) { + boolean handled = super.onPreferenceTreeClick(preference); + + if (!handled && preference instanceof PreferenceActivityResultListener) { + ((PreferenceActivityResultListener) preference).onPreferenceClick(this, preference); + } + + return handled; + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + onActivityResult(getPreferenceScreen(), requestCode, resultCode, data); + super.onActivityResult(requestCode, resultCode, data); + } - public static void addDialogPreference(Class dialogPrefClass, Class dialogFragmentClass) { - dialogPreferences.put(dialogPrefClass, dialogFragmentClass); + /** + * Traverses a {@code PreferenceGroup} to notify all eligible preferences about the results + * of a returning activity. + * + * @param group The {@code PreferenceGroup} to traverse. + * @param requestCode The integer request code originally supplied to startActivityForResult(), allowing you to identify who this result came from. + * @param resultCode The integer result code returned by the child activity through its setResult(). + * @param data An Intent, which can return result data to the caller (various data can be attached to Intent "extras"). + */ + protected void onActivityResult(PreferenceGroup group, int requestCode, int resultCode, Intent data) { + final int n = group.getPreferenceCount(); + + for (int i = 0; i < n; i++) { + Preference pref = group.getPreference(i); + if (pref instanceof PreferenceActivityResultListener) { + ((PreferenceActivityResultListener) pref).onActivityResult(requestCode, resultCode, data); + } + + if (pref instanceof PreferenceGroup) { + onActivityResult((PreferenceGroup) pref, requestCode, resultCode, data); + } + } + } + + protected static HashMap, Class> dialogPreferences = new HashMap<>(); + + /** + * Sets a {@link Preference} to use the supplied {@link Fragment} as a dialog. + *

+ * NOTE + * If prefClass is not a subclass of {@link DialogPreference}, you must call + * {@link PreferenceManager#showDialog(Preference)} to execute the dialog showing logic when the + * user clicks on the preference. + *

+ * WARNING + * If fragmentClass is not a subclass of {@link DialogFragment}, the fragment will be + * added to the fragment manager with the tag {@link #FRAGMENT_DIALOG_TAG} and using + * {@link FragmentTransaction#commit()}. You must ensure that the fragment is removed from the + * manager when it's done with its work. + * If you want to handle how the fragment is being added to the manager, implement + * {@link PreferenceActivityResultListener} instead and use the fragment from + * {@link PreferenceActivityResultListener#onPreferenceClick(PreferenceFragmentCompat, Preference)} + * to add it manually. + * + * @param prefClass the {@link Preference} class to be used + * @param fragmentClass the {@link Preference} class to be instantiated and displayed / added + */ + public static void registerPreferenceFragment(Class prefClass, Class fragmentClass) { + dialogPreferences.put(prefClass, fragmentClass); } } From 9cee1b0694fbb53546f804951f709451376ee636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gergely=20K=C5=91r=C3=B6ssy?= Date: Thu, 26 Oct 2017 01:49:36 +0200 Subject: [PATCH 3/6] Gradle updates - support lib v27.0.0 and gradle plugin update to 3.0.0 from 3.0.0-rc2 --- build.gradle | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 0ccd7a7..20ff5c3 100644 --- a/build.gradle +++ b/build.gradle @@ -2,10 +2,10 @@ project.ext.buildToolsVersion = '26.0.2' project.ext.minSdkVersion = 14 project.ext.sdkVersion = 26 -project.ext.supportLibraryVersion = '26.1.0' -project.ext.supportLibraryVersionPrefix = '26.1.0' +project.ext.supportLibraryVersion = '27.0.0' +project.ext.supportLibraryVersionPrefix = '27.0.0' project.ext.supportLibraryVersionSuffix = '' -project.ext.fixLibraryVersion = '3' +project.ext.fixLibraryVersion = '0' project.ext.extrasLibraryVersionSuffix = '' @@ -15,7 +15,7 @@ buildscript { maven { url "https://maven.google.com" } } dependencies { - classpath 'com.android.tools.build:gradle:3.0.0-rc2' + classpath 'com.android.tools.build:gradle:3.0.0' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3' classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0' From dbd61c59e39dc82abb3ac6e35437278f48b1caec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gergely=20K=C5=91r=C3=B6ssy?= Date: Fri, 27 Oct 2017 06:48:42 +0200 Subject: [PATCH 4/6] Enabled scrollbars on the preference list --- preference-v7/src/main/res/values/styles.xml | 25 ++++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/preference-v7/src/main/res/values/styles.xml b/preference-v7/src/main/res/values/styles.xml index 7b855d9..d81e21c 100644 --- a/preference-v7/src/main/res/values/styles.xml +++ b/preference-v7/src/main/res/values/styles.xml @@ -2,7 +2,8 @@ - + + From 6bc1c691ea3e23f9a6a5db644ad1d362d62f80f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gergely=20K=C5=91r=C3=B6ssy?= Date: Fri, 27 Oct 2017 06:58:11 +0200 Subject: [PATCH 5/6] README and CHANGELOG updates to 27.0.0 related release; PreferenceActivityResultListener's javadoc updated --- CHANGELOG.md | 8 ++++++ README.md | 26 ++++++++++++------- .../PreferenceActivityResultListener.java | 6 ++++- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38f720b..de9d34a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +**2017-10-27** + +New version: 27.0.0.0 (based on v27.0.0) + +- `PreferenceCategory`'s text color can be set from code (`setColor(...)` or `setColorResource(...)`) and XML (`app:pref_categoryColor` attribute) +- Added `PreferenceActivityResultListener` that can be used for handling click events by starting an `Activity` for result and receiving the results +- Enabled scrollbars on the preference list + **2017-10-24** New version: 26.1.0.3 (based on v26.1.0) diff --git a/README.md b/README.md index 02cdafc..3931b08 100644 --- a/README.md +++ b/README.md @@ -18,12 +18,12 @@ If you would like to support me, you may donate some small amount via PayPal. ### 1. Add gradle dependency First, **remove** the unnecessary lines of preference-v7 and preference-v14 from your gradle file as the bugfix contains both of them: ```gradle -compile 'com.android.support:preference-v7:26.1.0' -compile 'com.android.support:preference-v14:26.1.0' +compile 'com.android.support:preference-v7:27.0.0' +compile 'com.android.support:preference-v14:27.0.0' ``` And **add** this single line to your gradle file: ```gradle -compile 'com.takisoft.fix:preference-v7:26.1.0.3' +compile 'com.takisoft.fix:preference-v7:27.0.0.0' ``` > Notice the versioning: the first three numbers are *always* the same as the latest official library while the last number is for own updates. I try to keep it up-to-date but if, for whatever reasons, I wouldn't notice the new support library versions, just issue a ticket. @@ -92,17 +92,17 @@ Now you can enjoy using the support preferences API without losing all your hair There are additional preferences not part of the official support library, but decided to add them to some extra libraries. You can add all of them to your project using ```gradle -compile 'com.takisoft.fix:preference-v7-extras:26.1.0.3' +compile 'com.takisoft.fix:preference-v7-extras:27.0.0.0' ``` or one or more groups: Preference | Dependency | Preview -|-|- -[`RingtonePreference`](https://github.com/Gericop/Android-Support-Preference-V7-Fix/wiki/Preference-types#ringtonepreference) | `compile 'com.takisoft.fix:preference-v7-ringtone:26.1.0.3'` | ![API 15](https://raw.githubusercontent.com/Gericop/Android-Support-Preference-V7-Fix/master/images/ringtone_api26.png) -[`DatePickerPreference`](https://github.com/Gericop/Android-Support-Preference-V7-Fix/wiki/Preference-types#datepickerpreference) | `compile 'com.takisoft.fix:preference-v7-datetimepicker:26.1.0.3'` | ![API 15](https://raw.githubusercontent.com/Gericop/Android-Support-Preference-V7-Fix/master/images/datepicker_api26.png) -[`TimePickerPreference`](https://github.com/Gericop/Android-Support-Preference-V7-Fix/wiki/Preference-types#timepickerpreference) | `compile 'com.takisoft.fix:preference-v7-datetimepicker:26.1.0.3'` | ![API 15](https://raw.githubusercontent.com/Gericop/Android-Support-Preference-V7-Fix/master/images/timepicker_api26.png) -[`ColorPickerPreference`](https://github.com/Gericop/Android-Support-Preference-V7-Fix/wiki/Preference-types#colorpickerpreference) | `compile 'com.takisoft.fix:preference-v7-colorpicker:26.1.0.3'` | ![API 15](https://raw.githubusercontent.com/Gericop/Android-Support-Preference-V7-Fix/master/images/colorpicker_api26_fixed.png) +[`RingtonePreference`](https://github.com/Gericop/Android-Support-Preference-V7-Fix/wiki/Preference-types#ringtonepreference) | `compile 'com.takisoft.fix:preference-v7-ringtone:27.0.0.0'` | ![API 15](https://raw.githubusercontent.com/Gericop/Android-Support-Preference-V7-Fix/master/images/ringtone_api26.png) +[`DatePickerPreference`](https://github.com/Gericop/Android-Support-Preference-V7-Fix/wiki/Preference-types#datepickerpreference) | `compile 'com.takisoft.fix:preference-v7-datetimepicker:27.0.0.0'` | ![API 15](https://raw.githubusercontent.com/Gericop/Android-Support-Preference-V7-Fix/master/images/datepicker_api26.png) +[`TimePickerPreference`](https://github.com/Gericop/Android-Support-Preference-V7-Fix/wiki/Preference-types#timepickerpreference) | `compile 'com.takisoft.fix:preference-v7-datetimepicker:27.0.0.0'` | ![API 15](https://raw.githubusercontent.com/Gericop/Android-Support-Preference-V7-Fix/master/images/timepicker_api26.png) +[`ColorPickerPreference`](https://github.com/Gericop/Android-Support-Preference-V7-Fix/wiki/Preference-types#colorpickerpreference) | `compile 'com.takisoft.fix:preference-v7-colorpicker:27.0.0.0'` | ![API 15](https://raw.githubusercontent.com/Gericop/Android-Support-Preference-V7-Fix/master/images/colorpicker_api26_fixed.png) --- @@ -148,7 +148,7 @@ The original implementation uses `?attr/textAppearanceSmall` as the message styl --- ## Version -The current stable version is **26.1.0.3**. +The current stable version is **27.0.0.0**. ## Notes # This demo / bugfix is set to work on API level 14+. @@ -167,6 +167,14 @@ API 15 | API 21 | API 26 ### Changelog +**2017-10-27** + +New version: 27.0.0.0 (based on v27.0.0) + +- `PreferenceCategory`'s text color can be set from code (`setColor(...)` or `setColorResource(...)`) and XML (`app:pref_categoryColor` attribute) +- Added `PreferenceActivityResultListener` that can be used for handling click events by starting an `Activity` for result and receiving the results +- Enabled scrollbars on the preference list + **2017-10-24** New version: 26.1.0.3 (based on v26.1.0) diff --git a/preference-v7/src/main/java/com/takisoft/fix/support/v7/preference/PreferenceActivityResultListener.java b/preference-v7/src/main/java/com/takisoft/fix/support/v7/preference/PreferenceActivityResultListener.java index d596eb9..0014685 100644 --- a/preference-v7/src/main/java/com/takisoft/fix/support/v7/preference/PreferenceActivityResultListener.java +++ b/preference-v7/src/main/java/com/takisoft/fix/support/v7/preference/PreferenceActivityResultListener.java @@ -4,10 +4,14 @@ import android.content.Intent; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; import android.support.v7.preference.Preference; /** - * + * An interface for custom preferences that want to handle click events by either starting an + * {@link Activity} for results calling {@link Fragment#startActivityForResult(Intent, int)} or + * using the supplied {@link PreferenceFragmentCompat} fragment manually (e.g. adding a fragment to + * it). */ public interface PreferenceActivityResultListener { /** From 8fce45f5f73d893285ca0b83cfd4cb3b5b5c48b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gergely=20K=C5=91r=C3=B6ssy?= Date: Fri, 27 Oct 2017 07:01:50 +0200 Subject: [PATCH 6/6] Gradle build tools and SDK version update --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 20ff5c3..f065604 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. -project.ext.buildToolsVersion = '26.0.2' +project.ext.buildToolsVersion = '27.0.0' project.ext.minSdkVersion = 14 -project.ext.sdkVersion = 26 +project.ext.sdkVersion = 27 project.ext.supportLibraryVersion = '27.0.0' project.ext.supportLibraryVersionPrefix = '27.0.0' project.ext.supportLibraryVersionSuffix = ''