¿Cómo agregar un botón a una pantalla de preferencias?

135

Soy bastante nuevo en el desarrollo de Android y acabo de encontrar Preferencias. Encontré PreferenceScreeny quería crear una funcionalidad de inicio de sesión con él. El único problema que tengo es que no sé cómo podría agregar un botón "Iniciar sesión" PreferenceScreen.

Así PreferenceScreenes como se ve mi :

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
...
    <PreferenceScreen android:title="@string/login" android:key="Login">
        <EditTextPreference android:persistent="true" android:title="@string/username" android:key="Username"></EditTextPreference>
        <EditTextPreference android:title="@string/password" android:persistent="true" android:password="true" android:key="Password"></EditTextPreference>
    </PreferenceScreen>
...
</PreferenceScreen>

El botón debe estar justo debajo de los dos EditTextPreferences.

¿Hay una solución simple para este problema? La única solución que encontré no funcionaba porque uso sub PreferenceScreens.

Actualizar:

Descubrí que puedo agregar botones de esta manera:

<PreferenceScreen android:title="@string/login" android:key="Login">
        <EditTextPreference android:persistent="true" android:title="@string/username" android:key="Username"></EditTextPreference>
        <EditTextPreference android:title="@string/password" android:persistent="true" android:password="true" android:key="Password"></EditTextPreference>
        <Preference android:layout="@layout/loginButtons" android:key="loginButtons"></Preference>
</PreferenceScreen>

y el archivo de diseño ( loginButtons.xml) se ve de esa manera:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent"
    android:weightSum="10" 
    android:baselineAligned="false" android:orientation="horizontal">
    <Button android:text="Login" android:layout_width="fill_parent"
        android:layout_weight="5" android:layout_height="wrap_content"
        android:id="@+id/loginButton" android:layout_gravity="left"></Button>
    <Button android:text="Password?" android:layout_width="fill_parent"
        android:layout_weight="5" android:layout_height="wrap_content"
        android:id="@+id/forgottenPasswordButton"></Button>
</LinearLayout>

Así que ahora aparecen los botones pero no puedo acceder a ellos en código. Lo probé findViewById()pero esto está volviendo nulo. ¿Alguna idea de cómo podría acceder a estos botones?

Van Naaktgeboren
fuente
Mira esta pregunta stackoverflow.com/questions/2697233/…
Juozas Kontvainis
2
Por cierto, la respuesta de @neelabh es más simple: puede lograr el comportamiento requerido especificando el controlador de eventos en el diseño xml: simplemente agregue android:onClick="method"a cada botón, donde el método se define en la actividad como public void method(View v).
Stan

Respuestas:

304

Para el xml:

<Preference android:title="Acts like a button"
                android:key="@string/myCoolButton"
                android:summary="This is a cool button"/>

Entonces para el Java en tu onCreate()

Preference button = findPreference(getString(R.string.myCoolButton));
button.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                @Override
                public boolean onPreferenceClick(Preference preference) {   
                    //code for what you want it to do   
                    return true;
                }
            });

Esto aparecerá como una preferencia normal, con solo un título y un resumen, por lo que parecerá que pertenece.

Editar: cambié a usar @string/myCoolButtony getString(R.string.myCoolButton)porque es mejor usar recursos para la asistencia del compilador, la traducción de idiomas y la facilidad de los cambios de cadena.

Junco
fuente
77
Muchas de las aplicaciones de Google precargadas utilizan este enfoque, por lo que es una buena idea seguirlo. Encontré un botón gris estándar que se ve fuera de lugar en una pantalla de preferencias, y gracias a ti encontré una buena manera de hacerlo parecer estandarizado :)
Tom
55
Asegúrese de que android:key="key"y findPreference("key");están utilizando la misma clave.
Reed
44
en realidad esto no muestra ningún botón, lo que confundirá al usuario y no es lo que el OP preguntó La respuesta correcta para mostrar realmente un botón es la de Nicolas.
mutable2112
77
Acabo de notar que publiqué esto en 2011 a las 1:11. Jaja.
Reed
3
Debería haberlo hecho 1 mes y 11 días después: 11/1 / '11 - 1:11 :)
P Kuijpers
43

Supongo que es demasiado tarde. Esto es lo que he hecho para una Preferencia de botón.

La preferencia en el archivo preferencia.xml en la carpeta xml

....
    <Preference
        android:key="resetBD"
        android:title="@string/ajustes_almacenamiento"
        android:summary="@string/ajustes_almacenamiento_desc"
        android:widgetLayout="@layout/pref_reset_bd_button" 
    ></Preference>
  ...

y pref_reset_bd_button.xml en la carpeta de diseño

 <?xml version="1.0" encoding="utf-8"?>
   <Button
       xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/resetButton" 
        android:text="@string/ajustes_almacenamiento_bt" 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="resetearBD">

   </Button>
Nicolas
fuente
android:widgetLayoutes la conexión perfecta entre fragmentos y preferencias (uno o ambos definidos en XML). Muchas gracias. Aquí
peter_the_oak
Hola @ nicolas Su código funciona, pero una pregunta ... ¿Cómo puede hacer que el botón funcione en una clase que extiende PreferenceActivity
SP
44
Por favor, dime cómo encontrar este botón con la identificación "resetButton" gracias!
Ben Jima
Encontré el uso de android: diseño superior a android: widgetLayout. Usando widgetLayout, mi botón se convirtió en lo que solo puedo describir como layout_alignParentRight = "true", pero ese comportamiento desapareció al usar android: layout en su lugar
JoeHz
1
Y no puedo hacer que esto active un controlador de eventos onPreferenceChange o Click
JoeHz
38

Quería agregar un enlace de salida a las preferencias y pude modificar el código de Jakar para que funcionara así:

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >   
   <PreferenceCategory android:title="Settings">
       <Preference android:title="Click to exit" android:key="exitlink"/>       
   </PreferenceCategory>    
</PreferenceScreen>

Originalmente, la 'Preferencia' era una 'Edición de referencia de texto' que edité manualmente.

Luego en la clase:

public class MyPreferences extends PreferenceActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.mypreferences);

    Preference button = (Preference)getPreferenceManager().findPreference("exitlink");      
    if (button != null) {
        button.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
            @Override
            public boolean onPreferenceClick(Preference arg0) {
                finish();   
                return true;
            }
        });     
    }
}
}
Dunfield
fuente
3
Funciona genial. Eso es brillante !
RRTW
8

Añadir

setContentView(R.layout.buttonLayout);

Abajo

addPreferencesFromResource(R.xml.yourPreference);

buttonLayout:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

<RelativeLayout
        android:id="@+id/top_control_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
</RelativeLayout>

<LinearLayout
        android:id="@+id/bottom_control_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true">

    <Button
            android:id="@+id/button"
            android:layout_width="match_parent"
            android:layout_height="70dp"
            android:text="@string/saveAlarm"/>
</LinearLayout>

<ListView
        android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="0dip"
        android:layout_above="@id/bottom_control_bar"
        android:layout_below="@id/top_control_bar"
        android:choiceMode="multipleChoice">
</ListView>

Botón de acceso por:

Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        //Your event
    }
});

Puede obtener el botón en la parte superior o inferior de la pantalla colocando el botón en RelativeLayout:

  • top_control_bar
  • barra_control_bajo

barra_control_bajo

Esto funcionó para mí. Espero poder ayudar a alguien con este código.

Thijs Limmen
fuente
Usé esto en mi aplicación, mantiene el botón en la parte superior de la lista que se ve mejor y es más fácil de usar para los botones Aceptar y Cancelar. Gracias.
Grux
1

No creo que haya una manera fácil de agregar un botón a una pantalla de preferencias. Las preferencias se limitan a:

EditTextPreference
ListPreference
RingtonePreference
CheckboxPreference

Mientras usa una pantalla de preferencias, está limitado al uso de estas opciones, y no hay una sola "preferencia de botón" que pueda usarse fácilmente para sus necesidades.

He estado buscando una funcionalidad similar, con agregar botones a la pantalla de preferencias, pero parece que necesita construir su propia pantalla para esto, administrando el cambio a las preferencias en su propia implementación.

Eric Nordvik
fuente
Tuve el mismo problema, si desea un botón en sus preferencias, debe usar una pantalla de prefijo propia :(
Janusz
1

¡Puedes hacerlo así para acceder al botón!

 View footerView = ((LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.layoutButtons, null, false);

No olvide agregar android:ida LinearLayout que contiene el botón en layoutButtons.xml , es decir android:id="@+id/mylayout"

 LinearLayout mLayout = (LinearLayout) footerView.findViewById(R.id.mylayout);
 Button login = (Button) footerView.findViewById(R.id.loginButton);
 login.setOnClickListener(this);
 ListView lv = (ListView) findViewById(android.R.id.list);
 lv.addFooterView(footerView);

 // Lines 2 and 3 can be used in the same way for a second Button!
Cha
fuente
no olvides marcar esta pregunta como VERDADERA si sientes que te ayudé en ella?
Shah
0

También puede personalizar el diseño de una Preferencia anulando Preference.onCreateView(parent). El siguiente ejemplo utiliza una clase interna anónima para hacer preferencias rojas.

    screen.addPreference(
        new Preference(context) {
            @Override
            protected View onCreateView(ViewGroup parent) {
                View view = super.onCreateView(parent);
                view.setBackgroundColor(Color.RED);
                return view;
            }
        });

Puede usar esta técnica para agregar un botón a la vista predeterminada.

Roger Keays
fuente
0

Si alguien llega a indicarle al usuario que haga clic en uno de los elementos de Preferencias y maneja ese clic y su solución se basa PreferenceFragmentCompat, entonces puede hacer esto:

<PreferenceScreen
...
>
...
<Preference
    android:key="@string/pref_key_clickable_item"
    android:persistent="false"
    android:title="Can be clicked"
    android:summary="Click this item so stuff will happen"/>
...
</PreferenceScreen>

Java:

@Override
onPreferenceTreeClick(Preference preference) {
    if (preference.getKey().equals(getContext().getString(R.string.pref_key_clickable_item))) {
       // user clicked the item
       // return "true" to indicate you handled the click
       return true;
    }
    return false;
}

Kotlin:

override fun onPreferenceTreeClick(preference: Preference): Boolean {
    if (preference.key == context?.getString(R.string.pref_key_clickable_ite)) {
       // user clicked the item
       // return "true" to indicate you handled the click
       return true
    }
    return false
}
Csaba Toth
fuente
0

Cree un diseño personalizado para el SettingsFragment.javaielayout_settings.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.settings.SettingsFragment"
    tools:ignore="NewApi">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appBarSettings"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppBarOverlay">

        <com.google.android.material.appbar.MaterialToolbar
            android:id="@+id/toolbarSettings"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:minHeight="?attr/actionBarSize"
            app:title="@string/fragment_title_settings" />
    </com.google.android.material.appbar.AppBarLayout>

    <!--this works as the container for the SettingsFragment.java
    put the code for the Button above or below this FrameLayout
    according to your requirement-->

    <FrameLayout
        android:id="@android:id/list_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
      app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />


    <com.google.android.material.button.MaterialButton
        android:id="@+id/btnSample"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|center"
        android:text="@string/button_sample_text" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

Luego, consulte el archivo de diseño en su styles.xml:

<style name="AppTheme" parent="....">
      ...............
      ...............
      <item name="preferenceTheme">@style/MyPreferenceThemeOverlay</item>
</style>

<style name="MyPreferenceThemeOverlay" parent="PreferenceThemeOverlay">
      <item name="android:layout>@layout/layout_settings</item>
</style>

Y luego, en el onViewCreated()método de tu SettingsFragment.java, puedes usar el botón de esta manera:

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle 
                             savedInstanceState) {

        MaterialButton btnSample = view.findViewById(R.id.btnSample);
        btnSample.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(requireContext(), "Sample Button 
                   clicked!!", Toast.LENGTH_LONG).show();
            }
        });
    }

Pantalla de configuración de muestra con botón

cgb_pandey
fuente
-1

pruebe android: onClick = "myMethod" funciona de maravilla para eventos onclick simples

Neelabh
fuente
44
Preferenceno tiene onClickpropiedad
ercan
La respuesta implica android:onClicken la vista del botón adjunto, no en la preferencia en sí.
Stan