Android: запретить диалог настроек для настроек, которые должны быть загружены по сети - PullRequest
2 голосов
/ 12 января 2011

Мое приложение имеет ListPreference, записи которого поступают из сетевого API.В onCreate () моего PreferenceActivity я порождаю фоновый поток, который выполняет вызов API, а затем заполняет записи ListPreference через одну или две секунды.

Если пользователь нажимает кнопку ListPreference на экране предпочтений передпараметры были загружены, я хочу запретить отображение диалогового окна настроек и вместо этого уведомить пользователя о том, что список параметров все еще загружается.

Я подозреваю, что правильный подход заключается в переопределении OnPreferenceClickListener, например так:

ListPreference dpref = (ListPreference) findPreference("debug");
String[] s = {"one", "two", "three"};
dpref.setEntries(s);
dpref.setEntryValues(s);
dpref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
    @Override
    public boolean onPreferenceClick(Preference preference) {
        Toast.makeText(this, "hi there", Toast.LENGTH_SHORT).show();
        return true;
    }
});

Показывается тост, но также отображается диалог выбора ListPreference.В документации OnPreferenceClickListener говорится, что onPreferenceClick должен возвращать true, если щелчок был обработан, но возвращение false дает тот же результат.

Как запретить отображение диалогового окна настроек?

Есть ли лучший способ обработки настроек, параметры которых необходимо загрузить перед просмотром?

Ответы [ 7 ]

6 голосов
/ 23 мая 2011

Я боролся с той же проблемой, но в более простой среде.Мой PreferenceScreen определен в XML-файле.Есть одно предпочтение, с которым я хочу справиться сам.Поэтому я просто помещаю объект «Preference» в xml-файл вместо «ListPreference» или «EditTextPreference»

    <Preference android:title="@string/preloadmaps1" android:summary="@string/preloadmaps2"
        android:key="preloadMaps" />

Теперь больше нет редактора, связанного с предпочтением, и я могу безопасно редактировать самостоятельнов "OnPreferenceClickListener"

5 голосов
/ 27 июня 2012

Ссылка на документ разработчика Android, который о showDialog :

Показывает диалог, связанный с этим предпочтением. Обычно это инициируется автоматически при нажатии на предпочтение. Вызывайте этот метод, если вам нужно показать диалоговое окно для какого-либо другого события.

Итак, когда предпочтение клика вызовет showDialog () автоматически, если вы хотите управлять, чтобы не показывать диалоговое окно при щелчке, вам нужно реализовать пользовательское предпочтение, например,

public class MyPreference extends ListPreference {
    private Context context;

    // a flag to control show dialog
    private boolean showDialog = false;

    public MyPreference(Context context) {
        super(context);
        this.context = context;
    }

    public MyPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;       
    }

    @Override
    protected void showDialog(Bundle state) {        
        if (showDialog) {
            // show dialog 
            super.showDialog(state);
        } else {
            // if you don't want to show a dialog when click preference
            return;
        } /* end of if */
    }
}
1 голос
/ 02 декабря 2014

Я знаю, что это старый вопрос, но до сих пор нет ответа, как отменить этот диалог.Итак, вот как вы можете отменить диалоговое окно настроек:

dpref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
    @Override
    public boolean onPreferenceClick(Preference preference) {
        ((ListPreference)preference).getDialog().dismiss();   <<< This will do it
        Toast.makeText(this, "hi there", Toast.LENGTH_SHORT).show();
        return true;
    }
});

Но вместо того, чтобы закрыть диалоговое окно, лучше скрыть его, чтобы иметь возможность показать его позже, когда список параметров загружен из Интернета.Так что:

dpref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
    @Override
    public boolean onPreferenceClick(Preference preference) {
        ((ListPreference)preference).getDialog().hide();   <<< This will just hide the dialog and you still can show it later
        Toast.makeText(this, "hi there", Toast.LENGTH_SHORT).show();
        return true;
    }
});

Позже, когда загружен список опций, выполните:

...
dpref.setEntries(<array_of_options_here>);
dpref.getdialog().show();  <<< If you dismiss the dialog earlier and not hide it, then getDialog() returns null here 
...
1 голос
/ 12 января 2011

Я не уверен, почему ваш путь не работает, но вот быстрое решение:

Добавить заглушку Предпочтение для каждого предпочтения, которое должно быть загружено.Вы можете настроить свое действие по клику любым удобным для вас способом.Диалоги не будут отображаться.

Когда ваши настройки предпочтений будут готовы, удалите старое предпочтение (по его имени) и создайте новый ListPreference (с тем же именем, что и у только что удаленного) с вашими параметрами.

Это даст вам возможность добавлять любые настраиваемые настройки для любого события, которое вам нужно.Хотя, как вы можете видеть, требуется дополнительное кодирование.

0 голосов
/ 01 июня 2018

Еще один способ для коллекции.Я считаю, что это работает только с библиотекой android.support.v7.preference и PreferenceFragmentCompat (27.1.1 в моем случае).Вот пример:

public class PrefsFragment extends PreferenceFragmentCompat implements PreferenceFragmentCompat.OnPreferenceDisplayDialogCallback {

    private static final int REQUEST_VIEW_PREFERENCE = 1;

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_VIEW_PREFERENCE && resultCode == Activity.RESULT_OK) {
            Preference preference = findPreference("preference_key");
            getPreferenceManager().showDialog(preference)
        }
    }

    @Override
    public Fragment getCallbackFragment() {
        this;
    }

    @Override
    public boolean onPreferenceDisplayDialog(PreferenceFragmentCompat caller, Preference pref) {
        if (pref.getKey().equals("preference_key")) {
            if (canBeOpened(pref)) {
                return false;
            } else {
                // show a fragment loading data with requestCode == REQUEST_VIEW_PREFERENCE
                ...
                return true;
            }
        }
    }

    private boolean canBeOpened(Preference pref) {
        // check whether a preference can be clicked
        ...
    }
}

Если я правильно понял исходный код Preference.java, OnPreferenceClickListener, возвращающий true, работает только для предпочтений, основанных на намерениях, но игнорируется, если появится диалоговое окно.

В приведенном выше примере OnPreferenceDisplayDialogCallback используется для предотвращения отображения диалоговых окон настроек.Важно вернуть фрагмент, реализующий этот интерфейс, из getCallbackFragment().

0 голосов
/ 29 января 2011

вы можете сделать следующее в onResume() в вашем предпочтении:

  • начать async call с ...
    • установить предпочтение на отключение с подсказкойчто значения извлекаются
    • сеть для извлечения значений (либо когда она не имеет значений, либо всегда) - асинхронно, поэтому она не останавливает возобновление
    • обновляет запись предпочтения с выбранными вамизначения
    • включают предпочтение и показывают подсказку по умолчанию

Недостаток, если это так, что ваши предпочтения будут обновляться слишком часто (например, всегда, когда вашэкран предпочтений запускается), но с этим вы можете справиться со случаем, когда результат сетевого вызова выдает список, в котором ранее выбранного значения больше нет (например, покажите пользователю диалоговое окно, в котором говорится, что его выбор больше не доступен).

Кроме того, это довольно сложная задача (поскольку вы должны определить Handler, потому что асинхронное выполнение живет в другом потоке ...)

Это выглядело бычто-то вроде этого (при условии, что вы делаете это в своем PreferenceActivity)

import android.os.Handler;
import android.os.AsyncTask;
import android.os.Message;

public class xyz extends PreferenceActivity {
    ...
    // define a handler to update the preference state
    final Handler handler = new Handler() {
        public void handleMessage( Message msg ) {
            ListPreference dpref = (ListPreference) getPreferenceManager().findPreference("debug");
            dpref.setEnabled( msg.getData().getBoolean("enabled") );
            dpref.setSummary( msg.getData().getString("summary") );
        }
    };



    private class updatePref extends AsyncTask<Void, Void, Void> {

        @Override
        protected Void doInBackground(Void... arg) {

            Message msg = handler.obtainMessage();
            Bundle data = new Bundle();
            data.putBoolean("enabled", false ); // disable pref
            data.putString("summary", "Getting vals from network..." ); // set summary
            msg.setData( data );
            handler.sendMessage(msg); // send it do the main thread

            ListPreference dpref = (ListPreference) getPreferenceManager().findPreference("debug");


            String values[];
            // call network function and let it fill values[]

            // do things according to the returned values, 
            // eg check if there are any, check if the user has 
            // already selected one, display a message if the 
            // user has selected one before but the values do not
            // contain them anymore, ...

            // set the new values     
            dpref.setEntries(values);
            dpref.setEntryValues(values);

            data.putBoolean("enabled", true ); // enable pref
            data.putString("summary", "Please choose" ); // set summary
            msg.setData( data );
            handler.sendMessage(msg); // send it do the main thread

            return null;
        }
    }

    public void onResume() {
        ....
        new updatePref().execute();

    }

}

Конечно, вы можете позвонить new updatePref().execute() в любом месте, так что вы также можете привязать его к Button, onCreate() или где угодно(нет необходимости делать это в onResume()).

0 голосов
/ 12 января 2011

Я бы использовал прокси Activity (в стиле диалога), который загружает настройки и запускает фактический PreferenceActivity после завершения.

...