Prevent BottomSheetDialogFragment covering navigation bar

前端 未结 10 494
轮回少年
轮回少年 2020-12-12 23:49

I\'m using really naive code to show a bottom sheet dialog fragment:

class LogoutBottomSheetFragment : BottomSheetDialogFragment() {

    override fun onCrea         


        
相关标签:
10条回答
  • 2020-12-13 00:20

    BottomSheetDialogFragment extends DialogFragment. Inside BottomSheetDialog it's creating a Dialog inside onCreateDialog

    public class BottomSheetDialogFragment extends AppCompatDialogFragment {
    
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            return new BottomSheetDialog(getContext(), getTheme());
        }
    
    }
    

    The dim layer is a property of dialog which is applying to whole window. Then only it will cover the status bar. If you need dim layer without bottom buttons, then you have to do manually by showing a layer inside layout and changing status bar colour accordingly.

    Apply theme for dialogfragment as given below

    class LogoutBottomSheetFragment : BottomSheetDialogFragment() {
        init {
            setStyle(DialogFragment.STYLE_NORMAL,R.style.dialog);
        }
    
        override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
            val view = inflater.inflate(R.layout.view_image_source_chooser, container, false)
            return view
        }
    
    
    }
    

    With styles as

     <style name="dialog" parent="Base.Theme.AppCompat.Dialog">
            <item name="android:windowBackground">@android:color/transparent</item>
            <item name="android:backgroundDimEnabled">false</item>
    </style>
    
    0 讨论(0)
  • 2020-12-13 00:25

    I had the same problem. After looking into sources I found a workaround (a little bit hacky, but I found no alternatives).

    public class YourDialog extends BottomSheetDialogFragment {
    
        //your code
    
        @NonNull
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            return new FitSystemWindowsBottomSheetDialog(getContext());
        }
    }
    
    public class FitSystemWindowsBottomSheetDialog extends BottomSheetDialog {
    
        public FitSystemWindowsBottomSheetDialog(Context context) {
            super(context);
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            if (getWindow() != null && Build.VERSION.SDK_INT >= 21) {
                findViewById(android.support.design.R.id.coordinator).setFitsSystemWindows(false);
                findViewById(android.support.design.R.id.container).setFitsSystemWindows(false);
                getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS |
                        WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
                getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
            }
        }
    }
    

    And, finally, don't forget to add android:fitsSystemWindows="true" at the root of your dialog layout.

    Hope it helps.

    0 讨论(0)
  • 2020-12-13 00:26

    I know there is many solutions here already but all of them seems too much to me, so I found this very simple solution here, credit goes to Arthur Nagy:

    just override the getTheme method in the BottomSheetDialogFragment:

    override fun getTheme(): Int  = R.style.Theme_NoWiredStrapInNavigationBar
    

    and in styles.xml:

    <style name="Theme.NoWiredStrapInNavigationBar" parent="@style/Theme.Design.BottomSheetDialog">
        <item name="android:windowIsFloating">false</item>
        <item name="android:navigationBarColor">@color/bottom_sheet_bg</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
    </style>
    

    You can also add support for night mode by changing the color @color/bottom_sheet_bg in the values-night assets folder

    0 讨论(0)
  • 2020-12-13 00:32

    There is a way to avoid changes in Java/Kotlin code, the issue can be fully resolved in XML nowadays:

    <style name="MyTheme" parent="Theme.MaterialComponents">
        <item name="bottomSheetDialogTheme">@style/BottomSheet</item>
    </style>
    
    <style name="BottomSheet" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
        <item name="android:windowIsFloating">false</item>
        <item name="android:statusBarColor">@android:color/transparent</item>         
        <item name="android:navigationBarColor">?android:colorBackground</item>
        <item name="android:navigationBarDividerColor">?android:colorBackground</item>
    </style>
    

    I also had an issue with my theme/style not being applied to the views inside BottomSheetDialogFragment, here's what I did to fix that in my base BottomSheetDialogFragment:

    override fun onGetLayoutInflater(savedInstanceState: Bundle?): LayoutInflater {
        val inflater = super.onGetLayoutInflater(savedInstanceState)
        val wrappedContext = ContextThemeWrapper(requireContext(), R.style.My_Theme)
        return inflater.cloneInContext(wrappedContext)
    }
    
    0 讨论(0)
  • 2020-12-13 00:33

    Don't use BottomSheetDialogFragment.I would prefer use adding bottom sheet by wrapping the layout in the coordinator layout and attaching BottomSheetBehaiviour to that layout

    You can follow this as an example

    0 讨论(0)
  • 2020-12-13 00:36

    Use follow API to setContentView instead of overriding onCreateView.

            val dialog = BottomSheetDialog(context)
            dialog.setContentView(R.layout.your_layout)
    

    BottomSheetDialog.setContentView will setup the correct behavior for BottomSheetDialog. You can see the source code:

           public void setContentView(@LayoutRes int layoutResId) {
                  super.setContentView(this.wrapInBottomSheet(layoutResId, (View)null, (LayoutParams)null));
           }
    
           private View wrapInBottomSheet(int layoutResId, View view, LayoutParams params) {
                   FrameLayout container = (FrameLayout)View.inflate(this.getContext(), layout.design_bottom_sheet_dialog, (ViewGroup)null);
                   CoordinatorLayout coordinator = (CoordinatorLayout)container.findViewById(id.coordinator);
                   if (layoutResId != 0 && view == null) {
                      view = this.getLayoutInflater().inflate(layoutResId, coordinator, false);
                   }
                   // ... more stuff
           }
    
    0 讨论(0)
提交回复
热议问题