Comment ajouter un bouton à PreferenceScreen

106

Existe-t-il un moyen d'ajouter un bouton au bas de l'écran des préférences et de les faire fonctionner correctement lors du défilement?

vlaku
la source
2
Avez-vous envisagé de créer une préférence personnalisée?
Prashast
2
Pour les futurs visiteurs, alors que la solution de Max fonctionne, il existe une solution alternative: stackoverflow.com/a/7251575/802469
Reed

Réponses:

249

Il existe une autre solution pour personnaliser l'apparence des préférences.

Concevez une mise en page XML normale avec des boutons ou tout ce que vous voulez ajouter aux préférences standard. Incluez un ListViewdans votre mise en page et donnez-lui l'ID @android:id/list.

Disons que nous appelons le fichier de mise en page res/layout/main.xml. Cela pourrait ressembler à ceci:

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

Dans votre PreferenceActivity, ajoutez ces deux lignes à votre onCreate:

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

Le ListViewdans votre mise en page sera alors remplacé par les préférences définies de la manière habituelle dans res/xml/preferences.xml.

Max
la source
10
Ne fonctionne pas lorsque le bouton est placé sous la vue de liste. Ne fonctionne pas lorsque l'activité des préférences utilise le thème de la boîte de dialogue.
Greg Ennis
11
La dernière documentation sur l'utilisation de PreferenceActivity sur developer.android.com/reference/android/preference/… mentionne que pour tout nouveau développement, PreferenceFragment est le moyen préféré de mise en œuvre. Il semble que la solution donnée ne fonctionnera pas dans un tel scénario.
Pankaj
4
Il ne défile toujours pas avec la liste.
Sudarshan Bhat
7
Je suis un peu déconcerté par le nombre de votes de cette réponse car elle ne répond pas réellement à la question d'origine. Il ne défile pas avec la liste et ne fonctionne pas lorsque le bouton est placé en bas de la vue, comme mentionné dans les commentaires ci-dessus.
howettl
1
@howettl remplace simplement fill_parent par wrap_content dans ListView layout_height
Martin Ch
56

Je sais que c'est un peu tard, mais je viens de trouver une solution que j'aime mieux que la solution appréciée de Max.

Vous pouvez simplement ajouter un pied de page (ou si vous souhaitez que le bouton soit en haut, un en-tête) à la ListView de PreferenceActivity comme ceci:

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

J'espère que ça aidera quelqu'un.

jpihl
la source
2
Au moins, cela se sent mieux comme solution de Max car elle ne repose pas sur les identifiants d'élément. Voyons comment il se comporte dans les futures versions d'Android ...
Daniel F
@DanielF. ne traversez pas le pont avant d'y être;)
jpihl
1
Je ne peux pas obtenir le ListViewavec PreferenceFragment :(
Michał K
1
Non, cela ne fonctionnerait pas de cette façon (car il PreferenceFragmenta sa propre liste), mais je l'ai résolu en créant simplement un Preferenceet en définissant un Intentdessus. Il n'était pas nécessaire de créer un bouton (du moins dans mon cas)
Michał K
1
Ne fonctionne pas avec PreferenceFragmentCompat, car getListView renverra en fait un RecyclerView
Mauker
11

Cet exemple ci-dessous rendra un bouton en bas de la page (au cas où quelqu'un serait toujours intéressé).

Dans le cas d'un LinearLayout, vous pouvez également appliquer des pondérations; cela est nécessaire car la Listview est définie sur * fill_parent *. Je fais généralement cela en ajoutant * android: layout_weight *:

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

L'explication ci-dessous n'est probablement pas à 100% mais elle vous aidera à comprendre ...

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

Vous pourriez aussi dire, parce que le bouton n'a pas de poids; le bouton est rendu à une hauteur de 0dp.

Maintenant, avec le layout_weigths ajouté, il laissera le bouton rendre 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
| +--
+--
Ronnie
la source
Désolé, j'ai raté le message de @stealthcopter
Ronnie
7

En fait, il existe une solution. Voici un code, j'espère, cela sera utile à tout le monde. Il ressemble à 3 options et 2 boutons en bas de l'écran, indépendamment de la résolution de l'écran (ciblé à 240 comme le plus bas)

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
la source
2

Il vous suffit d'utiliser PreferenceFragment dans l'activité générale et d'ajouter le bouton dans la mise en page de l'activité.

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

entrez la description de l'image ici

Albert
la source
J'ai suivi cette suggestion, et elle affiche le bouton en bas de la vue, mais il est superposé en haut de la liste des préférences et ne peut pas être cliqué (c'est-à-dire que cliquer sur le bouton active uniquement l'élément de préférence en dessous).
iaindownie
Le bouton onClickListener n'est pas déclenché avec cette solution
rdehuyss
@rdehuyss parce que vous devez ajouter onClickListener à buttonSave:)
Albert
1

Ce serait à quoi ressemble le code dans l'activité de l'exemple de ronny. Mon intention était de mettre un menu en bas de l'écran.

/** 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
la source
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>

Je fais référence à @Ronnie, utilise RelativeLayout et définit une hauteur pour layout_height de listview, puis définit le layout_alignParentBottom = "true" du bouton, il peut rendre un bouton au bas de PreferenceScreen; puis utilisez la méthode @Max. cela fonctionne pour mes besoins.

Mejonzhan
la source
C'est une bonne solution, mais vous avez oublié de définir la liste au-dessus du bouton. actuellement, les éléments de la liste peuvent se trouver derrière le bouton, ce qui n'est pas recommandé car s'il s'agit du dernier élément, il ne sera jamais visible et donc cliquable.
développeur android
oh, oui, vous avez raison, j'ai oublié ce cas, car ma liste n'afficher que 5 articles, merci.
Mejonzhan
veuillez mettre à jour votre réponse, afin que les autres n'aient pas ce comportement.
développeur android
Je pense que vous avez également oublié certains attributs et la balise de fin de relativeLayout.
développeur android
En fait, définir le bon listview_height peut résoudre le problème que vous avez dit.
Mejonzhan
1

Il est également possible d'ajouter des boutons d'action à la barre d'action pour une approche standard 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>
redevill
la source
0

Vue personnalisée dans Preference Activity, cela aidera à ajouter une vue personnalisée dans PreferenceActivity dans Android.

Créer main.xml, la seule vue nécessaire est un ListView, avec 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>

Créer 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
la source
0

Ce qui suit est une solution simple pour ajouter un bouton cliquable à votre écran de préférences. Ceci est rendu facile car les préférences réservent déjà l'espace dans l'android: widgetLayout et le bouton peuvent passer des clics avec android: onClick.

Créez d'abord un button.xml avec le contenu

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

Maintenant, dans votre preferences.xml, ajoutez la préférence

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

Votre PreferenceActivity ne doit plus contenir qu'un membre 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
la source
0

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

}
Dmitry
la source
0

J'ai trouvé que toutes les réponses ci-dessus n'étaient pas utilisables car les mises en page que j'ai créées pour `` envelopper '' le PreferenceScreenconteneur dans des mises en page personnalisées (puis ajouter un bouton sous le ListView) ne fonctionnaient pas réellement.

Ils superposaient uniquement la mise en page personnalisée en haut de la liste des préférences (flottante), et cliquer (par exemple) sur un nouveau bouton personnalisé n'appellerait que la préférence sous le bouton.

Cependant, j'ai trouvé cette solution qui fonctionne un régal pour ajouter un bouton sous le conteneur de liste de préférences, lors de l'utilisation PreferenceFragment.

iaindownie
la source