Можно ли загружать элементы ListPreference из адаптера?

Я собираюсь создать действие настроек для своего приложения. Я определил PreferenceActivity с хорошим макетом, включая объект ListPreference, чтобы пользователь мог выбрать устройство Bluetooth. У меня возникли проблемы с динамическим заполнением списка.

Я хочу заполнить ListPreference значениями из адаптера массива (который я создам и заполню соответствующими именами устройств Bluetooth).

Если бы это был вращающийся вид, я мог бы просто вызвать setAdapter(). Однако с объектом ListPreference я не могу понять, как подключить адаптер (findviewByID не будет выполнять преобразование из представления в ListPreference, поэтому я даже не могу получить дескриптор объекта).

Я хотел бы подключить адаптер, а затем заполнить адаптер значениями, которые, в свою очередь, заполнили бы ListPreference значениями.


person Brad Hein    schedule 29.05.2010    source источник


Ответы (4)


ListPreference не работает с адаптерами, работает со строками. См. setEntries() и < a href="http://developer.android.com/reference/android/preference/ListPreference.html#setEntryValues(java.lang.CharSequence[])" rel="noreferrer">setEntryValues()

Чтобы получить ListPreference, вызовите findPreference() на вашем PreferenceActivity. Бросьте Preference, и вы вернетесь к ListPreference.

person CommonsWare    schedule 30.05.2010
comment
Это не так, вы можете установить адаптер для билдера в обратном вызове onPrepareDialogBuilder. - person Bako; 19.08.2020

Для особого случая списка устройств Bluetooth вы можете использовать следующий класс:

package de.duenndns;

import android.bluetooth.*;
import android.content.Context;
import android.preference.ListPreference;
import android.util.AttributeSet;

import java.util.Set;

public class BluetoothDevicePreference extends ListPreference {

    public BluetoothDevicePreference(Context context, AttributeSet attrs) {
        super(context, attrs);

        BluetoothAdapter bta = BluetoothAdapter.getDefaultAdapter();
        Set<BluetoothDevice> pairedDevices = bta.getBondedDevices();
        CharSequence[] entries = new CharSequence[pairedDevices.size()];
        CharSequence[] entryValues = new CharSequence[pairedDevices.size()];
        int i = 0;
        for (BluetoothDevice dev : pairedDevices) {
            entries[i] = dev.getName();
            if (entries[i] == null) entries[i] = "unknown";
            entryValues[i] = dev.getAddress();
            i++;
        }
        setEntries(entries);
        setEntryValues(entryValues);
    }

    public BluetoothDevicePreference(Context context) {
        this(context, null);
    }

}

Его можно использовать непосредственно из XML-файла prefs для хранения MAC-адреса в виде строки prefs:

<de.duenndns.BluetoothDevicePreference
    android:key="bluetooth_mac"
    android:title="Bluetooth Device"
    android:dialogTitle="Choose Bluetooth Device" />
person ge0rg    schedule 26.01.2011
comment
Прежде всего: спасибо всем за этот фрагмент кода. Это работает хорошо. но у меня проблема с рендерингом в превью в AS. Rendering Problems java.lang.NullPointerException   at de.jphjung.speedcamssiegerland.BluetoothDevicePreference.<init>(BluetoothDevicePreference.java:20)   at java.lang.reflect.Constructor.newInstance(Constructor.java:423)   at android.preference.GenericInflater.createItem(GenericInflater.java:385) [...and some more...too much for that character limit here] - person beta; 05.11.2016

Просто обновление на случай, если появится кто-то еще, ответ ge0rg работает, но немного изменил его, чтобы учесть несколько предпочтений, а не только Bluetooth, а также если у них нет настроенных сопряженных устройств, чтобы вы не получили ошибку с нулевым массивом.

ListPreference BTList = (ListPreference) findPreference("your preference key");
    BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
    CharSequence[] entries = new CharSequence[1];
    CharSequence[] entryValues = new CharSequence[1];
    entries[0] = "No Devices";
    entryValues[0] = "";
    if(pairedDevices.size() > 0){
        entries = new CharSequence[pairedDevices.size()];
        entryValues = new CharSequence[pairedDevices.size()];
        int i=0;
        for(BluetoothDevice device : pairedDevices){
            entries[i] = device.getName();
            entryValues[i] = device.getAddress();
            i++;
        }
    }
    BTList.setEntries(entries);
    BTList.setEntryValues(entryValues);

`Надеюсь, это поможет кому-то... о, и это помещается в метод onCreate для действия предпочтений

person DRing    schedule 15.06.2011

Другой способ — переопределить onPrepareDialogBuilder. ListPreference и инициализировать setSingleChoiceItems AlertDialog.Builder непосредственно с вашим адаптером:

public class AdapterListPreference extends ListPreference
{
    @Override
    protected void onPrepareDialogBuilder( AlertDialog.Builder builder )
    {
        // don't call super.onPrepareDialogBuilder() because it'll check
        // for Entries and set up a setSingleChoiceItems() for them that
        // will never be used

        final ListAdapter adapter = …;

        builder.setSingleChoiceItems(
            adapter,
            0,
            new DialogInterface.OnClickListener()
            {
                @Override
                public void onClick( DialogInterface dialog, int which )
                {
                    // adapter.getItemId( which )

                    dialog.dismiss();
                }
            } );

        builder.setPositiveButton( null, null );
    }
}

Если вы посмотрите на исходники Android, вы обнаружите, что onPrepareDialogBuilder() действительно вызывает:

public AlertDialog.Builder setSingleChoiceItems (CharSequence[] items, int checkedItem, DialogInterface.OnClickListener listener)

с этими входными массивами. Чтобы заставить ListPreference использовать какой-либо адаптер (например, ArrayAdaper, CursorAdapter), вам просто нужно вызвать:

public AlertDialog.Builder setSingleChoiceItems (ListAdapter adapter, int checkedItem, DialogInterface.OnClickListener listener)

вместо.

Таким образом, ListPreference будет работать с адаптером напрямую, и вам не нужно копировать данные из адаптера, чтобы поместить их в массивы записей.

Найдите рабочий пример здесь .

person mf511    schedule 03.07.2013