Пользовательские настройки, targetSdkVersion =»11″: отсутствует отступ?

#android #android-3.0-honeycomb #android-preferences

#Android #android-3.0-honeycomb #android-настройки

Вопрос:

У меня есть пара пользовательских DialogPreference реализаций, плавающих вокруг, таких как эта:

 package apt.tutorial;

import android.content.Context;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.TimePicker;

public class TimePreference extends DialogPreference {
    private int lastHour=0;
    private int lastMinute=0;
    private TimePicker picker=null;

    public static int getHour(String time) {
        String[] pieces=time.split(":");

        return(Integer.parseInt(pieces[0]));
    }

    public static int getMinute(String time) {
        String[] pieces=time.split(":");

        return(Integer.parseInt(pieces[1]));
    }

    public TimePreference(Context ctxt) {
        this(ctxt, null);
    }

    public TimePreference(Context ctxt, AttributeSet attrs) {
        this(ctxt, attrs, 0);
    }

    public TimePreference(Context ctxt, AttributeSet attrs, int defStyle) {
        super(ctxt, attrs, defStyle);

        setPositiveButtonText("Set");
        setNegativeButtonText("Cancel");
    }

    @Override
    protected View onCreateDialogView() {
        picker=new TimePicker(getContext());

        return(picker);
    }

    @Override
    protected void onBindDialogView(View v) {
        super.onBindDialogView(v);

        picker.setCurrentHour(lastHour);
        picker.setCurrentMinute(lastMinute);
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        super.onDialogClosed(positiveResult);

        if (positiveResult) {
            lastHour=picker.getCurrentHour();
            lastMinute=picker.getCurrentMinute();

            String time=String.valueOf(lastHour) ":" String.valueOf(lastMinute);

            if (callChangeListener(time)) {
                persistString(time);
            }
        }
    }

    @Override
    protected Object onGetDefaultValue(TypedArray a, int index) {
        return(a.getString(index));
    }

    @Override
    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
        String time=null;

        if (restoreValue) {
            if (defaultValue==null) {
                time=getPersistedString("00:00");
            }
            else {
                time=getPersistedString(defaultValue.toString());
            }
        }
        else {
            time=defaultValue.toString();
        }

        lastHour=getHour(time);
        lastMinute=getMinute(time);
    }
}
  

Они работают просто отлично. Однако в приложении с android:targetSdkVersion="11" определенными, на XOOM, они обнаруживают отсутствие отступа, когда в PreferenceActivity :

PreferenceActivity с перепутанным пользовательским DialogPreference

Кроме того, размер шрифта кажется немного больше, по крайней мере, для заголовка.

Там нет ничего, DialogPreference где я действительно переопределяю любое поведение форматирования для этого материала, AFAIK. Предпочтительный XML ничем не примечателен, кроме ссылки на вышеупомянутый класс:

 <PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android">
    <ListPreference
        android:key="sort_order"
        android:title="Sort Order"
        android:summary="Choose the order the list uses"
        android:entries="@array/sort_names"
        android:entryValues="@array/sort_clauses"
        android:dialogTitle="Choose a sort order" />
    <CheckBoxPreference
        android:key="alarm"
        android:title="Sound a Lunch Alarm"
        android:summary="Check if you want to know when it is time for lunch" />
    <apt.tutorial.TimePreference
        android:key="alarm_time"
        android:title="Lunch Alarm Time"
        android:defaultValue="12:00"
        android:summary="Set your desired time for the lunch alarm"
        android:dependency="alarm" />
    <CheckBoxPreference
        android:key="use_notification"
        android:title="Use a Notification"
        android:defaultValue="true"
        android:summary="Check if you want a status bar icon at lunchtime, or uncheck for a full-screen notice"
        android:dependency="alarm" />
</PreferenceScreen>
  

Кто-нибудь знает, где я ошибаюсь?

Спасибо!


Обновить

Вот ссылка на проект, который содержит это пользовательское предпочтение и простой XML-файл предпочтений, демонстрирующий проблему. Даже всего с двумя классами Java, предпочтительным XML и arrays.xml файлом, я получаю это явление. Вот скомпилированный APK из этого проекта.

Комментарии:

1. Вам следует пойти спросить Марка Мерфи — он знает все 🙂

2. @JohnnyLambada: Я пробовал это, но фронт-офис Green Bay Packers отказался от комментариев. О, подождите. Вы не имели в виду goo.gl/KNYOu ? 🙂

3. Всегда приятно столкнуться с той же проблемой, что и у Марка Мерфи. Если он не может легко разобраться, тогда я не чувствую себя так плохо.

Ответ №1:

(перекрестная публикация из связанного потока Android-разработчиков)

Хорошо, я разобрался.

Для предпочтения есть три возможных конструктора:

 MyPreference(Context ctxt)
MyPreference(Context ctxt, AttributeSet attrs)
MyPreference(Context ctxt, AttributeSet attrs, int defStyle)
  

Где-то по ходу дела я уловил закономерность наличия
цепочка из однопараметрического конструктора к двухпараметрическому конструктору
(передается null для 2-го параметра) и имеет двухпараметрический
цепочка конструктора к конструктору с тремя параметрами (передача 0 для
3-й параметр).

И это неправильный ответ.

Я надеюсь, что правильный ответ заключается в реализации только второго конструктора, потому что правильный стиль по умолчанию является внутренним для Android ( com.android.internal.R.attr.dialogPreferenceStyle ). Второй конструктор — это тот, который используется для раздувания XML-настроек.

Спасибо всем за помощь!

Комментарии:

1. Можно ли просто поместить «com.android.internal.R.attr.dialogPreferenceStyle» вместо 0 в качестве третьего атрибута, который передается третьему конструктору? Некоторое время назад у меня была та же проблема, что и у вас, и в конце концов я отказался от нее.

2. @TenFour04: У вас нет доступа к com.android.internal.R.attr.dialogPreferenceStyle .

3. Ну, это не весело. Я не понимаю, почему определенные ресурсы ограничены, а другие нет. Например, вы можете использовать list_selector_background, но не list_selector_holo_dark. Спасибо.

4. @Maxim: Да, внедрение двухпараметрического конструктора для привязки к суперклассу решило проблему.

5. Это работает, если мы расширим предпочтение от одного из стандартных предпочтений, таких как EditPreference. Что, если мы создадим пользовательский макет для наших предпочтений и расширим его из базового класса предпочтений? Я не могу получить это по назначению. Интересно, пробовали ли вы подобный случай?

Ответ №2:

Вы можете поработать с void Preference.setWidgetLayoutResource(int widgetLayoutResId) методом, хотя я предпочитаю переопределить View Preference.onCreateView(ViewGroup parent) метод в моем пользовательском классе настроек и взломать его, добавив пользовательские представления чуть ниже @android:id/summary (используйте утилиту hierarchyviewer для получения подробной информации).

Полный метод:

 @Override
protected View onCreateView(ViewGroup parent)
{
    View ret = super.onCreateView(parent);

    View summary = ret.findViewById(android.R.id.summary);
    if (summary != null)
    {
        ViewParent summaryParent = summary.getParent();
        if (summaryParent instanceof ViewGroup)
        {
            final LayoutInflater layoutInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            ViewGroup summaryParent2 = (ViewGroup) summaryParent;
            layoutInflater.inflate(R.layout.seek_bar_preference, summaryParent2);

            seekBar = (SeekBar) summaryParent2.findViewById(R.id.seekBar);
            seekBar.setMax(maxValue - minValue);
            seekBar.setOnSeekBarChangeListener(this);

            statusText = (TextView) summaryParent2.findViewById(R.id.seekBarPrefValue);

            unitsRightView = (TextView) summaryParent2.findViewById(R.id.seekBarPrefUnitsRight);
            unitsLeftView = (TextView) summaryParent2.findViewById(R.id.seekBarPrefUnitsLeft);
        }
    }

    return ret;
}
  

Исходный код моего класса SeekBarPreference основан на коде из http://robobunny.com можно загрузить здесь
изображение 1
изображение 2

Ответ №3:

Я попробовал ваш код на эмуляторе. С приведенным вами кодом проблем нет, и все строки имеют одинаковое форматирование; но все они выглядят более похожими (по формату) на третье предпочтение ( Lunch Alarm Time ), чем остальные.

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

РЕДАКТИРОВАТЬ: ОК. Итак, вышесказанное не является (полностью) правдой. Определенно возникла проблема, когда я попытался установить целевой sdk на HoneyComb . Но при настройке темы для PreferenceActivity класса как android:theme="@android:style/Theme.Black" , все настройки выглядят согласованно, как показано ниже.

введите описание изображения здесь

Этот стиль похож на Froyo , но не на HoneyComb ; в последнем шрифт заголовка меньше, а отступ больше. Вероятно, тема по умолчанию не назначается Custom Preferences — просто предположение 🙂 Обходным путем было бы явно назначить тему по умолчанию для вашего предпочтительного действия, но я не знаю, какая тема по умолчанию в HoneyComb (и можно ли ее установить).

Комментарии:

1. @Rajath DSouza: В эмуляторе 3.0 я получаю такое же поведение, как и в XOOM. Какой эмулятор вы пробовали?

2. Я попробовал это с помощью эмулятора Android SDK с целевым значением, установленным на Android 3.0 (API level 11) , и обложкой на WXGA .

3. @Rajath DSouza: Как совершенно странно. У меня вообще нет стилей в этом конкретном проекте, так что это не похоже на источник проблемы. Мне придется еще немного поэкспериментировать и попытаться немного сузить проблему.

4. @Rajath DSouza: Просто для подтверждения — у вас android:targetSdkVersion="11" в вашем манифесте не просто установлено значение 11 для цели сборки, верно?

5. @CommonsWare: Нет, похоже, что я все это время связывался с Froyo (остатками предыдущего проекта в Eclipse). Когда я установил android:targetSdkVersion="11" , я вижу ту же ошибку, что и у вас: D … Извините, что ввел вас в заблуждение.

Ответ №4:

Решение, которое помогло мне:

Я заменил

 public TimePreference(Context ctxt, AttributeSet attrs) {
    this(ctxt, attrs, 0);
}
  

с

 public TimePreference(Context ctxt, AttributeSet attrs) {
    this(ctxt, attrs, ctxt.getResources().getSystem().getIdentifier("dialogPreferenceStyle", "attr", "android"));
}
  

Как вы можете видеть, я заменил третий аргумент 0 на ctxt.getResources().getSystem().getIdentifier(«dialogPreferenceStyle», «attr», «android») во втором конструкторе класса пользовательских настроек.

Комментарии:

1. Спасибо. Для меня это очень полезно.

Ответ №5:

Чтобы сделать принятый ответ более понятным. Вам нужен только этот конструктор:

 public TimePreference(Context ctxt, AttributeSet attrs) {
    // this(ctxt, attrs, 0); // wrong
    super(ctxt, attrs); 
}