Jak dodać przycisk do PreferenceScreen

106

Czy jest jakiś sposób, aby dodać przycisk u dołu ekranu preferencji i sprawić, by działały poprawnie podczas przewijania?

vlaku
źródło
2
Czy spojrzałeś na tworzenie niestandardowych preferencji?
Prashast
2
Dla przyszłych odwiedzających, podczas gdy rozwiązanie Maxa działa, istnieje alternatywne rozwiązanie: stackoverflow.com/a/7251575/802469
Reed

Odpowiedzi:

249

Istnieje inne rozwiązanie umożliwiające dostosowanie wyglądu preferencji.

Zaprojektuj normalny układ XML z przyciskami lub czymkolwiek, co chcesz dodać do standardowych preferencji. Uwzględnij ListVieww swoim układzie i nadaj mu identyfikator @android:id/list.

Powiedzmy, że nazywamy plik układu res/layout/main.xml. Może to wyglądać mniej więcej tak:

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

W swoim PreferenceActivity, dodaj te dwie linie do onCreate:

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

W ListViewtwoim układzie zostaną wtedy zastąpione preferencjami zdefiniowanymi w zwykły sposób res/xml/preferences.xml.

Maks
źródło
10
Nie działa, gdy przycisk znajduje się poniżej widoku listy. Nie działa, gdy aktywność preferencji używa motywu okna dialogowego.
Greg Ennis
11
Najnowsza dokumentacja dotycząca korzystania z PreferenceActivity pod adresem developer.android.com/reference/android/preference/ ... wspomina, że ​​w przypadku wszystkich nowych programów preferowanym sposobem implementacji jest PreferenceFragment. Wydaje się, że dane rozwiązanie nie zadziała w takim scenariuszu.
Pankaj
4
Nadal nie przewija się wraz z listą.
Sudarshan Bhat,
7
Jestem trochę zaskoczony tym, ile głosów ma ta odpowiedź, ponieważ tak naprawdę nie odpowiada ona na pierwotne pytanie. Nie przewija się wraz z listą i nie działa, gdy przycisk jest umieszczony u dołu widoku, jak wspomniano w komentarzach powyżej.
howettl
1
@howettl po prostu zmień fill_parent na wrap_content w układzie ListView layout_height
Martin Ch
56

Wiem, że to trochę za późno, ale właśnie znalazłem rozwiązanie, które lubię bardziej niż chwalone rozwiązanie Maxa.

Możesz po prostu dodać stopkę (lub, jeśli chcesz, aby przycisk był na górze, nagłówek) do ListView PreferenceActivity w następujący sposób:

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

Mam nadzieję, że to komuś pomoże.

jpihl
źródło
2
Przynajmniej wydaje się to lepsze jako rozwiązanie Maxa, ponieważ nie opiera się na identyfikatorach elementów. Zobaczmy, jak zachowa się w przyszłych wersjach Androida ...
Daniel F
@DanielF. nie przechodź przez most, dopóki do niego nie
dojdziesz
1
Nie mogę dostać ListViewz PreferenceFragment :(
Michał K
1
Nie, to by nie działało w ten sposób (ponieważ PreferenceFragmentma własną listę), ale rozwiązałem to, po prostu tworząc Preferencei ustawiając Intentna nim. Nie było potrzeby tworzenia guzika (przynajmniej w moim przypadku)
Michał K
1
Nie działa z PreferenceFragmentCompat, ponieważ getListView w rzeczywistości zwróci RecyclerView
Mauker
11

Poniższy przykład wyrenderuje przycisk u dołu strony (na wypadek, gdyby ktoś był nadal zainteresowany).

W przypadku LinearLayout można również zastosować wagi; jest to potrzebne, ponieważ Listview jest ustawiony na * fill_parent *. Zwykle robię to, dodając * 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>

Poniższe wyjaśnienie nie jest prawdopodobnie w 100%, ale pomoże ci zrozumieć ...

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

Można też powiedzieć, że Button nie ma wagi; przycisk jest renderowany z wysokością 0 dp.

Teraz po dodaniu layout_weigths pozwoli to renderować przycisk 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
źródło
Przepraszam, że przegapiłem wpis @stealthcopter
Ronnie
7

Właściwie jest rozwiązanie. Oto kod, mam nadzieję, że przyda się każdemu. Wygląda na to, że 3 opcje i 2 przyciski u dołu ekranu, niezależnie od rozdzielczości ekranu (było ustawione na 240 jako najniższą)

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
źródło
2

Wystarczy użyć PreferenceFragment w ramach ogólnego działania i dodać przycisk do układu działania.

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>

ustawienie_czynności

wprowadź opis obrazu tutaj

Albert
źródło
Postępowałem zgodnie z tą sugestią i faktycznie wyświetla przycisk u dołu widoku, ale jest nałożony na górę listy preferencji i nie można go kliknąć (tj. Kliknięcie przycisku aktywuje tylko element preferencji poniżej).
iaindownie
Przycisk onClickListener nie jest uruchamiany przy użyciu tego rozwiązania
rdehuyss
@rdehuyss to, ponieważ musisz dodać onClickListener do buttonSave:)
Albert
1

Tak będzie wyglądał kod w działaniu na przykładzie Ronny'ego. Moim zamiarem było umieszczenie menu w dolnej części ekranu.

/** 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
źródło
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>

Odwołuję się do @Ronnie, używam RelativeLayout i ustawiam wysokość dla layout_height widoku listy, a następnie ustawiam layout_alignParentBottom przycisku = "true". Może on renderować przycisk na dole PreferenceScreen; następnie użyj drogi @Max. działa na moje potrzeby.

Mejonzhan
źródło
To fajne rozwiązanie, ale zapomniałeś ustawić widok listy nad przyciskiem. obecnie elementy widoku listy mogą znajdować się za przyciskiem, co nie jest zalecane, ponieważ jeśli jest to ostatnia pozycja, nigdy nie będzie widoczna i dlatego można ją kliknąć.
programista Androida
o tak, masz rację, zapomniałem o tej sprawie, ponieważ mój listview tylko 5 pozycji, dzięki.
Mejonzhan
zaktualizuj swoją odpowiedź, aby inni nie mieli tego zachowania.
programista Androida
Myślę, że zapomniałeś również o niektórych atrybutach i tagu końcowym RelativeLayout.
programista Androida
W rzeczywistości ustawienie odpowiedniego parametru listview_height może rozwiązać problem, który powiedziałeś.
Mejonzhan
1

Możliwe jest również dodanie przycisków akcji do paska akcji w przypadku standardowego podejścia systemu 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
źródło
0

Widok niestandardowy w działaniu Preference pomoże to dodać widok niestandardowy w PreferenceActivity w systemie Android.

Tworzenie main.xml, jedyny widok to konieczne ListView, o identyfikatorze 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>

Utwórz 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
źródło
0

Poniżej przedstawiono proste rozwiązanie umożliwiające dodanie klikalnego przycisku do ekranu preferencji. Jest to łatwe, ponieważ preferencje już rezerwują miejsce w android: widgetLayout, a przycisk może przechodzić przez kliknięcia z android: onClick.

Najpierw utwórz plik button.xml z zawartością

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

Teraz w Twoim preferencjach.xml dodaj preferencję

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

Twoja PreferenceActivity musi teraz zawierać tylko element członkowski 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
źródło
0

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

}
Dmitrij
źródło
0

Zauważyłem, że wszystkie powyższe odpowiedzi są nie do użytku, ponieważ wszelkie układy, które utworzyłem w celu „zawinięcia” PreferenceScreenkontenera w niestandardowe układy (a następnie dodanie przycisku poniżej ListView) w rzeczywistości nie działały.

Nakładali tylko układ niestandardowy na górę listy preferencji (ruchomy), a kliknięcie (np.) Nowego przycisku niestandardowego wywołałoby tylko preferencję znajdującą się pod przyciskiem.

Jednak znalazłem to rozwiązanie, które działa świetnie, dodając przycisk poniżej kontenera listy preferencji podczas używania PreferenceFragment.

iaindownie
źródło