如何显示一个DialogPreference

huangapple go评论87阅读模式
英文:

How do you show a DialogPreference

问题

  • 这是一个名为 some_layout.xml 的随机布局:

     <?xml version="1.0" encoding="utf-8"?>
     <androidx.constraintlayout.widget.ConstraintLayout
         xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:app="http://schemas.android.com/apk/res-auto"
         xmlns:tools="http://schemas.android.com/tools"
         android:layout_width="match_parent"
         android:layout_height="match_parent">
    
         <!-- 这里有一些视图 -->
    
     </androidx.constraintlayout.widget.ConstraintLayout>
    
  • 这是一个扩展了 DialogPreference 的 SomeDialog.java 类:

     import android.content.Context;
    
     import androidx.preference.DialogPreference;
    
     public class SomeDialog extends DialogPreference {
    
    
         public SomeDialog(Context context) {
             super(context);
         }
    
         @Override
         public int getDialogLayoutResource() {
             return R.layout.some_layout;
         }
     }
    
  • 这是首选项屏幕:

     <?xml version="1.0" encoding="utf-8"?>
     <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    
         <android.example.perappbrightness.SomeDialog
                 android:title="@string/rate_app"
                 android:summary="@string/rate_summary"
                 android:key="rate_app"/>
    
     </PreferenceScreen>
    

崩溃错误的相关部分。MainActivty 崩溃的行是 PreferenceManager.setDefaultValues(this, R.xml.preferences, false);

java.lang.RuntimeException: Unable to start activity ComponentInfo{android.example.perappbrightness/android.example.perappbrightness.MainActivity}: android.view.InflateException: Binary XML file line #36: Error inflating class android.example.perappbrightness.SomeDialog
    Caused by: android.view.InflateException: Binary XML file line #36: Error inflating class android.example.perappbrightness.SomeDialog
android.example.perappbrightness.MainActivity.onCreate(MainActivity.java:72)

SettingsActivity.java 没有进行修改。它来自 Android Studio 的模板。

我做错了什么?

英文:
  • Here is a random layout called some_layout.xml:

    &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
    &lt;androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
        xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;
        xmlns:tools=&quot;http://schemas.android.com/tools&quot;
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;match_parent&quot;&quot;&gt;
    
        &lt;!-- Some views in here --&gt;
    
    &lt;/androidx.constraintlayout.widget.ConstraintLayout&gt;
    
  • Here is a class SomeDialog.java that extends DialogPreference:

    import android.content.Context;
    
    import androidx.preference.DialogPreference;
    
    public class SomeDialog extends DialogPreference {
    
    
        public SomeDialog(Context context) {
            super(context);
        }
    
        @Override
        public int getDialogLayoutResource() {
            return R.layout.some_layout;
        }
    }
    
  • And here's the preference screen:

    &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
    &lt;PreferenceScreen xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;&gt;
    
        &lt;android.example.perappbrightness.SomeDialog
                android:title=&quot;@string/rate_app&quot;
                android:summary=&quot;@string/rate_summary&quot;
                android:key=&quot;rate_app&quot;/&gt;
    
    &lt;/PreferenceScreen&gt;
    

Relevant part of crash error. The line at which MainActivty crashes is PreferenceManager.setDefaultValues(this, R.xml.preferences, false);:

java.lang.RuntimeException: Unable to start activity ComponentInfo{android.example.perappbrightness/android.example.perappbrightness.MainActivity}: android.view.InflateException: Binary XML file line #36: Error inflating class android.example.perappbrightness.SomeDialog
    Caused by: android.view.InflateException: Binary XML file line #36: Error inflating class android.example.perappbrightness.SomeDialog
android.example.perappbrightness.MainActivity.onCreate(MainActivity.java:72)

 

SettingsActivity.java is an untouched. It's from the template of Android Studio.

What am I doing wrong?

答案1

得分: 1

首先,您需要为 SomeDialog 添加更多的构造函数。仅具有 Context 构造函数是不够的,因为 Preference 将从 xml 文件中充气。通常具有以下三个构造函数足够了:

public SomeDialog(Context context) {
    super(context);
}

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

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

除此之外,您的 SettingsActivity 中的 SettingsFragment 需要实现 onDisplayPreferenceDialog(Preference preference) 方法,以显示自定义 Preference 的自定义对话框。

public static class SettingsFragment extends PreferenceFragmentCompat {
    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        setPreferencesFromResource(R.xml.root_preferences, rootKey);
    }

    @Override
    public void onDisplayPreferenceDialog(Preference preference) {
        if (preference instanceof SomeDialog) {
            MyDialogFragment dialogFragment = new MyDialogFragment();
            Bundle b = new Bundle();
            b.putString(MyDialogFragment.KEY, preference.getKey());
            b.putInt(MyDialogFragment.KEY_LAYOUT_RES_ID, ((SomeDialog) preference).getDialogLayoutResource());

            dialogFragment.setArguments(b);
            dialogFragment.setTargetFragment(this, 0);
            dialogFragment.show(getFragmentManager(), null);
        } else super.onDisplayPreferenceDialog(preference);
    }
}

最后但同样重要的是,您还需要提供自定义对话框本身。这是通过扩展 DialogFragment 类来完成的。

我的非常简单的 DialogFragment 包含一个位于 FrameLayout 内的 TextView,只是为了展示它可以工作。

public class MyDialogFragment extends DialogFragment {
    
    public static final String KEY = "key";
    public static final String KEY_LAYOUT_RES_ID = "resid";

    
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(requireArguments().getInt(KEY_LAYOUT_RES_ID), container, false);
    }
    
    
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        TextView textView = view.findViewById(R.id.textView);
        textView.setText(requireArguments().getString(KEY));
    }
}

希望这些信息对您有所帮助。如果您需要进一步的解释或有其他问题,请随时提问。

英文:

First, you need to add more constructors to SomeDialog. The Context constructor is not enough since the Preference will be inflated from xml. Having the following three constructors is usually sufficient:

public SomeDialog(Context context) {
    super(context);
}

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

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

In addition to that, the SettingsFragment in your SettingsActivity needs to implement onDisplayPreferenceDialog(Preference preference) to show a custom dialog for the custom Preference.

public static class SettingsFragment extends PreferenceFragmentCompat {
    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        setPreferencesFromResource(R.xml.root_preferences, rootKey);
    }

    @Override
    public void onDisplayPreferenceDialog(Preference preference) {
        if (preference instanceof SomeDialog) {
            MyDialogFragment dialogFragment = new MyDialogFragment();
            Bundle b = new Bundle();
            b.putString(MyDialogFragment.KEY, preference.getKey());
            b.putInt(MyDialogFragment.KEY_LAYOUT_RES_ID,  ((SomeDialog) preference).getDialogLayoutResource());

            dialogFragment.setArguments(b);
            dialogFragment.setTargetFragment(this, 0);
            dialogFragment.show(getFragmentManager(), null);
        } else super.onDisplayPreferenceDialog(preference);
    }
}

And, last not least, you also have to provide the custom dialog itself. This is done via a class extending DialogFragment.

My very simple DialogFragment has a TextView inside a FrameLayout, just to show it works

如何显示一个DialogPreference

MyDialogFragment code:

public class MyDialogFragment extends DialogFragment {

    public static final String KEY = &quot;key&quot;;
    public static final String KEY_LAYOUT_RES_ID = &quot;resid&quot;;


    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
                return inflater.inflate(requireArguments().getInt(KEY_LAYOUT_RES_ID), container, false);

    }


    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        TextView textView = view.findViewById(R.id.textView);
        textView.setText(requireArguments().getString(KEY));
    }
}

huangapple
  • 本文由 发表于 2020年8月8日 20:06:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/63315165.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定