SwitchPreference in pre Android 7 always switched off - android

I'm extending PreferenceFragmentCompat, in the onCreatePreferences method the preference are set using addPreferencesFromResource(R.xml.preferences).
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<SwitchPreference
android:defaultValue="true"
android:key="disableAppWhenObscured"
android:title="#string/screen_settings_block_app_when_obscured" />
</PreferenceScreen>
As dependency I have the following entry:
implementation "androidx.preference:preference-ktx:1.0.0"
On devices post Android 6.X, everything works like expected. On devices with Android 6 and pre-6, the switches are always off and not changeable if clicked on it, even not changeable programmatically but the change listener gets fired.
You know what the problem is?
Edit: If I change the UI element to CheckBoxPreference, everything works as expected even in Android 6 and pre-6. Furthermore before I started using androidX the SwitchPreference worked as well.
Edit2: Found out that the switchView is null inside the SwitchPreference in the following method:
#Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
View switchView = holder.findViewById(AndroidResources.ANDROID_R_SWITCH_WIDGET);
syncSwitchView(switchView);
syncSummaryView(holder);
}
and this leads to not changeing the UI in the syncSwitchView method.

Using SwitchPreferenceCompat instead of SwitchPreference should resolve the problem.

Related

How to change view for multiple window display in Android N? How to check application is in multiwindow or not?

How can we give separate layout or separate activity for Multiple window ?
eg. I have checked below things with help of android developer site
<activity android:name="com.configure.it.MyScreen">
<layout android:defaultHeight="400dp"
android:defaultWidth="200dp"
android:gravity="top|end"
android:minimalSize="300dp" />
</activity>
by declaring above things it affect how an activity behaves in multi-window mode.
But how can I show different layout if my particular screen is activated on Multiple-Window ?
From the Android Developer link .
To make changes in UI or separate layout which should be used on Multiple-window activate.
We can check if activity is in Multiple-window by following way
From activity Activity.isInMultiWindowMode() Call to find out if the activity is in multi-window mode.
eg. To check in Activity if its multiple window than header(or any view should have Red background color if its not in multiple window thn it should be Green background color)
headerView.setBackgroundColor(inMultiWindow()?Color.RED:Color.GREEN);
using inMultiWindow() replacing Fragment is also possible
To get Callback on Multiple-Window Activation.
From Activity onMultiWindowChanged method is available to handle runtime changes on this method callback.System will give callback on this method whenever the activity goes into or out of multi-window mode with boolean value.With the help of sample link & android developer link
#Override
public void onMultiWindowChanged(boolean inMultiWindow) {
super.onMultiWindowChanged(inMultiWindow);
headerView.setBackgroundColor(inMultiWindow ? Color.RED : Color.GREEN);
// here we can change entire fragment also.
//If multiple window in than seperate and for multiple window out different
}
Will keep updating if I get anything else.
isInMultiWindowMode() is added in API 24 to check device is in Multi window Mode or not, it returns a boolean value. whenever device goes to Multi window Mode it triggers onConfigurationChanged() method.
you will need to manually update your Views, Reload resources, etc... in onConfigurationChanged() based on Landscape and portrait mode.
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
{
//do something (Update your views / Reload resources)
}else{
}
}
In Manifest.xml
<activity
android:name=".yourActivity"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
/>
For further reference check with Multi-Window Support Google Dev and MultiWindow Medium Corp

switching between dialog and activity based on device size

In any application the add/edit will be comparatively having lesser inputs. I have seen that the application, esp., calendar, are using clever strategy to show these as simple dialog, so that the user may not notice that there is empty space in the designed form
As shown below
My question is, how to make it happen?
What I'm doing is I extend DialogFragment:
public class AboutFragment extends DialogFragment { ... }
I also have an activity that contains that fragment. And when the dialog/activity needs to be called, this method decides how to display it:
public static void showAbout(Activity parent) {
if (isTablet) {
AboutFragment aboutFragment = AboutFragment.newInstance();
aboutFragment.setStyle(DialogFragment.STYLE_NORMAL, R.style.DialogTheme);
DialogUtils.showDialog(parent, aboutFragment);
} else {
Intent aboutIntent = new Intent(parent, AboutActivity.class);
parent.startActivity(aboutIntent);
}
}
How to decide whether it is a tablet, is totally up to you.
This technique is explained in the documentation.
In my opinion the best approach here is to use
<!-- Theme for a window without an action bar that will be displayed either full-screen
on smaller screens (small, normal) or as a dialog on larger screens
(large, xlarge). -->
"android:Theme.Holo.Light.DialogWhenLarge.NoActionBar"
The best/easiest solution I've found is to always use an Activity, and based on screensize (and version), change your Theme parent.
in res/values/themes.xml
<style name="Detail.Theme" parent="#android:style/Theme.Holo.Light" >
...
</style>
and in res/values-large/themes.xml
<style name="Detail.Theme" parent="#android:style/Theme.Holo.Light.DialogWhenLarge" >
...
</style>
use Context.setTheme method to set them programmetically. As the doc says
this should be called before any views are instantiated in the Context
(for example before calling.
So, to switch between themes need to call setTheme before onCreate
public void onCreate(Bundle savedInstanceState) {
// check screen size
setTheme(dialogTheme);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
}
As #StinePike answered, setting a dialog theme programatically doesn't do any use (to me), as it shows a wierd black screen behind the dialog, rather than a dimmed background (as shown in the question). This is obviously a bug.
Instead of trying to set it programatically, or in style.xml, and pretty much everywhere except for AndroidManifest.xml, I did the reverse, which has worked for me.
(the solution which I took from the marvelous solution of the above issue)
The simplest solution (that works) as follows:
1. Make the activity a dialog by default through AndroidManifest.xml:
e.g., in the AndroidManifest.xml:
<activity
android:name="com.example.MyActivity"
android:label="#string/title_activity_mine"
android:theme="#android:style/Theme.DeviceDefault.Dialog">
...
</activity>
2. On starting the activity, set the theme to default if device is not a tablet.
if (!(isTablet(this)) {
setTheme(defaultTheme);
}
super.onCreate(savedInstanceState);
...
Note:
solution will work with custom styles defined in style.xml.
Ref:
How to detect device is Android phone or Android tablet?
Dialog with transparent background in Android
Issue 4394 - android - setTheme() does not work as expected
PS: final app on tablet and phone is as follows:
Use a DailogFragment and then control how its shown with setShowsDialog()

RingtonePreference not saving in PreferenceActivity

I am using PreferenceScreen to set some user preferences in my Android app. It works perfectly for several ListPreference and CheckboxPreference items, however I cannot get RingtonePreference to work properly. The appropriate ringtone dialog displays, and can be selected, but the selection is never saved.
My app only plays the default sound no matter what I select. Whenever I re-open the ringtone dialog (either immediately after making a selection, or after exiting the app and coming back in) it always just has the default item selected. I have a field to display the preference value, and it always shows the default sound is selected, even after changing it on the preferences screen. I also confirmed that the appropriate xml file on my device (in /data/data/myapp/shared_prefs) is not changing when I monitor it with DDMS. If I change other items (such as a CheckboxPreference), I see the shared_prefs file change realtime. I have stripped my PreferenceScreen to the bare minimum and it still behaves the same. I tried changing key names, defaults, and clearing app data on my phone.. nothing seems to work.
I did find 2 similar questions already posted on SO (here and here), but they are several months old, with no answers and/or the person asking the question gave up and tried another method. I'd like to figure out why it does not appear to work as designed.. or at least, find a suitable method to get the same thing done.
The relevant portions of my code are below.. thanks in advance!
/res/xml/preferences.xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<RingtonePreference
android:key="alertSound"
android:ringtoneType="notification"
android:summary="Select audio notification sound"
android:title="Alert Sound" >
</RingtonePreference>
</PreferenceScreen>
/src/myapp/EditPrefsActivity.java:
public class EditPrefsActivity extends PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
settings = PreferenceManager.getDefaultSharedPreferences(this);
addPreferencesFromResource(R.xml.preferences);
}
}
I just found the solution! The answer was recently posted in a similar question: https://stackoverflow.com/a/15887357/1992342
Removing android:launchMode="singleInstance" from the EditPrefsActivity <activity> entry in the manifest solves the problem. Apparently it is a [little known] Android bug.

How to Initialize Preferences Screen on First Invocation?

I believe I am correctly initializing preferences from XML. My Preferences Screen also works properly and reflects the correct user selected settings.
However, upon first invocation of that Preferences Screen, none of the settings are checked (checkbox) or selected (list). This, of course, confuses the user as it doesn't reflect the current (default/initial) value.
Since all I do to invoke the Preferences Screen is
startActivity(new Intent(this, EditPreferences.class));
And my EditPreferences class only contains:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.usersettings);
}
I am not sure where or how to tell it to pre-initialize the visual display with the default setting.
I have this hunch that all I am missing is a single line somewhere, but I don't know where: XML file? override a method in EditPreferences? Other?
Can't you define the default value in the XML itself?
<CheckBoxPreference ...
android:defaultValue="true"
... />
You can specify a default value on a preference (in your xml layout for example):
<EditTextPreference android:defaultValue="whatever" />

Is it possible to display a DialogPreference without showing a PreferenceScreen?

I'm currently writing a live wallpaper for Android and it has a PreferenceScreen which currently contains only one preference - a DialogPreference to set various properties of animation.
User workflow to configure it currently looks like this:
Settings... => (shows the preferences list with only one title ) Animation speed => MyDialogPreference
What I want is to make the workflow like this:
Settings... => MyDialogPreference
I.e. I'm looking for a way to skip showing that preferences list with only one item and to show that dialog right away.
But it seems that PreferenceActivity requests itself to have PreferenceScreen as a root element of preference hierarchy. So... is it even possible to do what i want? :)
Code references:
Activity code:
public class ForestLakePreferences extends PreferenceActivity
{
protected void onCreate(Bundle savedState)
{
super.onCreate(savedState);
getPreferenceManager().setSharedPreferencesName(
ForestLakeWallpaper.PREFS_NAME);
addPreferencesFromResource(R.xml.preferences);
}
}
Prefs resource:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:key="lake_preferences">
<DurationEditDialog
android:title="#string/prefs_duration_title"
android:dialogTitle="#string/configure_durations_dlg_title"
android:dialogLayout="#xml/set_durations_layout" />
</PreferenceScreen>
It turned out this can't be done in that way.
But i've found a workaround: i made my activity not a PreferencesActivity, but a custom one and made it look like dialog by placing the following in AndroidManifest.xml
<activity android:theme="#android:style/Theme.Dialog" .... />
A DialogPreference has a showDialog(Bundle state) method, try calling it. I am not sure if you will have to give it anything else like the Preferences or anything.

Categories

Resources