简体   繁体   中英

Adding custom DialogPreference to xml file

I've implemented this custom DialogPreference in C# with Xamarin however I'm having issues adding it to my xml file.

namespace Client.Android
{
public class TimePreference : DialogPreference
{
    private int lastHour = 0;
    private int lastMinute = 0;
    private TimePicker picker = null;

    public static int GetHour(string time)
    {
        string[] pieces = time.Split (':');
        return Convert.ToInt32 (pieces [0]);
    }

    public static int GetMinute(string time)
    {
        string[] pieces = time.Split (':');
        return Convert.ToInt32 (pieces [1]);
    }

    public TimePreference(Context context, IAttributeSet attSet) : base(context, attSet)
    {
        SetPositiveButtonText (Resource.String.time_preference_set);
        SetNegativeButtonText (Resource.String.time_preference_cancel);
    }

    protected override View OnCreateDialogView ()
    {
        picker = new TimePicker (Context);
        return picker;
    }

    protected override void OnBindDialogView (View view)
    {
        base.OnBindDialogView (view);
        picker.CurrentHour = (Java.Lang.Integer) lastHour;
        picker.CurrentMinute = (Java.Lang.Integer) lastMinute;
    }

    protected override void OnDialogClosed (bool positiveResult)
    {
        base.OnDialogClosed (positiveResult);

        if (positiveResult) {
            lastHour = (int) picker.CurrentHour;
            lastMinute = (int) picker.CurrentMinute;

            string time = lastHour + ":" + lastMinute;

            if (CallChangeListener (time)) {
                PersistString (time);
            }
        }
    }

    protected override Java.Lang.Object OnGetDefaultValue (TypedArray a, int index)
    {
        return a.GetString (index);
    }

    protected override void OnSetInitialValue (bool restorePersistedValue, Java.Lang.Object defaultValue)
    {
        string time = string.Empty;

        if (restorePersistedValue) {
            if (defaultValue == null) {
                time = GetPersistedString ("00:00");
            } else {
                time = GetPersistedString (defaultValue.ToString ());
            }
        } else {
            time = defaultValue.ToString ();
        }

        lastHour = GetHour (time);
        lastMinute = GetMinute (time);
    }
}
}

My projects name/default namespace is "Client.Android" and I've tried adding it to my xml file like so:

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
    <PreferenceCategory android:title="@string/pref_foo" >
    ...

    <Client.Android.TimePreference
         android:title="@string/pref_bar"
         android:key="@string/prefkey_bar"
         android:defaultValue="12:00" />
    ...
    </PreferenceCategory>
</PreferenceScreen>

But I get the following exception on AddPreferencesFromResource(Resource.Xml.settings); of my OnCreate method:

    Android.Views.InflateException: Binary XML file line #32: Error inflating class Client.Android.TimePreference
  at Android.Runtime.JNIEnv.CallNonvirtualVoidMethod (intptr,intptr,intptr,Android.Runtime.JValue[]) [0x00084] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.12-series/7f0e3d3c/source/monodroid/src/Mono.Android/src/Runtime/JNIEnv.g.cs:895
  at Android.Preferences.PreferenceActivity.AddPreferencesFromResource (int) [0x00070] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.12-series/7f0e3d3c/source/monodroid/src/Mono.Android/platforms/android-19/src/generated/Android.Preferences.PreferenceActivity.cs:729
  at Client.Android.SettingsActivity.OnCreate (Android.OS.Bundle) [0x00015] in c:\pushtotalk\Client.Android\SettingsActivity.cs:45
  at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (intptr,intptr,intptr) [0x00011] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.12-series/7f0e3d3c/source/monodroid/src/Mono.Android/platforms/android-19/src/generated/Android.App.Activity.cs:2178
  at at (wrapper dynamic-method) object.7c9f4d4d-9496-4803-b019-cd453beeee8b (intptr,intptr,intptr) <IL 0x00017, 0x00043>
  at --- End of managed exception stack trace ---
  at android.view.InflateException: Binary XML file line #32: Error inflating class Client.Android.TimePreference
  at at android.preference.GenericInflater.createItemFromTag(GenericInflater.java:441)
  at at android.preference.GenericInflater.rInflate(GenericInflater.java:481)
  at at android.preference.GenericInflater.rInflate(GenericInflater.java:493)
  at at android.preference.GenericInflater.inflate(GenericInflater.java:326)
  at at android.preference.GenericInflater.inflate(GenericInflater.java:263)
  at at android.preference.PreferenceManager.inflateFromResource(PreferenceManager.java:272)
  at at android.preference.PreferenceActivity.addPreferencesFromResource(PreferenceActivity.java:1472)
  at at client.android.SettingsActivity.n_onCreate(Native Method)
  at at client.android.SettingsActivity.onCreate(SettingsActivity.java:32)
  at at android.app.Activity.performCreate(Activity.java:5231)
  at at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
  at at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159)
  at at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
  at at android.app.ActivityThread.access$800(ActivityThread.java:135)
  at at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
  at at android.os.Handler.dispatchMessage(Handler.java:102)
  at at android.os.Looper.loop(Looper.java:136)
  at at android.app.ActivityThread.main(ActivityThread.java:5017)
  at at java.lang.reflect.Method.invokeNative(Native Method)
  at at java.lang.reflect.Method.invoke(Method.java:515)
  at at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
  at at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
  at at dalvik.system.NativeStart.main(Native Method)
  at Caused by: java.lang.ClassNotFoundException: Didn't find class "Client.Android.TimePreference" on path: DexPathList[[zip file "/data/app/Client.Android-1.apk"],nativeLibraryDirectories=[/data/app-lib/Client.Android-1, /vendor/lib, /system/lib]]
  at at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
  at at java.lang.ClassLoader.loadClass(ClassLoader.java:497)
  at at java.lang.ClassLoader.loadClass(ClassLoader.java:457)
  at at android.preference.GenericInflater.createItem(GenericInflater.java:375)
  at at android.preference.GenericInflater.createItemFromTag(GenericInflater.java:430)
  at ... 22 more

These are the default attributes available (You can also view inherited attributes by expanding the Inherited XML Attributes block in the android docs for DialogPreference ):

android:dialogIcon - The icon for the dialog. 
android:dialogLayout - A layout to be used as the content View for the dialog. 
android:dialogMessage - The message in the dialog. 
android:dialogTitle - The title in the dialog. 
android:negativeButtonText - The negative button text for the dialog. 
android:positiveButtonText - The positive button text for the dialog. 

So in order to use your own attributes you need to create your own Resource file where you define Stylable s for your DialogPreference like:

Resource\\Values\\MyTimePreferenceAttrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyTimePreference">
        <attr name="defaultValue" format="string"/>
    </declare-styleable>
</resources>

Then in your AXML layout where you create your TimePreference view you need to add a namespace so that they can be resolved:

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:my="http://schemas.android.com/apk/res-auto" >
    <PreferenceCategory android:title="@string/pref_foo" >
    ...

    <Client.Android.TimePreference
         my:defaultValue="12:00" />
    ...
    </PreferenceCategory>
</PreferenceScreen>

Then in your constructor of TimePreference you can get the value with something like:

var ta = context.ObtainStyledAttributes(attrs, Resource.Styleable.MyTimePreference);
var defaultValue = ta.GetString(Resource.Styleable.MyTimePreference_defaultValue);
ta.Recycle();

You also might have a problem with using capitalized namespace in your XML layout. However the classname stays Capitalized, so:

<client.android.TimePreference
    ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM