Cómo agregar un botón a PreferenceScreen

106

¿Hay alguna forma de agregar un botón en la parte inferior de la pantalla de preferencias y hacer que funcionen correctamente al desplazarse?

vlaku
fuente
2
¿Ha pensado en crear una preferencia personalizada?
Prashast
2
Para los visitantes futuros, mientras la solución de Max funciona, hay una solución alternativa: stackoverflow.com/a/7251575/802469
Reed

Respuestas:

249

Existe otra solución para personalizar la apariencia de las preferencias.

Diseñe un diseño XML normal con botones o lo que desee agregar a las preferencias estándar. Incluya un ListViewen su diseño y asígnele la identificación @android:id/list.

Digamos que llamamos al archivo de diseño res/layout/main.xml. Podría verse algo como esto:

<?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>

En su PreferenceActivity, agregue estas dos líneas a su onCreate:

addPreferencesFromResource(R.xml.preferences);
setContentView(R.layout.main);

El ListViewen su diseño será reemplazado por las preferencias definidas de la forma habitual en res/xml/preferences.xml.

Max
fuente
10
No funciona cuando el botón se coloca debajo de la vista de lista. No funciona cuando la actividad de preferencias usa el tema de diálogo.
Greg Ennis
11
La documentación más reciente sobre el uso de PreferenceActivity en developer.android.com/reference/android/preference/… menciona que para todos los nuevos desarrollos, PreferenceFragment es la forma preferida de implementar. Parece que la solución dada no funcionará en tal escenario.
Pankaj
4
Todavía no se desplaza con la lista.
Sudarshan Bhat
7
Estoy un poco desconcertado por la cantidad de votos que tiene esta respuesta, ya que en realidad no responde a la pregunta original. No se desplaza con la lista y no funciona cuando el botón se coloca en la parte inferior de la vista, como se mencionó en los comentarios anteriores.
howettl
1
@howettl simplemente cambia fill_parent a wrap_content en ListView layout_height
Martin Ch
56

Sé que esto es un poco tarde, pero acabo de encontrar una solución que me gusta más que la elogiada solución de Max.

Simplemente puede agregar un pie de página (o si desea que el botón esté en la parte superior, un encabezado) al ListView de PreferenceActivity así:

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));
    }
}

Espero que esto ayude a alguien.

jpihl
fuente
2
Al menos, esto se siente mejor como la solución de Max, ya que no depende de los ID de los elementos. Veamos cómo se comporta en futuras versiones de Android ...
Daniel F
@DanielF. no cruce el puente hasta llegar a él;)
jpihl
1
No puedo obtener el ListViewcon PreferenceFragment :(
Michał K
1
No, no funcionaría de esa manera (porque PreferenceFragmenttiene su propia lista), pero lo resolví simplemente creando un Preferencey estableciendo un Intenten él. No había necesidad de crear un botón (al menos en mi caso)
Michał K
1
No funciona con PreferenceFragmentCompat, ya que getListView en realidad devolverá un RecyclerView
Mauker
11

Este ejemplo a continuación mostrará un botón en la parte inferior de la página (en caso de que alguien todavía esté interesado).

En el caso de LinearLayout, también puede aplicar pesos; esto es necesario porque Listview está configurado en * fill_parent *. Normalmente hago esto agregando * 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>

La explicación a continuación no es probablemente del 100%, pero lo ayudará a comprender ...

+-- 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
  +--

También se podría decir, porque el botón no tiene peso; el botón se representa a una altura de 0dp.

Ahora, con el layout_weigths agregado, dejará que el botón se renderice en vista

+-- 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
| +--
+--
Ronnie
fuente
Lo siento, perdí la publicación de @stealthcopter
Ronnie
7

De hecho, hay una solución. Aquí hay un código, espero que sea útil para cualquiera. Parece que hay 3 opciones y 2 botones en la parte inferior de la pantalla, independientemente de la resolución de la pantalla (se apuntó a 240 como el más bajo)

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; 
    } 
}
vlaku
fuente
2

Solo necesita usar PreferenceFragment dentro de la Actividad general y agregar el botón en el diseño de la actividad.

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>

ajuste_actividad

ingrese la descripción de la imagen aquí

Albert
fuente
Seguí esta sugerencia y muestra el botón en la parte inferior de la vista, pero está superpuesto en la parte superior de la lista de preferencias y no se puede hacer clic (es decir, al hacer clic en el botón solo se activa el elemento de preferencia que se encuentra debajo).
iaindownie
El botón onClickListener no se activa con esta solución
rdehuyss
@rdehuyss porque necesitas agregar onClickListener a buttonSave:)
Albert
1

Este sería el aspecto del código en la actividad del ejemplo de ronny. Mi intención era poner un menú en la parte inferior de la pantalla.

/** 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
}
user507410
fuente
1
 <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>

Hago referencia a @Ronnie, uso RelativeLayout y establezco una altura para layout_height de listview, y luego configuro el layout_alignParentBottom = "true" del botón. Puede representar un botón en la parte inferior de PreferenceScreen; luego usa la forma de @Max. funciona para mis necesidades.

Mejonzhan
fuente
Esta es una buena solución, pero olvidó configurar la vista de lista encima del botón. Actualmente, los elementos de la vista de lista podrían estar detrás del botón, lo que no se recomienda ya que si es el último elemento, nunca será visible y, por lo tanto, se podrá hacer clic en él.
desarrollador de Android
oh, sí, tienes razón, olvidé este caso, porque mi lista solo ve 5 elementos, gracias.
Mejonzhan
actualice su respuesta para que otros no tengan este comportamiento.
desarrollador de Android
Creo que también olvidaste algunos atributos y la etiqueta final del relativo diseño.
desarrollador de Android
De hecho, configurar el listview_height correcto puede resolver el problema que dijo.
Mejonzhan
1

También es posible agregar botones de acción a la barra de acciones para un enfoque estándar de Android.

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>
rehacer
fuente
0

Vista personalizada en Preference Activity esto ayudará a agregar una vista personalizada en PreferenceActivity en Android.

Crear main.xml, la vista sólo es necesario es un ListView, con 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>

Crear 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");
        }
}
Ankit Singh
fuente
0

La siguiente es una solución simple para agregar un botón en el que se puede hacer clic a su pantalla de preferencias. Esto se hace fácil porque las preferencias ya reservan el espacio en el android: widgetLayout y el botón puede pasar clics con android: onClick.

Primero crea un button.xml con el contenido

<?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>

Ahora en suferences.xml, agregue la preferencia

<Preference
    android:key="button"
    android:title="Title"
    android:summary="Summary"
    android:widgetLayout="@layout/button" />

Su PreferenceActivity ahora solo tiene que contener un miembro onButtonClick

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");
}
}
ppareit
fuente
0

preferencias.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) {
                ...
            }
    }

}
Dmitry
fuente
0

Encontré que todas las respuestas anteriores no se pueden usar ya que los diseños que creé para 'envolver' el PreferenceScreencontenedor dentro de diseños personalizados (luego agregar un botón debajo del ListView) en realidad no funcionó.

Solo superpusieron el diseño personalizado en la parte superior de la lista de preferencias (flotante), y al hacer clic (por ejemplo) en un nuevo botón personalizado solo se invocaría la preferencia debajo del botón.

Sin embargo, encontré esta solución que funciona muy bien para agregar un botón debajo del contenedor de la lista de preferencias, cuando se usa PreferenceFragment.

iaindownie
fuente