web-dev-qa-db-fra.com

création d'une DialogPreference à partir de XML

J'ai essayé d'utiliser un Android.preference.DialogPreference gonflé à partir de XML, mais la documentation semble manquer de quelques bits essentiels, et je ne trouve aucun exemple de travail nulle part. Mon XML ressemble maintenant à ceci (j'ai essayé de nombreuses permutations mais cela semble être un minimum raisonnable):

<DialogPreference
Android:key="funThing" Android:title="Fun Thing"
Android:dialogLayout="@layout/fun_layout"
Android:positiveButtonText="OK"
Android:negativeButtonText="Cancel"
/>

Ma supposition à ce stade est qu'il est nécessaire de sous-classer DialogPreference et de ne pas l'utiliser directement. D'une part, je ne peux pas trouver un moyen d'associer la valeur de préférence réelle à un élément dans la boîte de dialogue elle-même, qui à la réflexion est une sorte de cadeau. Et aussi, en regardant la source de DialogPreference.Java semble le confirmer. Et je viens également de remarquer que la documentation officielle le désigne comme une "classe de base". Mais au moins, ce serait bien d'établir une source définitive sur le net qui aiderait les prochains N à comprendre cela plus rapidement que moi.

Pour mémoire, le fichier journal ressemble à ceci:

I/ActivityManager(   61): Starting: Intent { cmp=org.jeremy.Android/.PreferencesActivity } from pid 2755
W/Resources( 2755): Converting to string: TypedValue{t=0x10/d=0x4b0 a=-1}
W/Resources( 2755): Converting to string: TypedValue{t=0x10/d=0x20 a=-1}
D/AndroidRuntime( 2755): Shutting down VM
W/dalvikvm( 2755): threadid=1: thread exiting with uncaught exception (group=0x40015560)
E/AndroidRuntime( 2755): FATAL EXCEPTION: main
E/AndroidRuntime( 2755): Java.lang.RuntimeException: Unable to start activity ComponentInfo{org.jeremy.Android/org.jeremy.Android.PreferencesActivity}: Android.view.InflateException: Binary XML file line #28: Error inflating class Java.lang.reflect.Constructor
E/AndroidRuntime( 2755):    at Android.app.ActivityThread.performLaunchActivity(ActivityThread.Java:1647)
E/AndroidRuntime( 2755):    at Android.app.ActivityThread.handleLaunchActivity(ActivityThread.Java:1663)
E/AndroidRuntime( 2755):    at Android.app.ActivityThread.access$1500(ActivityThread.Java:117)
E/AndroidRuntime( 2755):    at Android.app.ActivityThread$H.handleMessage(ActivityThread.Java:931)
E/AndroidRuntime( 2755):    at Android.os.Handler.dispatchMessage(Handler.Java:99)
E/AndroidRuntime( 2755):    at Android.os.Looper.loop(Looper.Java:123)
E/AndroidRuntime( 2755):    at Android.app.ActivityThread.main(ActivityThread.Java:3683)
E/AndroidRuntime( 2755):    at Java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 2755):    at Java.lang.reflect.Method.invoke(Method.Java:507)
E/AndroidRuntime( 2755):    at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:839)
E/AndroidRuntime( 2755):    at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:597)
E/AndroidRuntime( 2755):    at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime( 2755): Caused by: Android.view.InflateException: Binary XML file line #28: Error inflating class Java.lang.reflect.Constructor
E/AndroidRuntime( 2755):    at Android.preference.GenericInflater.createItem(GenericInflater.Java:397)
E/AndroidRuntime( 2755):    at Android.preference.GenericInflater.onCreateItem(GenericInflater.Java:417)
E/AndroidRuntime( 2755):    at Android.preference.GenericInflater.createItemFromTag(GenericInflater.Java:428)
E/AndroidRuntime( 2755):    at Android.preference.GenericInflater.rInflate(GenericInflater.Java:481)
E/AndroidRuntime( 2755):    at Android.preference.GenericInflater.rInflate(GenericInflater.Java:493)
E/AndroidRuntime( 2755):    at Android.preference.GenericInflater.inflate(GenericInflater.Java:326)
E/AndroidRuntime( 2755):    at Android.preference.GenericInflater.inflate(GenericInflater.Java:263)
E/AndroidRuntime( 2755):    at Android.preference.PreferenceManager.inflateFromResource(PreferenceManager.Java:251)
E/AndroidRuntime( 2755):    at Android.preference.PreferenceActivity.addPreferencesFromResource(PreferenceActivity.Java:262)
E/AndroidRuntime( 2755):    at org.jeremy.Android.PreferencesActivity.onCreate(PreferencesActivity.Java:40)
E/AndroidRuntime( 2755):    at Android.app.Instrumentation.callActivityOnCreate(Instrumentation.Java:1047)
E/AndroidRuntime( 2755):    at Android.app.ActivityThread.performLaunchActivity(ActivityThread.Java:1611)
E/AndroidRuntime( 2755):    ... 11 more
E/AndroidRuntime( 2755): Caused by: Java.lang.InstantiationException: Android.preference.DialogPreference
E/AndroidRuntime( 2755):    at Java.lang.reflect.Constructor.constructNative(Native Method)
E/AndroidRuntime( 2755):    at Java.lang.reflect.Constructor.newInstance(Constructor.Java:415)
E/AndroidRuntime( 2755):    at Android.preference.GenericInflater.createItem(GenericInflater.Java:383)
E/AndroidRuntime( 2755):    ... 22 more
W/ActivityManager(   61):   Force finishing activity org.jeremy.Android/.PreferencesActivity
W/ActivityManager(   61):   Force finishing activity org.jeremy.Android/.SplashActivity
34
Jeremy

Celui-ci est bizarre, vous devez sous-classer DialogPreference. La sous-classe n'a rien à faire. Alors

public class MyDialogPreference extends DialogPreference {

    public MyDialogPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }

} 

peut être instancié. Alors qu'un avion ancien DialogPreference ne peut pas. Très bizarre, ils devraient être exactement la même chose.

19
Marc Holder Kluver

Voici un exemple d'utilisation de la préférence de dialogue (sous-classement comme vous l'avez mentionné).

package dk.myapp.views;

import Android.content.Context;
import Android.preference.DialogPreference;
import Android.util.AttributeSet;

/**
 * The OptionDialogPreference will display a dialog, and will persist the
 * <code>true</code> when pressing the positive button and <code>false</code>
 * otherwise. It will persist to the Android:key specified in xml-preference.
 */
public class OptionDialogPreference extends DialogPreference {

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

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

}

Le fichier preferences.xml doit contenir

<dk.myapp.views.OptionDialogPreference
            Android:key="@string/prefKeyResetQuests"
            Android:dialogIcon="@Android:drawable/ic_dialog_alert"
            Android:title="Reset Quests"
            Android:summary="Reset all quest-progress."
            Android:dialogMessage="Are you sure you wish to reset your quest progress? This action cannot be undone!"
            Android:positiveButtonText="Clear Quests"
            Android:negativeButtonText="Cancel"/>

J'ai un res/value contenant (bien que le nom de clé puisse également être déclaré explicitement ci-dessus).

<string name="prefKeyResetQuests">resetQuests</string>  

My PreferenceActivity effectue la réinitialisation réelle de onPause. Notez que l'onStop peut être trop tard car onStop ne sera pas toujours appelé immédiatement après avoir appuyé sur:

@Override
public void onPause() {
    SharedPreferences prefs = Android.preference.PreferenceManager.
        getDefaultSharedPreferences(getBaseContext());
    if(prefs.getBoolean(
        getResources().getString(R.string.prefKeyResetQuests), false)) {
        // apply reset, and then set the pref-value back to false
    }
}

Ou de manière équivalente puisque nous sommes toujours dans la PreferenceActivity:

@Override
protected void onPause() {
    Preference prefResetQuests =
        findPreference(getResources().getString(R.string.prefKeyResetQuests));
    if(prefResetQuests.getSharedPreferences().
        getBoolean(prefResetQuests.getKey(), false)){
        // apply reset, and then set the pref-value back to false 
    }
}
41
arberg

Première:

Créez votre propre classe qui étend DialogPreference comme ci-dessous:

package com.test.view;

import Android.preference.DialogPreference;

public class DialogExPreference extends DialogPreference 
{
    public DialogExPreference(Context oContext, AttributeSet attrs)
    {
        super(oContext, attrs);     
    }
}

Seconde:

Modifiez le fichier xml comme ci-dessous:

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

    <com.test.view.DialogExPreference
        Android:title="@string/title"
        Android:dialogMessage="@string/lite"              
                Android:negativeButtonText="test"/> 

</PreferenceScreen>

Alors c'est bon.

15
SKf