Is there any way to add a button to the bottom of preferences screen and make them work correct when scrolling?
-
2Have you looked at creating a custom preference? – Prashast Apr 23 '10 at 11:09
-
2For future visitors, while Max's solution works, there is an alternate solution: http://stackoverflow.com/a/7251575/802469 – Reed Mar 19 '14 at 21:20
12 Answers
There is another solution for customizing the appearance of the preferences.
Design a normal XML layout with buttons or whatever you want to add to the standard preferences. Include a ListView
in your layout and give it the ID @android:id/list
.
Let's say we call the layout file res/layout/main.xml
. It could look something like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button android:text="This is a button on top of all preferences."
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ListView android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
In your PreferenceActivity
, add these two lines to your onCreate
:
addPreferencesFromResource(R.xml.preferences);
setContentView(R.layout.main);
The ListView
in your layout will then be replaced by the preferences defined the usual way in res/xml/preferences.xml
.

- 3,830
- 1
- 17
- 18

- 2,574
- 1
- 14
- 3
-
-
10Does not work when button is placed below the list view. Does not work when preferences activity is using the dialog theme. – Greg Ennis Nov 06 '11 at 17:30
-
11The latest documentation on using PreferenceActivity at http://developer.android.com/reference/android/preference/PreferenceActivity.html mentions that for all new development PreferenceFragment is the preferred way to implement. It seems that the given solution wont work in such a scenario. – Pankaj Jul 26 '12 at 07:20
-
thankx man, such a easy solution , but took my long time to add View to Preference Screen – Naba Jan 04 '13 at 13:35
-
4
-
7I'm a bit baffled by how many votes this answer has since it doesn't actually answer the original question. It doesn't scroll with the list, and it doesn't work when the button is placed at the bottom of the view, as mentioned in comments above. – howettl Jan 21 '13 at 23:21
-
Very clearly described and worked perfectly the first time, thanks! Why people want to hide buttons IN a ListView is beyond me--listen, buttons should be OUTSIDE of a ListView, so that they are *viewable*! – SMBiggs Sep 30 '13 at 16:10
-
1@howettl just change fill_parent to wrap_content in ListView layout_height – Martin Ch Mar 16 '14 at 15:47
-
How would you then programatically access the button / textview? I want to set the text fo the textview. – Zapnologica Nov 06 '14 at 10:46
-
This doesn't seem to be working in Marshmellow. Anyone else seeing this? – Justin Nov 02 '15 at 16:36
-
Updated code is here https://developer.android.com/reference/android/preference/PreferenceActivity.html as Default Shared Preference Setting. – Teekam Jun 07 '17 at 07:09
I know this is a bit late, but I just found a solution i like better than Max's praised solution.
You can simply add a footer (or if you like the button to be on top, a header) to the PreferenceActivity's ListView like so:
public class MyActivity extends PreferenceActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
ListView v = getListView();
v.addFooterView(new Button(this));
}
}
I hope this helps someone.

- 7,941
- 3
- 37
- 50
-
2At least this feels better as Max's solution as it doesn't rely on element id's. Let's see how it behaves in future versions of Android... – Daniel F Sep 16 '12 at 21:27
-
-
2
-
@MichałK I'm not at all sure, and I can't try right now as I haven't got the SDK installed, but you could maybe do it like this: ListView v = ((PreferenceActivity)getActivity()).getListView(); – jpihl Nov 01 '12 at 20:23
-
1No, it wouldn't work that way (because `PreferenceFragment` has its own list), but I resolved it by just creating a `Preference` and setting an `Intent` on it. There was no need to create a button (at least in my case) – Michał Klimczak Nov 01 '12 at 20:56
-
3Doesn't work with the PreferenceFragmentCompat, since getListView will actually return a RecyclerView – Mauker Mar 28 '20 at 17:40
This example below will render a button at the bottom of the page (in case anybody is still interested).
In case of a LinearLayout you could also apply weights; this is needed because the Listview is set to *fill_parent*. I usually do this by adding *android:layout_weight* 's:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ListView android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_weight="10"/>
<Button android:text="This is a button on top of all preferences."
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_weight="1"/>
</LinearLayout>
The explanation below isn't propbably 100% but it will help you understand...
+-- View Port (linear layout)
| +-- List View (this is where the preferences will go)
| |
| |
| +--
+--
+--
| Button (which was pushed out of view by the fillparent of ListView
+--
You could also say, because the Button has no weight; the button is rendered at 0dp height.
Now with the layout_weigths added it will lett the button render inview
+-- View Port (linear layout)
| +-- List View (this is where the preferences will go)
| |
| |
| +--
| +--
| | Button (which was pushed out of view by the fillparent of ListView
| +--
+--

- 852
- 12
- 25
Actually, there is a solution. Here is a code, i hope, this will be useful for anyone. It looks like 3 options and 2 buttons in the bottom of the screen, independent of screen resolution (was targeted to 240 as lowest)
package com.myapplication.gui;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.view.Display;
import android.view.Gravity;
import android.view.WindowManager;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ScrollView;
import com.myproject.general.HeightListView;
import com.myapplication.R;
public class FilterActivity extends PreferenceActivity {
private LinearLayout rootView;
private LinearLayout buttonView;
private Button buttonDone;
private Button buttonRevert;
private ListView preferenceView;
private LinearLayout gradientView;
private ScrollView scrollRoot;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int height = display.getHeight();
int width = height > 240 ? display.getWidth() : display.getWidth() - 4;
scrollRoot = new ScrollView(this);
scrollRoot.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
rootView = new LinearLayout(this);
rootView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
rootView.setOrientation(LinearLayout.VERTICAL);
buttonView = new LinearLayout(this);
buttonView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
buttonView.setOrientation(LinearLayout.HORIZONTAL);
buttonView.setGravity(Gravity.BOTTOM);
gradientView = new LinearLayout(this);
gradientView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
gradientView.setOrientation(LinearLayout.HORIZONTAL);
gradientView.setBackgroundResource(R.drawable.gradient);
gradientView.setPadding(0, 5, 0, 0);
gradientView.setBackgroundResource(R.drawable.gradient);
buttonDone = new Button(this);
buttonDone.setText(R.string.filterButton_Done);
buttonDone.setLayoutParams(new LayoutParams(width/2, LayoutParams.WRAP_CONTENT));
gradientView.addView(buttonDone);
buttonRevert = new Button(this);
buttonRevert.setText(R.string.filterButton_Revert);
buttonRevert.setLayoutParams(new LayoutParams(width/2, LayoutParams.WRAP_CONTENT));
gradientView.addView(buttonRevert);
buttonView.addView(gradientView);
preferenceView = new HeightListView(this);
preferenceView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
preferenceView.setId(android.R.id.list);
PreferenceScreen screen = createPreferenceHierarchy();
screen.bind(preferenceView);
preferenceView.setAdapter(screen.getRootAdapter());
rootView.addView(preferenceView);
rootView.addView(buttonView);
if (height > 240) {
this.setContentView(rootView);
}
else {
scrollRoot.addView(rootView);
this.setContentView(scrollRoot);
}
setPreferenceScreen(screen);
}
private PreferenceScreen createPreferenceHierarchy() {
PreferenceScreen root = getPreferenceManager().createPreferenceScreen(this);
PreferenceScreen pref1 = getPreferenceManager().createPreferenceScreen(this);
pref1.setKey("pref1");
pref1.setTitle("Title");
pref1.setSummary("Summary");
root.addPreference(pref1);
PreferenceScreen pref2 = getPreferenceManager().createPreferenceScreen(this);
pref2.setKey("pref2");
pref2.setTitle("Title");
pref2.setSummary("Summary");
root.addPreference(pref2);
PreferenceScreen pref3 = getPreferenceManager().createPreferenceScreen(this);
pref3.setKey("pref3");
pref3.setTitle("Title");
pref3.setSummary("Summary");
root.addPreference(pref3);
return root;
}
}
You just need to use PreferenceFragment inside general Activity and add the button into activity layout.
public class SettingActivity extends Activity {
UserProfileViewModel userProfileViewModel = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_setting);
getFragmentManager().beginTransaction()
.replace(R.id.content, new SettingsFragment())
.commit();
}
private class SettingsFragment extends PreferenceFragment {
public SettingsFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.pref_main);
}
}
}
SettingActivity.java
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/buttonSave"/>
<Button
android:id="@+id/buttonSave"
android:text="Save"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</RelativeLayout>
activity_setting

- 107
- 8
-
I followed this suggestion, and it does display the button at the bottom of the view, but it's superimposed on top of the preferences list and cannot be clicked (i.e. clicking the button only activates the preference item underneath). – iaindownie Mar 06 '19 at 17:22
-
-
@rdehuyss it because you need to add onClickListener to `buttonSave` :) – Albert Aleksieiev May 22 '19 at 04:07
It is also possible to add Action buttons to the action bar for an android standard approach.
public class PrefActivity extends PreferenceActivity{
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.preference_header_menu, menu);
return super.onCreateOptionsMenu(menu);
}
}
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/action_add"
android:icon="@drawable/ic_menu_add_dark"
android:title="@string/menu_action_add_title"
android:showAsAction="always" />
</menu>

- 341
- 1
- 3
- 9
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="@dimens/listview_height" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="This is a button on top of all preferences." />
</RelativeLayout>
I reference @Ronnie, use RelativeLayout and set a height for layout_height of listview, and then set the button's layout_alignParentBottom = "true", It can render a button at the bottom of PreferenceScreen; then use the way of @Max. it works for my needs.

- 2,374
- 1
- 20
- 30
-
This is a nice solution, but you forgot to set the listview above the button. currently, items of the listview could be behind the button, which is not recommended since if it's the last item, it will never be visible and therefore clickable. – android developer Apr 26 '13 at 09:00
-
oh, yes, you are right, I forgot this case, because my listview only 5 items, thanks. – Mejonzhan Apr 26 '13 at 09:22
-
please update your answer, so others won't have this behavior. – android developer Apr 26 '13 at 09:43
-
I think you also forgot some attributes and the end-tag of the relativeLayout . – android developer Apr 26 '13 at 10:09
-
In fact, setting the right listview_height can solve the problem you said. – Mejonzhan Apr 27 '13 at 16:29
-
no it won't. since it's a constant value, yet the size of the list can be as large as you wish, the last item that should be visible will in fact be (at least partially) hidden by the button. it's really easy to fix your code though. – android developer Apr 27 '13 at 19:17
The following is a simple solution to add a clickable button to your preference screen. This is made easy because the preferences already reserve the space in the android:widgetLayout and the button can pass clicks with android:onClick.
First create a button.xml with the content
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:text="BUTTON"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/button"
android:onClick="onButtonClick"/>
</LinearLayout>
Now in your preferences.xml, add the preference
<Preference
android:key="button"
android:title="Title"
android:summary="Summary"
android:widgetLayout="@layout/button" />
Your PreferenceActivity now only has to contain a onButtonClick member
public class MainActivity extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.main_preferences);
}
public void onButtonClick(View v) {
Log.d("Button", "Yeah, button was clicked");
}
}

- 423
- 5
- 5
preferences.xml:
<Preference
android:key="clearAllData"
android:title="@string/settings_clear_all_data">
</Preference>
SettingsFragment.java:
public class SettingsFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
Preference clearAllData = (Preference) findPreference("clearAllData");
// setup buttons
final Context context = getActivity();
clearAllData.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
...
}
}
}

- 14,306
- 23
- 105
- 189
This would be what the code looks like in the activity at the ronny's example. My intent was to put an menu in the bottom side of the screen.
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.prefs);
addPreferencesFromResource(R.xml.prefs);
/* LayoutInflater CX = getLayoutInflater();
CX.inflate(R.layout.main,null);*/
// TODO Auto-generated method stub
}

- 512
- 4
- 12
Custom view in Preference Activity this will help to add custom view in PreferenceActivity in Android.
Create main.xml, the only necessary view is a ListView, with id: android:id="@android:id/list"
.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:weightSum="1">
<ListView
android:id="@android:id/list"
android:layout_weight="1"
android:layout_width="fill_parent"
android:layout_height="0dp">
</ListView>
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Create CustomPreferenceActivity.java
public class CustomPreferenceActivity extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
addPreferencesFromResource(R.xml.settings);
//setup any other views that you have
TextView textView = (TextView) findViewById(R.id.textView);
textView.setText("View Added");
}
}

- 21,519
- 75
- 241
- 416

- 31
- 3
I found all of the above answers to be un-usable as any layouts I created to 'wrap' the PreferenceScreen
container inside custom layouts (then adding a button below the ListView
) didn't actually work.
They only overlaid the custom layout on top of the preferences list (floating), and clicking (e.g.) a new custom button would only invoke the preference underneath the button.
However, I found this solution which works a treat for adding a button below the preferences list container, when using PreferenceFragment
.

- 1,046
- 12
- 28