需求分析
- 從底部滑入,手指水平拖動可看到底下 Activity
- 解決
show() 時機導致的 IllegalStateException: Can not perform this action after onSaveInstanceState
推薦方案:BottomSheetDialogFragment (Material Design)
public class BottomSheetFragment extends BottomSheetDialogFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_bottom_sheet, container, false);
// 設定拖動行為
return view;
}
@Override
public void onStart() {
super.onStart();
BottomSheetDialog dialog = (BottomSheetDialog) getDialog();
if (dialog != null) {
FrameLayout bottomSheet = dialog.findViewById(com.google.android.material.R.id.design_bottom_sheet);
BottomSheetBehavior> behavior = BottomSheetBehavior.from(bottomSheet);
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
behavior.setDraggable(true); // 允許拖動關閉
}
}
}
安全顯示模式(避免 onSaveInstanceState 崩潰)
// 錯誤寫法
fragment.show(getSupportFragmentManager(), "tag");
// 正確寫法 1:commitAllowingStateLoss
fragment.show(getSupportFragmentManager().beginTransaction(), "tag");
// 正確寫法 2:Lifecycle 感知 (Fragment 1.3.0+)
fragment.show(getChildFragmentManager(), "tag"); // 在 Fragment 內使用
// 正確寫法 3:延遲顯示
new Handler(Looper.getMainLooper()).post(() ->
fragment.show(getSupportFragmentManager(), "tag")
);
自訂 DialogFragment 抽屜效果(不依賴 Material 元件)
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NORMAL, R.style.BottomSheetDialogTheme);
}
@Override
public void onStart() {
super.onStart();
Dialog dialog = getDialog();
if (dialog != null) {
Window window = dialog.getWindow();
WindowManager.LayoutParams params = window.getAttributes();
params.gravity = Gravity.BOTTOM;
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
window.setAttributes(params);
window.setWindowAnimations(R.style.BottomSheetAnimation);
}
}
styles.xml 關鍵設定