自定义首选项,targetSdkVersion =“11”:缺少缩进?

时间:2011-04-22 15:30:58

标签: android android-3.0-honeycomb android-preferences

我有几个自定义的DialogPreference实现,例如this one

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 with messed-up custom 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>

任何人都知道我哪里出错了?

谢谢!


更新

包含此自定义首选项的

Here is a link to a project和一个演示此问题的简单首选项XML文件。即使只有两个Java类,首选项XML和arrays.xml文件,我也会遇到这种现象。来自这个项目的Here is a compiled APK

5 个答案:

答案 0 :(得分:13)

(来自associated android-developers thread的交叉发布)

好的,我明白了。

首选项上有三种可能的构造函数:

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

沿着这条线的某个地方,我找到了拥有的模式 单参数构造函数链到双参数构造函数 (将null传递给第二个参数),并具有双参数 构造函数链到三参数构造函数(传递0表示 第三个参数)。

这不是正确的答案。

我希望正确的答案是只实施第二个 构造函数,因为正确的默认样式是Android内部的 (com.android.internal.R.attr.dialogPreferenceStyle)。第二 构造函数是与膨胀首选项XML一起使用的构造函数。

感谢大家的帮助!

答案 1 :(得分:6)

你可以使用void Preference.setWidgetLayoutResource(int widgetLayoutResId)方法跳舞,虽然我更喜欢在我的自定义Preference类中覆盖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;
}

可以下载基于http://robobunny.com代码的SeekBarPreference类的源代码here image1 image2

答案 2 :(得分:1)

我在模拟器上尝试了你的代码。您提供的代码没有问题,并且所有行都具有相同的格式;但它们看起来与第三种偏好(Lunch Alarm Time)的相似(格式)与其他偏好相似。

看起来其他三个首选项的缩进超过了要求。因此,您可能使用了一些全局格式样式,但未被TimePreference首选项获取。

编辑:好的。所以,上述内容并非(完全)正确。当我尝试将目标sdk设置为HoneyComb时,肯定存在问题。但是,在将PreferenceActivity类的主题设置为android:theme="@android:style/Theme.Black"时,所有首选项的外观都会保持一致,如下所示。

enter image description here

此样式与Froyo类似,但不是HoneyComb;在后者中,标题字体较小,并且有更多缩进。可能默认主题没有分配给Custom Preferences - 只是一个猜测:)一个解决方法是明确地将默认主题分配给您的首选项活动,但我不知道HoneyComb中的默认主题是什么(以及是否可以设置。

答案 3 :(得分:1)

帮助我的解决方案:

我已经取代了

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

正如你所看到的,我用 ctxt.getResources()替换了第三个参数 0 .getSystem()。getIdentifier(&#34; dialogPreferenceStyle&#34;,&#34; attr& #34;,&#34; android&#34;)在自定义首选项类的第二个构造函数中。

答案 4 :(得分:1)

使接受的答案更清楚。你只需要这个构造函数:

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