带有数字选择器的Android PreferenceActivity对话框

时间:2013-12-24 10:12:09

标签: android dialog numberpicker

我见过许多自定义解决方案和这个问题的答案。我需要一些非常简单的东西,我有一个偏好活动,我需要的是其中一个选项将打开带有数字选择器的对话框并保存结果。能否一步一步指导我如何完成这项工作?

public class SettingsActivity extends PreferenceActivity
{
    @Override
    protected void onCreate(final Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        getFragmentManager().beginTransaction().replace(android.R.id.content, new MyPreferenceFragment()).commit();
        //requestWindowFeature(Window.FEATURE_NO_TITLE);    
    }

    public static class MyPreferenceFragment extends PreferenceFragment
    {
        @Override
        public void onCreate(final Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.xml.prefs);

        }
    }

}

XML:          

    <SwitchPreference
        android:key="cross"
        android:summaryOff="Cross is invisible"
        android:summaryOn="Cross is visible"
        android:switchTextOff="OFF"
        android:switchTextOn="ON"
        android:title="Cross" 
        android:defaultValue="true"/>

    <SwitchPreference
        android:key="autoP"
        android:summaryOff="App will go to sleep"
        android:summaryOn="App will not go to sleep"
        android:switchTextOff="OFF"
        android:switchTextOn="ON"
        android:title="Always On" 
        android:defaultValue="true"/>

    <SwitchPreference
        android:key="tempD"
        android:summaryOff="Temprature not displayed"
        android:summaryOn="Temprature displayed"
        android:switchTextOff="OFF"
        android:switchTextOn="ON"
        android:title="Tempature Display" 
        android:defaultValue="true"/>

    <ListPreference
        android:entries="@array/units"
        android:entryValues="@array/lunits"
        android:key="listUnits"
        android:summary="Units schosssing"
        android:title="Units" android:defaultValue="C"/>

     <!--Need to add button to open dialog-->       

</PreferenceScreen>

Number Picker XML:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <NumberPicker
        android:id="@+id/numberPicker1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="64dp" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/numberPicker1"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="98dp"
        android:layout_toRightOf="@+id/numberPicker1"
        android:text="Cancel" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/button2"
        android:layout_alignBottom="@+id/button2"
        android:layout_marginRight="16dp"
        android:layout_toLeftOf="@+id/numberPicker1"
        android:text="Set" />

</RelativeLayout>

4 个答案:

答案 0 :(得分:52)

子类DialogPreference以构建您自己的NumberPickerPreference

我已经为你实现了一个。它工作得很好,但功能不完整。例如,最小值和最大值是硬编码常量。这些应该是首选xml声明的属性。要使其工作,您需要添加一个指定自定义属性的attrs.xml文件。

要在库项目中支持自定义xml属性的NumberPicker首选项小部件和显示如何使用它的演示应用程序的完整实现,请参阅GitHub:https://github.com/Alobar/AndroidPreferenceTest

您可以将窗口小部件用作任何其他首选项窗口小部件,除非您必须完全限定名称:

<强>的preferences.xml

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

    <com.example.preference.NumberPickerPreference
        android:key="key_number"
        android:title="Give me a number"
        android:defaultValue="55" />

</PreferenceScreen>

<强> NumberPickerPreference.java

package com.example.preference;

import android.content.Context;
import android.content.res.TypedArray;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.NumberPicker;

/**
 * A {@link android.preference.Preference} that displays a number picker as a dialog.
 */
public class NumberPickerPreference extends DialogPreference {

    // allowed range
    public static final int MAX_VALUE = 100;
    public static final int MIN_VALUE = 0;
    // enable or disable the 'circular behavior'
    public static final boolean WRAP_SELECTOR_WHEEL = true; 

    private NumberPicker picker;
    private int value;

    public NumberPickerPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public NumberPickerPreference(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected View onCreateDialogView() {
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        layoutParams.gravity = Gravity.CENTER;

        picker = new NumberPicker(getContext());
        picker.setLayoutParams(layoutParams);

        FrameLayout dialogView = new FrameLayout(getContext());
        dialogView.addView(picker);

        return dialogView;
    }

    @Override
    protected void onBindDialogView(View view) {
        super.onBindDialogView(view);
        picker.setMinValue(MIN_VALUE);
        picker.setMaxValue(MAX_VALUE);
        picker.setWrapSelectorWheel(WRAP_SELECTOR_WHEEL);
        picker.setValue(getValue());
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        if (positiveResult) {
            picker.clearFocus();
            int newValue = picker.getValue();
            if (callChangeListener(newValue)) {
                setValue(newValue);
            }
        }
    }

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

    @Override
    protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
        setValue(restorePersistedValue ? getPersistedInt(MIN_VALUE) : (Integer) defaultValue);
    }

    public void setValue(int value) {
        this.value = value;
        persistInt(this.value);
    }

    public int getValue() {
        return this.value;
    }
}

答案 1 :(得分:3)

这是我在androidx和kotlin中的操作方式:

NumberPickerPreference.kt

import android.content.Context
import android.util.AttributeSet
import androidx.preference.DialogPreference

class NumberPickerPreference(context: Context?, attrs: AttributeSet?) :
    DialogPreference(context, attrs) {

    override fun getSummary(): CharSequence {
        return getPersistedInt(INITIAL_VALUE).toString()
    }

    fun getPersistedInt() = super.getPersistedInt(INITIAL_VALUE)

    fun doPersistInt(value: Int) {
        super.persistInt(value)
        notifyChanged()
    }

    companion object {
        // allowed range
        const val INITIAL_VALUE = 50
        const val MIN_VALUE = 12
        const val MAX_VALUE = 100
    }
}

NumberPickerPreferenceDialog.kt

import android.content.Context
import android.os.Bundle
import android.view.View
import android.widget.NumberPicker
import androidx.preference.PreferenceDialogFragmentCompat


class NumberPickerPreferenceDialog : PreferenceDialogFragmentCompat() {
    lateinit var numberPicker: NumberPicker

    override fun onCreateDialogView(context: Context?): View {
        numberPicker = NumberPicker(context)
        numberPicker.minValue = NumberPickerPreference.MIN_VALUE
        numberPicker.maxValue = NumberPickerPreference.MAX_VALUE

        return numberPicker
    }

    override fun onBindDialogView(view: View?) {
        super.onBindDialogView(view)
        numberPicker.value = (preference as NumberPickerPreference).getPersistedInt()
    }

    override fun onDialogClosed(positiveResult: Boolean) {
        if (positiveResult) {
            numberPicker.clearFocus()
            val newValue: Int = numberPicker.value
            if (preference.callChangeListener(newValue)) {
                (preference as NumberPickerPreference).doPersistInt(newValue)
                preference.summary
            }
        }
    }

    companion object {
        fun newInstance(key: String): NumberPickerPreferenceDialog {
            val fragment = NumberPickerPreferenceDialog()
            val bundle = Bundle(1)
            bundle.putString(ARG_KEY, key)
            fragment.arguments = bundle

            return fragment
        }
    }
}

SettingsFragment.kt

import android.os.Bundle
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat

class SettingsFragment : PreferenceFragmentCompat() {
    private val DIALOG_FRAGMENT_TAG = "NumberPickerDialog"

    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
        setPreferencesFromResource(R.xml.settings, rootKey)
    }

    override fun onDisplayPreferenceDialog(preference: Preference?) {
        if (parentFragmentManager.findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) {
            return
        }
        if (preference is NumberPickerPreference) {
            val dialog = NumberPickerPreferenceDialog.newInstance(preference.key)
            dialog.setTargetFragment(this, 0)
            dialog.show(parentFragmentManager, DIALOG_FRAGMENT_TAG)
        } else
            super.onDisplayPreferenceDialog(preference)
    }
}

settings.xml

<your.package.NumberPickerPreference
        app:key="your_pref_key"
        app:title="@string/your_pref_title" />

希望这会有所帮助。

答案 2 :(得分:2)

实施DialogPreference是一个解决方案:

答案 3 :(得分:0)

基于ListPreference的简单解决方案,可随时添加值/条目:

root_preferences.xml:

<?php
session_start();
$out = $_SESSION["output"];
echo $out;
$data = preg_replace("/\{[^}]+\}/", "", $out);
$msg = trim($out, '{},');
$msg2 =  trim($msg, '"');
$msg3= str_replace('"','',$msg2);
echo $msg3;
?>

SettingsActivity.java:

<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto"
    ...

    <ListPreference
        app:key="myNumber"
        app:title="my title"
        app:useSimpleSummaryProvider="true"/>