英文:
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:
<?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""> <!-- Some views in here --> </androidx.constraintlayout.widget.ConstraintLayout>
-
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:
<?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>
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
MyDialogFragment code:
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));
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论