解决BottomSheetDialog横屏下不能展示完全问题

项目开发中使用了谷歌推荐的实现类似网易云音乐的上弹对话框BottomSheetDialog控件,该控件在竖屏状态下显示没有问题,但是在横屏状态下弹窗只能显示一半,需要手动往上滑一下才能完全显示。在网上找了下解决方案,看到了https://www.jianshu.com/p/50c54d8e0d4a 相同的问题,但是这篇文章中只给了相应的解决方案,没有完整的代码,对于使用原生的BottomSheetDialog人员来说,根本就是个鸡肋。这里我结合源码和上述文章中的解决方案,整理成一个完整的自定义BottomSheetDialog供后来者使用,希望能帮助你们。

特别注意:这里对应的布局文件和id对应的R文件直接引用你们项目中的R文件就可以,布局使用的是Android 自带的布局文件,只要使用Android studio进入BottomDialog的源码,点击下面图片中的位置即可使

用。

下载BottomSheetDialog布局文件和样式的位置

下面是完整代码:

  1 import android.content.Context;
  2 import android.content.res.TypedArray;
  3 import android.os.Build;
  4 import android.os.Bundle;
  5 import android.support.annotation.LayoutRes;
  6 import android.support.annotation.NonNull;
  7 import android.support.annotation.StyleRes;
  8 import android.support.design.widget.BottomSheetBehavior;
  9 import android.support.design.widget.CoordinatorLayout;
 10 import android.support.v4.view.AccessibilityDelegateCompat;
 11 import android.support.v4.view.ViewCompat;
 12 import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
 13 import android.support.v7.app.AppCompatDialog;
 14 import android.util.TypedValue;
 15 import android.view.MotionEvent;
 16 import android.view.View;
 17 import android.view.ViewGroup;
 18 import android.view.Window;
 19 import android.widget.FrameLayout;
 20 
 21 
 22 public class BaseBottomSheetDialog extends AppCompatDialog {
 23     private BottomSheetBehavior<FrameLayout> behavior;
 24     boolean cancelable;
 25     private boolean canceledOnTouchOutside;
 26     private boolean canceledOnTouchOutsideSet;
 27     private BottomSheetBehavior.BottomSheetCallback bottomSheetCallback;
 28 
 29     public BaseBottomSheetDialog(@NonNull Context context) {
 30         this(context, 0);
 31     }
 32 
 33     public BaseBottomSheetDialog(@NonNull Context context, @StyleRes int theme) {
 34         super(context, getThemeResId(context, theme));
 35         this.cancelable = true;
 36         this.canceledOnTouchOutside = true;
 37         this.bottomSheetCallback = new NamelessClass_1();
 38         this.supportRequestWindowFeature(1);
 39     }
 40 
 41     protected BaseBottomSheetDialog(@NonNull Context context, boolean cancelable, OnCancelListener cancelListener) {
 42         super(context, cancelable, cancelListener);
 43         this.cancelable = true;
 44         this.canceledOnTouchOutside = true;
 45 
 46 
 47 
 48         this.bottomSheetCallback = new NamelessClass_1();
 49         this.supportRequestWindowFeature(1);
 50         this.cancelable = cancelable;
 51     }
 52 
 53     public void setContentView(@LayoutRes int layoutResId) {
 54         super.setContentView(this.wrapInBottomSheet(layoutResId, (View)null, (ViewGroup.LayoutParams)null));
 55     }
 56     class NamelessClass_1 extends BottomSheetBehavior.BottomSheetCallback {
 57         NamelessClass_1() {
 58         }
 59 
 60         public void onStateChanged(@NonNull View bottomSheet, int newState) {
 61             if (newState == 5) {
 62                 BaseBottomSheetDialog.this.cancel();
 63             }
 64 
 65         }
 66 
 67         public void onSlide(@NonNull View bottomSheet, float slideOffset) {
 68         }
 69     }
 70     protected void onCreate(Bundle savedInstanceState) {
 71         super.onCreate(savedInstanceState);
 72         Window window = this.getWindow();
 73         if (window != null) {
 74             if (Build.VERSION.SDK_INT >= 21) {
 75                 window.clearFlags(67108864);
 76                 window.addFlags(-2147483648);
 77             }
 78 
 79             window.setLayout(-1, -1);
 80         }
 81 
 82     }
 83 
 84     public void setContentView(View view) {
 85         super.setContentView(this.wrapInBottomSheet(0, view, (ViewGroup.LayoutParams)null));
 86     }
 87 
 88     public void setContentView(View view, ViewGroup.LayoutParams params) {
 89         super.setContentView(this.wrapInBottomSheet(0, view, params));
 90     }
 91 
 92     public void setCancelable(boolean cancelable) {
 93         super.setCancelable(cancelable);
 94         if (this.cancelable != cancelable) {
 95             this.cancelable = cancelable;
 96             if (this.behavior != null) {
 97                 this.behavior.setHideable(cancelable);
 98             }
 99         }
100 
101     }
102 
103     protected void onStart() {
104         super.onStart();
105         if (this.behavior != null) {
106             this.behavior.setState(3);
107         }
108     }
109 
110     public void setCanceledOnTouchOutside(boolean cancel) {
111         super.setCanceledOnTouchOutside(cancel);
112         if (cancel && !this.cancelable) {
113             this.cancelable = true;
114         }
115 
116         this.canceledOnTouchOutside = cancel;
117         this.canceledOnTouchOutsideSet = true;
118     }
119 
120     private View wrapInBottomSheet(int layoutResId, View view, ViewGroup.LayoutParams params) {
121         FrameLayout container = (FrameLayout)View.inflate(this.getContext(), R.layout.design_bottom_sheet_dialog, (ViewGroup)null);
122         CoordinatorLayout coordinator = (CoordinatorLayout)container.findViewById(R.id.coordinator);
123         if (layoutResId != 0 && view == null) {
124             view = this.getLayoutInflater().inflate(layoutResId, coordinator, false);
125         }
126 
127         FrameLayout bottomSheet = (FrameLayout)coordinator.findViewById(R.id.design_bottom_sheet);
128         this.behavior = BottomSheetBehavior.from(bottomSheet);
129         this.behavior.setBottomSheetCallback(this.bottomSheetCallback);
130         this.behavior.setHideable(this.cancelable);
131         if (params == null) {
132             bottomSheet.addView(view);
133         } else {
134             bottomSheet.addView(view, params);
135         }
136         coordinator.findViewById(R.id.touch_outside).setOnClickListener(new View.OnClickListener() {
137             @Override
138             public void onClick(View v) {
139                 if (BaseBottomSheetDialog.this.cancelable && BaseBottomSheetDialog.this.isShowing() && BaseBottomSheetDialog.this.shouldWindowCloseOnTouchOutside()) {
140                     BaseBottomSheetDialog.this.cancel();
141                 }
142             }
143         });
144         ViewCompat.setAccessibilityDelegate(bottomSheet, new AccessibilityDelegateCompat() {
145             public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
146                 super.onInitializeAccessibilityNodeInfo(host, info);
147                 if (BaseBottomSheetDialog.this.cancelable) {
148                     info.addAction(1048576);
149                     info.setDismissable(true);
150                 } else {
151                     info.setDismissable(false);
152                 }
153 
154             }
155 
156             public boolean performAccessibilityAction(View host, int action, Bundle args) {
157                 if (action == 1048576 &&BaseBottomSheetDialog.this.cancelable) {
158                     BaseBottomSheetDialog.this.cancel();
159                     return true;
160                 } else {
161                     return super.performAccessibilityAction(host, action, args);
162                 }
163             }
164         });
165         bottomSheet.setOnTouchListener((view1, event) -> true);
166         return container;
167     }
168 
169     boolean shouldWindowCloseOnTouchOutside() {
170         if (!this.canceledOnTouchOutsideSet) {
171             TypedArray a = this.getContext().obtainStyledAttributes(new int[]{16843611});
172             this.canceledOnTouchOutside = a.getBoolean(0, true);
173             a.recycle();
174             this.canceledOnTouchOutsideSet = true;
175         }
176 
177         return this.canceledOnTouchOutside;
178     }
179 
180     private static int getThemeResId(Context context, int themeId) {
181         if (themeId == 0) {
182             TypedValue outValue = new TypedValue();
183             if (context.getTheme().resolveAttribute(R.attr.bottomSheetDialogTheme, outValue, true)) {
184                 themeId = outValue.resourceId;
185             } else {
186                 themeId = R.style.Theme_Design_Light_BottomSheetDialog;
187             }
188         }
189 
190         return themeId;
191     }
192 }
原文地址:https://www.cnblogs.com/1925yiyi/p/13613505.html