Development issue/problem:
I want something in my settings menu that changes the duration of the vibration.
There is no sliding tag for prefs.xml, what is the best way to proceed?
How can I solve this problem?
Solution 1:
You can create your own preference class that expands the DialogPreference and displays the SeekBar as a dialog box.
Solution 2:
I have improved the link provided by Macarse, so that the value is only saved when you click ok, and you can @string/… Values in the XML file.
Here’s the code:
/* The following code is written by Matthew Wiggins
* and is released under the license APACHE 2.0
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Improvements :
* – Save the value on a positive click, do not change the search bar
* – @string/… Values in the xml file
*/
Package and.atcm.carpooling.utils;
Import android.app.AlertDialog;
Import android.content.Context;
Import android.os.bundle;
Import android.preference.DialogPreference;
Import android.util.AttributeSet;
Import android.view.Gravity; Import
android.view.view;
android.view.view.OnClickListener;
android.widget.Button;
android.widget.LinearLayout import;
android.widget.SeekBar import;
android.widget.TextView import;
The SeekBarPreference public class extends DialogPreference with SeekBar.OnSeekBarChangeListener, OnClickListener
{
// ——————————————————————————————
// Closed Attributes:
private static endpoints androidns=http://schemas.android.com/apk/res/android
SearchBar private mSeekBar;
private TextView mSplashText,mValueText;
private Context mContext ;
private String mDialogMessage, mSuffix;
private int mDefault, mMax, mValue = 0;
// ——————————————————————————————
// ——————————————————————————————
// Builder:
public SeekBarPreference(Context, attributesSet attributes) {
super(context,attrs);
mContext = context ;
// Get string value for dialogMessage:
int mDialogMessageId = attrs.getAttributeResourceValue(androidns, dialogMessage, 0);
if(mDialogMessageId ==0) mDialogMessage = attrs.getAttributeValue(androidns, dialogMessage);
else mDialogMessage = mContext.getString(mDialogMessageId) ;
// Get the string value for the suffix (text attribute in the xml file):
int mSuffixId = attrs.getAttributeResourceValue(androidns, text, 0) ;
if(mSuffixId == 0) mSuffix = attrs.getAttributeValue(androidns, text) ;
else mSuffix = mContext.getString(mSuffixId) ;
// Get the default and maximum values from the search bar:
mDefault = attrs.getAttributeIntValue(androids, default, 0);
mMax = attrs.getAttributeIntValue(androids, max, 100);
}
// ——————————————————————————————
// ——————————————————————————————
// Methods of the dialogue conference :
@Surface
protected view onCreateDialogView() {
Parameters LinearLayout.LayoutParams;
linearLayout layout = new LinearLayout(mContext);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setPadding(6,6,6) ;
mSplashText = new TextView(mContext);
mSplashText.setPadding(30, 10, 30, 10);
if (mDialogMessage != null)
mSplashText.setText(mDialogMessage);
layout.addView(mSplashText) ;
mValueText = new TextView(mContext);
mValueText.setGravity(Gravity.CENTER_HORIZONTAL);
mValueText.setTextSize(32);
params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
layout.addView(mValueText, params;)
mSeekBar = new SeekBar(mContext);
mSeekBar.setOnSeekBarChangeListener(this);
layout.addView(mSeekBar, new LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)))) ;
if (shouldPersist())
mValue = getPersistedInt(mDefault) ;
mSeekBar.setMax(mMax) ;
mSeekBar.setProgress(mValue) ;
return model;
}
Override
protected void onBindDialogView(View v) {
super.onBindDialogView(v);
mSeekBar.setMax(mMax);
mSeekBar.setProgress(mValue);
}.
General
protects void onSetInitialValue (logical restore, Object defaultValue)
{
super.onSetInitialValue(restore, defaultValue);
if (restore)
mValue = shouldPersist() ? getPersistedInt(mDefault): 0;
otherwise
mValue = (Integer)defaultValue;
}
// ——————————————————————————————
// ——————————————————————————————
// OnSeekBarChangeListener Methods :
@Override
public void onProgressChanged(SeekBar, int value, boolean fromTouch)
{
String t = String.valueOf(value);
mValueText.setText(mSuffix == null ? t : t.concat( + mSuffix));
}.
Override
public null and void onStartTrackingTouch (search in SeekBar) {}
@Override
public null and void onStopTrackingTouch (search in SeekBar) {}.
public invalid setMax(int max) { mMax = max; }
public int getMax() { return mMax; }
public invalid setProgress(int progress) {
mValue = progress;
if (mSeekBar != null)
mSeekBar.setProgress(progress);
}
public int getProgress() { return mValue; }
// ——————————————————————————————
——————————————————————————————
// Define listening to the positive button and the onClick action :
@Override
public empty showDialog(Package state) {
super.showDialog(state) ;
PositiveButton = ((AlertDialog) getDialog()).getButton(AlertDialog.BUTTON_POSITIVE);
positiveButton.setOnClickListener(this);
}.
@General invalid
opClisk(View v) {
as (shouldPersist()) {
mValue = mSeekBar.getProgress();
remainInt(mSeekBar.getProgress());
callChangeListener(Integer.valueOf(mSeekBar.getProgress());
}
((AlertDialog) getDialog()).dismiss();
}
// ——————————————————————————————
}
EDIT:
Here’s a screenshot:
EDIT: At arlomedia’s request, here are all the necessary bits of code (I’ve just created a new project, it’s working fine. I fixed some bugs in the SeekBarPreference class, so don’t forget to copy/paste it again) :
Main activities :
Package and.at.test sliderpref ;
import android.app.Activity;
import android.content.intentional;
import android.os.bundle;
import android.view.Menu;
import android.view.MenuItem ;
the MainActivity public class expands the activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@General Boolean menu
onCreateOptionsMenu(Menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Public check boolean
onMenuItemSelected(int featureId, item MenuItem) {
switch(item.getItemId()) {
case R.id.menu_settings : {
startActivity (new intent (this, SettingsActivity.class)) ;
pause;
}
}
return where;
}
}
SettingsActivities :
Package and.at.test sliderpref ;
Import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.bundle;
import android.preference.PreferenceActivity;
import android.preferenceFragment;
import android.preference.PreferenceManager;
import and.at.testsliderpref.utils.SeekBarPreference ;
the SettingsActivity public class extends the SettingsActivity preferences {
@Override
protected empty onCreate(Bundle storedInstanceState) {
// Call the super:
super.onCreate(savedInstanceState) ;
// Set the activity clip:
getFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsFragment()).commit();
}
public static class settingsFragment expands PreferenceFragment Implementation of OnSharedPreferenceChangeListener {
private SeekBarPref _searchBarPref ;
@Override
public void onCreate(Bundle storedInstanceState) {
super.onCreate(savedInstanceState) ;
// Load the parameters of the XML source
addPreferencesFromResource(R.xml.activity_settings) ;
// Get Widgets:
_SearchBarPref = (SearchBarPreference) this.findPreference(SEEKBAR_VALUE) ;
// Set the listener:
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this) ;
// Set the search bar summary:
int radius = PreferencesManager.getDefaultSharedPreferences(this.getActivity()).getInt(SEEKBAR_VALUE, 50);
_seekBarPref.setSummary(this.getString(R.string.settings_summary).replace($1, +radius)));
}
@SharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
// Set Search List Summary:int radius = PreferencesManager.getDefaultSharedPreferences(this.getActivity()).getInt(SEEKBAR_VALUE, 50);_seekBarPref.setSummary(this.getString(R.string.settings_summary).replace($1, +radius));}}.
layout > activity_main.xml :
menu > main.xml :
xml > activity_parameters.xml :
Values > strings.xml :
TestSliderPref
SeekBarPreference test
Parameter
Message appears here
Current value 1
Km
Header appears here
Don’t forget to add your SettingsActivity to the manifesto and everything should be fine.
Solution 3:
An easy way to do this is to add an empty preference to your preferences.xml file that uses a layout with the search bar.
Add your preferences.xml
add a cursor under layouts
Solution 4:
If you have already switched to androidX, you can simply use androidx.preference.SeekBarPreference. Documentation here and here
Define it in XML as follows:
Pay attention: Now in Android Studio (my current version 3.2.1), the automatic preferences do not work for androidx.preference.preferencesScreen in prefs.xml, but don’t worry about the xml swell settings with setPreferencesFromResource() works fine. All required attribute names and component references can be found here.
Solution No 5:
This is a good Slider Preferences component – Android Slider Preferences Library
https://github.com/jayschwa/AndroidSliderPreference
Solution No 6:
Another version.
All credit goes to Tim Autin.
I wanted the values loaded from XML tables to be displayed.
That’s what it looks like.
Code – which now expands the ListPreference list
import android.app.alertDialog;
import android.content.Context;
import android.os.bundle;
import android.preference.ListPreference;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.view;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView ;
The SeekBarListPreference public class extends ListPreference and implements SeekBar.OnSeekBarChangeListener, View.OnClickListener {
// ——————————————————————————————
// Closed Attributes:
private static android end lines = http://schemas.android.com/apk/res/android.
SearchBar private mSeekBar;
private TextView mSplashText, mValueText;
private Context mContext ;
private String mDialogMessage;
// ——————————————————————————————
public SeekBarListPreference(context, attributesNet) {
super(context, attributes) ;
mContext = Context ;
// Get string value for dialogMessage:
int mDialogMessageId = attrs.getAttributeResourceValue(androidns, dialogMessage, 0);
if (mDialogMessageId ==0)
mDialogMessage = attrs.getAttributeValue(androidns, dialogMessage);
else mDialogMessage = mContext.getString(mDialogMessageId);
}
// ——————————————————————————————
// Methods of the dialogue conference :
@Surface
protected view onCreateDialogView() {
Parameters LinearLayout.LayoutParams;
linearLayout layout = new LinearLayout(mContext);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setPadding(6, 6, 6) ;
mSplashText = new TextView(mContext);
mSplashText.setPadding(30, 10, 30, 10);
if (mDialogMessage != null)
mSplashText.setText(mDialogMessage);
layout.addView(mSplashText) ;
mValueText = new TextView(mContext);
mValueText.setGravity(Gravity.CENTER_HORIZONTAL);
mValueText.setTextSize(32);
params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT) ;
layout.addView(mValueText, params) ;
mSeekBar = new SeekBar(mContext);
mSeekBar.setOnSeekBarChangeListener(this);
layout.addView(mSeekBar, new LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)))) ;
setProgressBarValue() ;
return model;
}
@PrepareDialogBuilder(AlertDialog.Builder.Builder) {// don’t call super}.
private void setProgressBarValue() {
String mValue = null;
if (shouldPersist()) {
mValue = getValue();
}
end int max = this.getEntries().length – 1 ;
mSeekBar.setMax(max);
mSeekBar.setProgress(this.findIndexOfValue(mValue));
}
@Override
protected blank onBindDialogView(View v) {
super.onBindDialogView(v);
setProgressBarValue();
}
General
public invalid onProgressChanged(SeekBar, int value, boolean fromTouch) {
final CharSequence textToDisplay = getEntryFromValue(value);
mValueText.setText(textToDisplay);
}
private CharSequence getEntryFromValue(int value) [
CharSequence[] entries = getEntries();
return value >= 0 && entries != null ? entries [value]: null;
}
@Override
public blank onStartTrackingTouch(SeekBar) {
}
@Override
public blank onStopTrackingTouch(SeekBar) {
}
Override
public void showDialog(Bundle state) {
super.showDialog(state) ;
PositiveButton = ((AlertDialog) getDialog()).getButton(AlertDialog.BUTTON_POSITIVE);
positiveButton.setOnClickListener(this);
}.
@General invalid
opClisk(View v) {
if (shouldPersist()) {
final int progressChoice = mSeekBar.getProgress();
setValueIndex(progressChoice);
}
getDialog().dismiss();
}
}
Now use in the preset file
And the paintings
10 seconds
30 seconds
1 minute
2 minutes
unlimited
10
30
60
120
0
As a bonus, if you already have ListPreferences, you don’t have to add anything to display the summary as current value. So it works very well.
@Override
public blank onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
SetSummaryForPreferenceKey(key);
}
private void SetSummaryForPreferenceKey(String key) {
Preference = findPreference(key) ;
// This works with our new SeekBarPreference
, as (privileged ListPref instance) {
ListPref listPref = (ListPreference) privilege;
listPref.setSummary(listPref.getEntry());
}
} }.
Solution No 7:
I improved the code in Tim’s answer a little. This allows the output value to be changed simply when the cursor is moved, instead of the user having to press the OK button to make changes.
This is useful for things like the music volume control, where the user should be able to hear the volume setting as it is being made.
When the user presses OK, the new value is stored. When the user presses the Cancel button, the originally set value is restored.
Thanks and the honor goes to Tim, I just added an extra onClick listener and pushed the value of the update to the onChange listener.
Package and.atcm.carpooling.utils;
/* The following code is written by Matthew Wiggins
* and is released under the license APACHE 2.0
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Improvements :
* – Save the value on the positive click button and/or change the search bar
* – Restore the preset value on the negative click button
*/.
Import android.R;
import android.app.AlertDialog;
import android.content.Context;
import android.os.bundle;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.Severity;
import android.view.view;
import android.view.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView ;
The SeekBarPreference public class extends DialogPreference with
SeekBar.OnSeekBarChangeListener, OnClickListener {
// ——————————————————————————————
// Closed Attributes:
private static android end lines = http://schemas.android.com/apk/res/android.
SearchBar private mSeekBar;
private TextView mSplashText, mValueText;
private Context mContext ;
private String mDialogMessage, mSuffix ;
private int mDefault, mMax, mValue, mOrig = 0 ;
// ——————————————————————————————
// ——————————————————————————————
// Builder:
public SeekBarPreference(Context, attributesSet attributes) {
super(context, attrs);
mContext = context ;
// Get string value for dialogMessage:
int mDialogMessageId = attrs.getAttributeResourceValue(androidns,
dialogMessage, 0);
if (mDialogMessageId ==0)
mDialogMessage = attrs
.getAttributeValue(androidns, dialogMessage);
else
mDialogMessage = mContext.getString(mDialogMessageId) ;
// Get the string value for the suffix (text attribute in the xml file):
int mSuffixId = attrs.getAttributeResourceValue(androidns, text, 0);
if (mSuffixId ==0)
mSuffix = attrs.getAttributeValue(androidns, text);
otherwise
mSuffix = mContext.getString(mSuffixId) ;
// Get the default and maximum values for the search bar:
mDefault = attrs.getAttributeIntValue(androids, default, 0);
mMax = attrs.getAttributeIntValue(androids, max, 100);
}
// ——————————————————————————————
// ——————————————————————————————
// Methods of the dialogue conference :
@Surface
protected view onCreateDialogView() {
Parameters LinearLayout.LayoutParams;
linearLayout layout = new LinearLayout(mContext);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setPadding(6, 6, 6) ;
mSplashText = new TextView(mContext);
mSplashText.setPadding(30, 10, 30, 10);
if (mDialogMessage != null)
mSplashText.setText(mDialogMessage);
layout.addView(mSplashText) ;
mValueText = new TextView(mContext);
mValueText.setGravity(Gravity.CENTER_HORIZONTAL);
mValueText.setTextSize(32);
params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
layout.addView(mValueText, params;)
mSeekBar = new SeekBar(mContext);
mSeekBar.setOnSeekBarChangeListener(this);
layout.addView(mSeekBar, new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT)))) ;
if (shouldPersist())
mValue = getPersistedInt(mDefault) ;
mSeekBar.setMax(mMax) ;
mSeekBar.setProgress(mValue) ;
return model;
}
Override
protected void onBindDialogView(View v) {
super.onBindDialogView(v);
mSeekBar.setMax(mMax);
mSeekBar.setProgress(mValue);
}.
General
protected void onSetInitialValue(logical recovery, Object defaultValue) {
super.onSetInitialValue(recovery, defaultValue);
// Sets the configurable value
as (recovery)
mValue = shouldPersist() ? getPersistedInt(mDefault): 0;
else
mValue = (Integer) default value;
// Sets the original default value to
mOrig = mValue;
}
// ——————————————————————————————
// ——————————————————————————————
// OnSeekBarChangeListener Methods :
@Override
public void onProgressChanged(SeekBar, int value, boolean fromTouch) {
String t = String.valueOf(value) ;
mValueText.setText(mSuffix == null ? t : t.concat( + mSuffix)))
if (shouldPersist()) {
mValue = mSeekBar.getProgress();
persistInt(mSeekBar.getProgress());
callChangeListener(Integer.valueOf(mSeekBar.getProgress());
}.
}
@Override
public blank onStartTrackingTouch(SeekBar search) {
}
@Override
public blank onStopTrackingTouch(SeekBar search) {
}
public invalid setMax(int max) {
mMax = max ;
}
public int getMax() {
gives mMax;
}
public invalid setProgress(int progress) {
mValue = progress;
if (mBar of the week != null)
mBar of the week.setProgress(int progress);
}
public int getProgress() {
return mValue;
}
// ——————————————————————————————
——————————————————————————————
// Define listening to the positive button and the onClick action :
@Override
public empty showDialog(Package state) {
super.showDialog(state) ;
Positive button = ((AlertDialog) getDialog())
.getButton(AlertDialog.BUTTON_POSITIVE);
Negative button = ((AlertDialog) getDialog())
.getButton(AlertDialog.BUTTON_NEGATIVE);
positiveButton.setOnClickListener(cListenPos);
negativeButton.setOnClickListener(cListenNeg);
}.
View.OnClickListener cListenPos = new View.OnClickListener() {public null and void onClick(View v) {if (shouldPersist())) {mValue = mSeekBar.getProgress();mOrig = mSeekBar.getProgress();persistInt(mSeekBar.getProgress());callChangeListener(Integer.valueOf(mSeekBar.getProgress());}( AlertDialog) getDialog()).dismiss();}}}.
View.OnClickListener cListenNeg = new View.OnClickListener() {
public invalid onClick(View v) {
if (shouldPersist()) {
mValue = mOrig;
remainInt(mOrig);
callChangeListener(Integer).valueOf(mOrig));
}
((AlertDialog) getDialog()).dismiss();
}
}
@Check public empty
opClisk(View v) {}
// ——————————————————————————————
}
Solution No 8:
A small improvement over Tim’s reaction and his distractions:
protected nullity onBindDialogView(View v) {
super.onBindDialogView(v);
mSeekBar.setMax(mMax);
mSeekBar.setProgress(mValue);
String t = String.valueOf(mValue);
mValueText.setText(mSuffix == null ? t : t.concat( + mSuffix));
}
At the beginning, the current value is entered, which is otherwise empty until you actually move the cursor.
Good luck!
Related Tags: