Related
I have a custom BttomSheetDialogFragment and I want to have round corners in top of Bottom View
This is my Custom class that inflates my layout that I want to appear from bottom
View mView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.charge_layout, container, false);
initChargeLayoutViews();
return mView;
}
and also I have this XML resource file as background:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<corners android:topRightRadius="35dp"
android:topLeftRadius="35dp"
/>
<solid android:color="#color/white"/>
<padding android:top="10dp"
android:bottom="10dp"
android:right="16dp"
android:left="16dp"/>
</shape>
The problem is, when I set this resource file as background of my Layout's root element, the corners still are not rounded.
I can't use below code:
this.getDialog().getWindow().setBackgroundDrawableResource(R.drawable.charge_layout_background);
Because it overrides the default background of BottomSheetDialog and there won't be any semi-transparent gray color above my Bottom View.
Create a custom drawable rounded_dialog.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#android:color/white"/>
<corners android:topLeftRadius="16dp"
android:topRightRadius="16dp"/>
</shape>
Then override bottomSheetDialogTheme on styles.xml using the drawable as background:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="bottomSheetDialogTheme">#style/AppBottomSheetDialogTheme</item>
</style>
<style name="AppBottomSheetDialogTheme"
parent="Theme.Design.Light.BottomSheetDialog">
<item name="bottomSheetStyle">#style/AppModalStyle</item>
</style>
<style name="AppModalStyle"
parent="Widget.Design.BottomSheet.Modal">
<item name="android:background">#drawable/rounded_dialog</item>
</style>
This will change all the BottomSheetDialogs of your app.
With the new Material Component library you can customize the shape of your component using the shapeAppearanceOverlay attribute in your style (Note: it requires at least the version 1.1.0)
Just use the BottomSheetDialogFragment overriding the onCreateView method and then define your custom style for Bottom Sheet Dialogs.
Define the bottomSheetDialogTheme attribute in styles.xml in your app theme:
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.MaterialComponents.Light">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
....
<item name="bottomSheetDialogTheme">#style/CustomBottomSheetDialog</item>
</style>
Then just define your favorite shape with shapeAppearanceOverlay
<style name="CustomBottomSheetDialog" parent="#style/ThemeOverlay.MaterialComponents.BottomSheetDialog">
<item name="bottomSheetStyle">#style/CustomBottomSheet</item>
</style>
<style name="CustomBottomSheet" parent="Widget.MaterialComponents.BottomSheet">
<item name="shapeAppearanceOverlay">#style/CustomShapeAppearanceBottomSheetDialog</item>
</style>
<style name="CustomShapeAppearanceBottomSheetDialog" parent="">
<item name="cornerFamily">rounded</item>
<item name="cornerSizeTopRight">16dp</item>
<item name="cornerSizeTopLeft">16dp</item>
<item name="cornerSizeBottomRight">0dp</item>
<item name="cornerSizeBottomLeft">0dp</item>
</style>
You can obtain the same behavior overriding this method in your BottomSheetDialogFragment (instead of adding the bottomSheetDialogTheme in your app theme):
#Override public int getTheme() {
return R.style.CustomBottomSheetDialog;
}
In this case you are using this themeOverlay only in the single BottomSheetDialogFragment and not in all the app.
Important note about the EXPANDED STATE:
In the expanded state the BottomSheet has flat corners . You can check the official comment in github repo:
Our design team is strongly opinionated that rounded corners indicate scrollable content while flat corners indicate that there is no additional content. As such, they do no want us to add this change with fitToContents.
This behavior is provided by the BottomSheetBehavior and it is impossible to override it.
However there is a workaround -> DISCLAIMER: it can stop to work in the next releases !!
You can add a BottomSheetCallback in the BottomSheetDialogFragment:
#NonNull #Override public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
((BottomSheetDialog)dialog).getBehavior().addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override public void onStateChanged(#NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_EXPANDED) {
//In the EXPANDED STATE apply a new MaterialShapeDrawable with rounded cornes
MaterialShapeDrawable newMaterialShapeDrawable = createMaterialShapeDrawable(bottomSheet);
ViewCompat.setBackground(bottomSheet, newMaterialShapeDrawable);
}
}
#Override public void onSlide(#NonNull View bottomSheet, float slideOffset) {
}
});
return dialog;
}
#NotNull private MaterialShapeDrawable createMaterialShapeDrawable(#NonNull View bottomSheet) {
ShapeAppearanceModel shapeAppearanceModel =
//Create a ShapeAppearanceModel with the same shapeAppearanceOverlay used in the style
ShapeAppearanceModel.builder(getContext(), 0, R.style.CustomShapeAppearanceBottomSheetDialog)
.build();
//Create a new MaterialShapeDrawable (you can't use the original MaterialShapeDrawable in the BottoSheet)
MaterialShapeDrawable currentMaterialShapeDrawable = (MaterialShapeDrawable) bottomSheet.getBackground();
MaterialShapeDrawable newMaterialShapeDrawable = new MaterialShapeDrawable((shapeAppearanceModel));
//Copy the attributes in the new MaterialShapeDrawable
newMaterialShapeDrawable.initializeElevationOverlay(getContext());
newMaterialShapeDrawable.setFillColor(currentMaterialShapeDrawable.getFillColor());
newMaterialShapeDrawable.setTintList(currentMaterialShapeDrawable.getTintList());
newMaterialShapeDrawable.setElevation(currentMaterialShapeDrawable.getElevation());
newMaterialShapeDrawable.setStrokeWidth(currentMaterialShapeDrawable.getStrokeWidth());
newMaterialShapeDrawable.setStrokeColor(currentMaterialShapeDrawable.getStrokeColor());
return newMaterialShapeDrawable;
}
The BottomSheetDialog is setting a default white background color , this is why the corners are not visible, In order to show them you need to make the background of the dialog transparent by overriding the style of the BottomSheetDialog.
Define this style In your res/values/styles/styles.xml
<style name="BottomSheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
<item name="bottomSheetStyle">#style/bottomSheetStyleWrapper</item>
</style>
<style name="bottomSheetStyleWrapper" parent="Widget.Design.BottomSheet.Modal">
<item name="android:background">#android:color/transparent</item>
</style>
And set this style to your BottomSheetDialog
View view = getLayoutInflater().inflate(R.layout.chooser_bottom_sheet, null);
BottomSheetDialog dialog = new BottomSheetDialog(this,R.style.BottomSheetDialog); // Style here
dialog.setContentView(view);
dialog.show();
create a shape named rounded_corners_shape
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:topLeftRadius="8dp"
android:topRightRadius="8dp"/>
<solid android:color="#color/white"/>
</shape>
define a style
<style name="AppBottomSheetDialogTheme"
parent="Theme.Design.Light.BottomSheetDialog">
<item name="bottomSheetStyle">#style/AppModalStyle</item>
</style>
<style name="AppModalStyle" parent="Widget.Design.BottomSheet.Modal">
<item name="android:background">#drawable/rounded_corners_shape</item>
</style>
use this style on your custom BottomSheetDialogFragment like this, it will be work!
public class CustomDialogFragment extends BottomSheetDialogFragment {
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(STYLE_NORMAL, R.style. AppBottomSheetDialogTheme);
}
...
}
This worked for me.
Create a background drawable (e.g. named shape_rounded_dialog):
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#color/color_white" />
<corners android:topLeftRadius="16dp"
android:topRightRadius="16dp" />
</shape>
Add the styles below:
<style name="AppBottomSheetDialogTheme"
parent="Theme.MaterialComponents.Light.BottomSheetDialog">
<item name="bottomSheetStyle">#style/CustomBottomSheetStyle</item>
</style>
<style name="CustomBottomSheetStyle"
parent="Widget.Design.BottomSheet.Modal">
<item name="android:background">#drawable/shape_rounded_dialog</item>
</style>
In your DialogFragment, override the method getTheme() to return your style.
#Override
public int getTheme() {
return R.style.AppBottomSheetDialogTheme;
}
The simplest and cleanest solution, that worked for me, was to put the following 4 lines in onViewCreated(View view, Bundle savedInstanceState) method of my fragment class:
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
View bottomSheet = (View) view.getParent();
bottomSheet.setBackgroundTintMode(PorterDuff.Mode.CLEAR);
bottomSheet.setBackgroundTintList(ColorStateList.valueOf(Color.TRANSPARENT));
bottomSheet.setBackgroundColor(Color.TRANSPARENT);
}
This will allow for your custom drawable with rounded corners to be properly shown once set as the background of the top level view of your fragment layout.
In essence this overrides the default BottomSheetFragment attributes regarding color, tintMode and tintList.
Using this, there is no need for messing with style resources.
If you use the last version of material component you just have to override ShapeAppearance.MaterialComponents.LargeComponent (as the bottom sheet use this shape) and set the value you want like :
<style name="ShapeAppearance.YourApp.LargeComponent" parent="ShapeAppearance.MaterialComponents.LargeComponent">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">12dp</item>
</style>
And then set in your app style :
<item name="shapeAppearanceLargeComponent">#style/ShapeAppearance.YourApp.LargeComponent</item>
The solution of Gabriele Mariotti is similar and works too but this one is simpler.
I was checking the same thing today and yes you were right about following code
this.getDialog().getWindow().setBackgroundDrawableResource(R.drawable.charge_layout_background);
this applies to fragment background, so instead you should get the bottomsheet view from dialog window and change the background here is the code
#SuppressLint("RestrictedApi")
#Override
public void setupDialog(Dialog dialog, int style) {
super.setupDialog(dialog, style);
View rootView = getActivity().getLayoutInflater().inflate(R.layout.view_member_info,null,false);
unbinder = ButterKnife.bind(this, rootView);
adjustUIComponents();
dialog.setContentView(rootView);
FrameLayout bottomSheet = (FrameLayout) dialog.getWindow().findViewById(android.support.design.R.id.design_bottom_sheet);
bottomSheet.setBackgroundResource(R.drawable.container_background);
}
here bottomsheet is the actual view you want to change.
Answer by Koma Yip from another question worked for me, you should try it.
Create a xml in drawable , say dialog_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#color/white"/>
<corners android:radius="30dp" />
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
</shape>
put this in your layout xml root node:
set it as the background in your layout xml
android:background="#drawable/dialog_bg"
and in onCreateView() put this:
set the background of your dialog to transparent
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
Step 1:
Create a res/drawable named as rounded_background.xml :
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:topLeftRadius="32dp"
android:topRightRadius="32dp" />
<solid android:color="#D81B60" />
</shape>
Step 2:
Create this style to remove the dialog background:
<style name="NoBackgroundDialogTheme" parent="Theme.AppCompat.Light.Dialog">
<item name="android:windowBackground">#null</item>
</style>
Step 3:
Set the drawable to the root view of the dialog using setBackgroundResource() & set the style by overriding getTheme() method
Java:
public class MyDialogFragment extends BottomSheetDialogFragment {
#Override
public int getTheme() {
return R.style.NoBackgroundDialogTheme;
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = View.inflate(requireContext(), R.layout.bottom_sheet_profile, null);
view.setBackgroundResource(R.drawable.rounded_background);
return view;
}
}
Kotlin:
class MyDialogFragment : BottomSheetDialogFragment() {
override fun getTheme() = R.style.NoBackgroundDialogTheme
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val view: View = View.inflate(requireContext(), R.layout.bottom_sheet_profile, null)
view.setBackgroundResource(R.drawable.rounded_background)
return view
}
}
Result:
if( view.setBackgroundResource(R.drawable.rounded_background)) this line dose'nt work then try to set the background of the Xml format of fragment.
Create a shape drawable .. which we will use as background for bottom sheet .
Provide the appropriate value for radius of top left and right corner .
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:topLeftRadius="24dp"
android:topRightRadius="24dp" />
<padding android:top="2dp" />
<solid android:color="#color/white" />
</shape>
Now create style for " Bottom sheet dialog fragment "
<style name="BottomSheet" parent="#style/Widget.Design.BottomSheet.Modal">
<item name="android:background">#drawable/drawable_bottomsheet_background</item>
</style>
<style name="BaseBottomSheetDialog" parent="#style/Theme.Design.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="bottomSheetStyle">#style/BottomSheet</item>
</style>
<style name="BottomSheetDialogTheme" parent="BaseBottomSheetDialog" />
Now create a custom class that will extend BottomSheetDilogFragment ,where you provide your style .
open class CustomRoundBottomSheet : BottomSheetDialogFragment() {
override fun getTheme(): Int = R.style.BottomSheetDialogTheme
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = BottomSheetDialog(requireContext(), theme)
}
Now use this class wherever you want to have round corner bottom sheet .
eg
class BottomSheetSuccess : CustomRoundBottomSheet() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.bottomsheet_shopcreate_success, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
}
Simplistic solution:
class TopRoundedCornersFragment : BottomSheetDialogFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NORMAL, R.style.AppBottomSheetDialogTheme)
}
}
In styles.xml
<style name="BottomSheetStyle" parent="Widget.Design.BottomSheet.Modal">
<item name="android:background">#drawable/bottom_sheet_dialog_bg</item>
</style>
<style name="AppBottomSheetDialogTheme" parent="Theme.Design.Light.BottomSheetDialog">
<item name="bottomSheetStyle">#style/BottomSheetStyle</item>
</style>
Last, create a top rounded corner drawable resource (bottom_sheet_dialog_bg.xml)
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#android:color/white" />
<corners
android:topLeftRadius="4dp"
android:topRightRadius="4dp" />
</shape>
I know this question already has an accepted answer. I'd like to document the problems I went through and how I finally got it working so it is useful for someone on the future.
Firstly, I was using Theme.AppCompat.Light.DarkActionBar as the parent for our AppTheme. This meant #Gabriele Mariotti solution kept crashing with the error Could not inflate Behavior subclass com.google.android.material.bottomsheet.BottomSheetBehavior. I fixed this by simply changing the parent to Theme.MaterialComponents.Light.DarkActionBar. This did not affect our theme in any way but the RTE was gone. You can also fix this issue by simply including the require items to your style. But I didn't bother figuring out which styles were required by BottomSheetBehavior.
Secondly, try as I might, but I couldn't get the actual Frame layout (which was the BottomSheetDialogFragment) uses to have round corners. I realized that setting this to an image Drawable worked but not with a shape or a #null. Turns out, it was because the LinearLayout I was using had a background defined. This was overriding any background in the style. Removing that finally resulted in rounded corners.
Also, I didn't require any background shape to be set to round the corners. #Gabriele Mariotti's solution worked as soon as I made the above changes. However, to set the background colour what I wanted it to be, I had to override the "backgroundTint" item.
PS: I'm new to Android dev, and am maintaining an old App that was made for internal use in our College. I'm not all that familiar with Android's layout system or with the material library. I guess that's why it took me 3 days to figure this out. I hope this is useful to someone in the future.
This answer is only for the issue of setting the background color to Color.TRANSPARENT after setting up a drawable with rounded background to the layout.
None of the answer worked for me to set the background color to Color.TRANSPARENT except overriding setupDialog() solution:
#Override
public void setupDialog(Dialog dialog, int style) {
super.setupDialog(dialog, style);
View contentView = View.inflate(getContext(),
R.layout.fragment_bottom_sheet, null);
dialog.setContentView(contentView);
...
((View) contentView.getParent()).setBackgroundColor(ContextCompat.getColor(getContext(), android.R.color.transparent));
}
BUT the contentView you set for dialog here is not the view you get in onViewCreated() when inflating in onCreateView(). It breaks the standard flow, so may issue troubles like you can't use View Bindings - Kotlin Android Extensions in onViewCreated()
So I tweak a bit to set the background in onActivityCreated():
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
(view?.parent as View).setBackgroundColor(Color.TRANSPARENT)
}
Hope this help who got same trouble
Bottom Sheet Dialog with Curved shape and peek height
<!-- BottomSheet Dialog -->
<style name="BottomSheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
<item name="bottomSheetStyle">#style/CustomBottomSheet</item>
</style>
<style name="CustomBottomSheet" parent="Widget.MaterialComponents.BottomSheet">
<item name="shapeAppearanceOverlay">#style/CustomShapeAppearanceBottomSheetDialog</item>
<item name="behavior_peekHeight">420dp</item>
</style>
<style name="CustomShapeAppearanceBottomSheetDialog" parent="">
<item name="cornerFamily">rounded</item>
<item name="cornerSizeTopRight">20dp</item>
<item name="cornerSizeTopLeft">20dp</item>
<item name="cornerSizeBottomRight">0dp</item>
<item name="cornerSizeBottomLeft">0dp</item>
</style>
As pointed in other answers, when state is BottomSheetBehavior.STATE_EXPANDED corners will be flattened.
You can overcome this issue by setting peekHeight property of BottomSheetBehavior and using your custom style.
abstract class BaseBottomSheetFragment : BottomSheetDialogFragment(){
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
if (state == BottomSheetBehavior.STATE_EXPANDED) {
val displayMetrics = DisplayMetrics()
requireActivity().windowManager!!.defaultDisplay!!.getMetrics(displayMetrics)
(dialog as BottomSheetDialog).behavior.peekHeight = displayMetrics.heightPixels
} else {
(dialog as BottomSheetDialog).behavior.state = state
}
}
override fun getTheme(): Int {
return R.style.CustomBottomSheetDialog
}
}
CustomBottomSheetDialog Style
<style name="CustomBottomSheetDialog" parent="#style/ThemeOverlay.MaterialComponents.BottomSheetDialog">
<item name="bottomSheetStyle">#style/CustomBottomSheet</item>
<item name="materialButtonStyle">#style/CustomMaterialButtonStyle</item>
</style>
<style name="CustomMaterialButtonStyle" parent="#style/Widget.MaterialComponents.Button">
<item name="cornerRadius">#dimen/dialog_bottom_radius</item>
</style>
<style name="CustomBottomSheet" parent="Widget.MaterialComponents.BottomSheet">
<item name="shapeAppearanceOverlay">#style/CustomShapeAppearanceBottomSheetDialog</item>
</style>
<style name="CustomShapeAppearanceBottomSheetDialog" parent="">
<item name="android:background">#android:color/transparent</item>
<item name="backgroundTint">#android:color/transparent</item>
<item name="cornerFamily">rounded</item>
<item name="cornerSizeTopRight">#dimen/dialog_bottom_radius</item>
<item name="cornerSizeTopLeft">#dimen/dialog_bottom_radius</item>
<item name="cornerSizeBottomRight">0dp</item>
<item name="cornerSizeBottomLeft">0dp</item>
</style>
Shorter solution to disable flatting of rounded corners on STATE_EXPANDED:
#SuppressLint("RestrictedApi")
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState)
//Disable animator that flats the rounded corners
(dialog as BottomSheetDialog).behavior.disableShapeAnimations()
return dialog
}
Add these two methods in your BottomsheetDialogFragment class.
public void setDialogBorder(Dialog dialog) {
FrameLayout bottomSheet = (FrameLayout) dialog.getWindow().findViewById(android.support.design.R.id.design_bottom_sheet);
bottomSheet.setBackground(new ColorDrawable(Color.TRANSPARENT));
setMargins(bottomSheet, 10, 0, 10, 20);
}
private void setMargins(View view, int left, int top, int right, int bottom) {
if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
p.setMargins(left, top, right, bottom);
view.requestLayout();
}
}
Now call setDialogBorder(dialog) method in setupDialog() method of your BottomsheetDialogFragment class.
Now create a shape file in your drawable folder.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="20dp" />
<solid android:color="#color/white" />
<stroke
android:width="1dp"
android:color="#color/transparent" />
</shape>
Now set background for the parent viewgroup dialog view in xml file.
android:background="#drawable/round_border_white"
Done!!
You have to change the bottom sheet theme to achieve the top round layout
Create a custom drawable background_bottom_sheet_dialog_fragment.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:topLeftRadius="8dp"
android:topRightRadius="8dp" />
<padding android:top="0dp" />
<solid android:color="#color/white" />
</shape>
Then override bottomSheetDialogTheme on styles.xml using the drawable as background:
<!--Bottom sheet-->
<style name="BottomSheet" parent="#style/Widget.Design.BottomSheet.Modal">
<item
name="android:background">#drawable/background_bottom_sheet_dialog_fragment
</item>
</style>
<style name="BaseBottomSheetDialog"
parent="#style/Theme.Design.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="bottomSheetStyle">#style/BottomSheet</item>
</style>
<style name="BottomSheetDialogTheme" parent="BaseBottomSheetDialog" />
This will change the background layout of your bottom sheet
BottomSheetDialog
class SheetFragment() : BottomSheetDialogFragment() {
lateinit var binding: SheetFragmentBinding;
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog;
val view = View.inflate(context, R.layout.fragment_bottom_sheet, null);
binding = DataBindingUtil.bind(view)!!;
binding.viewModel = SheetFragmentVM();
dialog.setContentView(view);
var bottomSheetBehavior = BottomSheetBehavior.from(view.parent as View);
bottomSheetBehavior.setPeekHeight(BottomSheetBehavior.PEEK_HEIGHT_AUTO);
bottomSheetBehavior.setBottomSheetCallback(object :
BottomSheetBehavior.BottomSheetCallback() {
override fun onStateChanged(bottomSheet: View, newState: Int) {
if (BottomSheetBehavior.STATE_EXPANDED == newState) {
// do on STATE_EXPANDED
}
if (BottomSheetBehavior.STATE_COLLAPSED == newState) {
// do on STATE_COLLAPSED
}
if (BottomSheetBehavior.STATE_HIDDEN == newState) {
dismiss()
}
}
override fun onSlide(bottomSheet: View, slideOffset: Float) {
// do on slide
}
})
return dialog
}
add shape with rounded corner, make it background for your root layout
<?xml version="1.0" encoding="utf-8" ?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:topLeftRadius="#dimen/padding_margin_16_dp"
android:topRightRadius="#dimen/padding_margin_16_dp" />
<solid android:color="#color/white" />
</shape>
make background transparent on your BottomSheetDialogFragment
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
(view?.parent as View).setBackgroundColor(Color.TRANSPARENT)
}
its work for Contraintlayout, Framelyaout, Linearlayout, Relativelayout.
Complete Solution:
Add below style attribute to style.xml.
<style name="AppBottomSheetDialogTheme"
parent="Theme.Design.Light.BottomSheetDialog">
<item name="bottomSheetStyle">#style/AppModalStyle</item>
</style>
<style name="AppModalStyle"
parent="Widget.Design.BottomSheet.Modal">
<item name="android:background">#drawable/bottom_sheet_background</item>
</style>
Then use AppBottomSheetDialogTheme to create a bottom sheet dialog from your code.
private fun openBottomSheetTermsCondition() {
val mBottomSheetDialog = BottomSheetDialog(requireContext(),R.style.AppBottomSheetDialogTheme)
val sheetView = layoutInflater.inflate(R.layout.bottom_sheet_travel_advice_terms, null)
mBottomSheetDialog.setContentView(sheetView)
sheetView.tv_head.setOnClickListener {
mBottomSheetDialog.dismiss()
}
sheetView.webView.loadDataWithBaseURL(null,getString(R.string.privacy_policy_body_html),"text/html", "utf-8", null)
mBottomSheetDialog.show()
}
I use the below drawable to round the bottom sheet background.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:topLeftRadius="#dimen/bottom_sheet_corner_radius"
android:topRightRadius="#dimen/bottom_sheet_corner_radius" />
<solid android:color="#color/white" />
</shape>
Bottom sheet xml bottom_sheet_travel_advice_terms.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:behavior_hideable="false"
app:behavior_peekHeight="#dimen/bottom_sheet_peek_height"
app:cardCornerRadius="#dimen/spacing_normal"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/spacing_small">
<androidx.constraintlayout.widget.Guideline
android:id="#+id/begin_horizontal_guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="#dimen/activity_vertical_margin" />
<androidx.constraintlayout.widget.Guideline
android:id="#+id/begin_vertical_guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="#dimen/activity_horizontal_margin" />
<androidx.constraintlayout.widget.Guideline
android:id="#+id/end_vertical_guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_end="#dimen/activity_horizontal_margin" />
<View
android:id="#+id/sheet_header_shadow"
android:layout_width="match_parent"
android:layout_height="#dimen/spacing_tiny"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:background="#drawable/bottom_sheet_header_shadow"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/tv_head"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawablePadding="#dimen/spacing_normal"
android:fontFamily="sans-serif-medium"
android:gravity="start"
android:padding="#dimen/spacing_small"
android:text="#string/term_and_condition"
android:textColor="#color/greyish_brown"
android:textSize="20sp"
app:drawableLeftCompat="#drawable/ic_close_black_24dp"
app:layout_constraintEnd_toEndOf="#id/end_vertical_guideline"
app:layout_constraintStart_toStartOf="#id/begin_vertical_guideline"
app:layout_constraintTop_toBottomOf="#+id/begin_horizontal_guideline" />
<View
android:id="#+id/line_separation"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="#dimen/spacing_small"
android:background="#color/blue_gray"
app:layout_constraintTop_toBottomOf="#+id/tv_head" />
<WebView
android:id="#+id/webView"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="#id/end_vertical_guideline"
app:layout_constraintStart_toStartOf="#id/begin_vertical_guideline"
app:layout_constraintTop_toBottomOf="#id/line_separation" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
setupDialog() is RestrictedApi. The simplest solution that works as of material:1.3.0-beta01 without touching themes:
res/drawable/bs_background:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:topLeftRadius="16dp"
android:topRightRadius="16dp" />
<solid android:color="#color/dayNightBackground" />
</shape>
public class MyBsDialogFrag extends BottomSheetDialogFragment {
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
((View) view.getParent()).setBackgroundResource(R.drawable.bs_background);
}
}
firstly you should create a drawable xml file that contains a shape with a top rounded corner, name whatever you want.
I named it a bottom rounded_top_shape.xml
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<solid android:color="#android:color/white" />
<corners
android:topLeftRadius="16dp"
android:topRightRadius="16dp"
/>
then in your style.xml add this
<style name="AppBottomSheetDialogTheme" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
<item name="bottomSheetStyle">#style/AppModalStyle</item>
</style>
<style name="AppModalStyle" parent="Widget.Design.BottomSheet.Modal">
<item name="android:background">#drawable/rounded_top_shape</item>
</style>
then in your app theme add this line as bellow
<style name="MyAppTheme" parent="Theme.MaterialComponents.Light.Bridge">
<!-- this line -->
<item name="bottomSheetDialogTheme">#style/AppBottomSheetDialogTheme</item>
</style>
I found simple solution.
works with com.google.android.material:material:1.6.1
class MyBottomSheet: BottomSheetDialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
disableShapeAnimation()
}
#SuppressLint("RestrictedApi", "VisibleForTests")
private fun disableShapeAnimation() {
try {
val dlg = dialog as BottomSheetDialog
dlg.behavior.disableShapeAnimations()
} catch (ex: Exception) {
Log.e("BaseBottomSheet", "disableShapeAnimation Exception:", ex)
}
}
}
Another way to fix this issue is to extend BottomSheetDialog and create a custom class which suits your needs. You can do the same for layout xml file, and add background or any other customizations needed. This also has a benefit that you'll not be dependent on the id names used by Android(android.support.design.R.id.design_bottom_sheet), while changing the background (though the change of id name rarely happens AFAIK).
Create a custom drawable with rounded corner and set it as background of your BottomSheetDialogFragment's layout root
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#color/colorPrimary" />
<corners
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"
android:topLeftRadius="12dp"
android:topRightRadius="12dp" />
</shape>
And then simply add the below code to your BottomSheetDialogFragment class
#Override
public void setupDialog(Dialog dialog, int style) {
super.setupDialog(dialog, style);
View contentView = View.inflate(getContext(),
R.layout.fragment_bottom_sheet, null);
dialog.setContentView(contentView);
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) ((View) contentView.getParent())
.getLayoutParams();
CoordinatorLayout.Behavior behavior = params.getBehavior();
((View) contentView.getParent()).setBackgroundColor(ContextCompat.getColor(getContext(), android.R.color.transparent));
}
You can even play with the params to set margin like below
params.setMargins(50, 0, 50, 0);
If you need setFitContents=true, I tried the solution by hooking onStateChanged, but it flickers from the straight to rounded corners once the dialog reaches EXPANDED state. It's quite annoying.
There is an alternative workaround that doesn't cause flickering, doesn't require using private APIs, and is more readable (imho).
Looking at the code of BottomSheetBehavior we find:
/** True if Behavior has a non-null value for the #shapeAppearance attribute */
private boolean shapeThemingEnabled;
Turns out if shape theming is disabled, MaterialShapeDrawable will not be used. We find this in BottomSheetBehavior.onLayout():
// Only set MaterialShapeDrawable as background if shapeTheming is enabled, otherwise will
// default to android:background declared in styles or layout.
if (shapeThemingEnabled && materialShapeDrawable != null) {
ViewCompat.setBackground(child, materialShapeDrawable);
}
Defaulting to android:background is exactly what we need, as this means complete control on how the background is rendered.
We can disable material theming by creating a separate style and setting shapeAppearance and shapeAppearanceOverlay to null:
<style name="Theme.YourApp.NoShapeBottomSheetDialog" parent="Theme.MaterialComponents.BottomSheetDialog">
<item name="bottomSheetStyle">#style/Theme.YourApp.NoShapeButtonSheet</item>
</style>
<style name="Theme.YourApp.NoShapeButtonSheet" parent="Widget.MaterialComponents.BottomSheet.Modal">
<item name="shapeAppearance">#null</item>
<item name="shapeAppearanceOverlay">#null</item>
</style>
Extend BottomSheetDialogFragment and override onCreateDialog:
public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
return new BottomSheetDialog(requireContext(),
R.style.Theme_Grupin_NoShapeBottomSheetDialog);
}
The bottom sheet is now naked, without any background at all. So we can add any background we want, no animation will be triggered anymore.
If you are using material components theme, you can override the default behavoir of BottomSheetDialog by setting the background color to transparent then set the background of your layout to be rounded.
<style name="Theme.MyApp" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Customize your theme here. -->
<item name="bottomSheetDialogTheme">#style/BottomSheetDialog</item>
</style>
<style name="BottomSheetDialog" parent="ThemeOverlay.MaterialComponents.BottomSheetDialog">
<item name="bottomSheetStyle">#style/bottomSheetStyleWrapper</item>
</style>
<style name="bottomSheetStyleWrapper" parent="Widget.MaterialComponents.BottomSheet.Modal">
<item name="android:backgroundTint">#android:color/transparent</item>
</style>
rounded_corner.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#color/white"/>
<corners android:topLeftRadius="26dp"
android:topRightRadius="26dp"/>
</shape>
Then apply the shape to background of your bottom sheet root layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/rounded_corner">
<!--
other layout components
-->
</LinearLayout>
Note that if you're having component like Webview in the bottom sheet layout, you may not be able to achieve the rounded corner as expected because Webview has a default white background. In this case, you can simply remove the background like this:
webView.setBackgroundColor(0);
I would like to display a bottom sheet dialog less wide than the screen width.
For instance, the Share option from Google Play Music on a Nexus 9.
Do you know how to achieve this ?
For now I just succed to reduce the width of the sheet content but the background is still at the screen width and display a white background.
Some code:
build.gradle
compile 'com.android.support:design:23.3.0'
MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
...
mBottomSheetDialog = new BottomSheetDialog(this);
mBottomSheetDialog.setContentView(R.layout.sheet_test);
mBottomSheetDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
mBottomSheetDialog = null;
}
});
mBottomSheetDialog.show();
}
sheet_test
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="100dp"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
style="#style/TextAppearance.AppCompat.Body1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="Some Text"
android:textColor="#color/colorPrimary" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#ddd" />
<TextView
style="#style/TextAppearance.AppCompat.Body1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp"
android:text="Some Text" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#ddd" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
This worked for me when using BottomSheetDialogFragment:
public class CustomDialogFragment extends BottomSheetDialogFragment {
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(BottomSheetDialogFragment.STYLE_NORMAL, R.style.CustomBottomSheetDialogTheme);
}
...
}
Also add this to your styles.xml
<style name="CustomBottomSheetDialogTheme" parent="Theme.Design.Light.BottomSheetDialog">
<item name="bottomSheetStyle">#style/CustomBottomSheetStyle</item>
</style>
<style name="CustomBottomSheetStyle" parent="Widget.Design.BottomSheet.Modal">
<item name="android:background">#android:color/transparent</item>
</style>
Option 2:
override fun getTheme() = R.style.CustomBottomSheetDialogTheme
BottomSheetDialog bottomSheetDialog =new BottomSheetDialog(this,R.style.SheetDialog);
<style name="SheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
<!--<item name="android:windowCloseOnTouchOutside">false</item>-->
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:colorBackground"> #android:color/transparent</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="android:backgroundDimAmount">0.3</item>
<item name="android:windowFrame">#null</item>
<item name="android:windowIsFloating">true</item>
</style>
This is simplest solution for set transparent background of BottomSheetDialogFragment
It makes use of the following line of code:
((View) contentView.getParent()).setBackgroundColor(getResources().getColor(android.R.color.transparent));
Example in context:
public class ShareOneTouchAlertNewBottom extends BottomSheetDialogFragment {
#Override
public void setupDialog(Dialog dialog, int style) {
super.setupDialog(dialog, style);
View contentView = View.inflate(getContext(), R.layout.fragment_bottom_sheet, null);
dialog.setContentView(contentView);
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) ((View) contentView.getParent())
.getLayoutParams();
CoordinatorLayout.Behavior behavior = params.getBehavior();
((View) contentView.getParent()).setBackgroundColor(Color.TRANSPARENT);
}
}
Sorry got it late here is what you are looking for upvote if u have done it successfully
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
((View) getView().getParent()).setBackgroundColor(Color.TRANSPARENT);
}
Add this line in bottom sheet dialog fragment's on activity created. This will do the trick
The following function override worked in a BottomSheetDialogFragment implementation:
class MyTopicBottomSheet : BottomSheetDialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return super.onCreateDialog(savedInstanceState).apply {
// window?.setDimAmount(0.2f) // Set dim amount here
setOnShowListener {
val bottomSheet = findViewById<View>(com.google.android.material.R.id.design_bottom_sheet) as FrameLayout
bottomSheet.setBackgroundResource(android.R.color.transparent)
}
}
}
// Rest of your class here
}
Following the idea from Marco RS (that for me was the only solution at all that works), you can create a clean extension and apply wherever you want on your dialogs.
Extension:
fun BottomSheetDialogFragment.setTransparentBackground() {
dialog?.apply {
setOnShowListener {
val bottomSheet = findViewById<View?>(R.id.design_bottom_sheet)
bottomSheet?.setBackgroundResource(android.R.color.transparent)
}
}
Example:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setTransparentBackground()
}
Bit of a hack but it works for making background transparent. Obviously you can replace the 'transparent' with whatever colour you want.
mBottomSheetDialog.getWindow().findViewById(R.id.design_bottom_sheet).setBackgroundResource(android.R.color.transparent);
There are several hackish ways to do it. The way I solved this issue is the recommended way. Let's understand why?
In the docs, it's mentioned that
Modal bottom sheet. This is a version of DialogFragment that shows a bottom sheet using BottomSheetDialog instead of a floating dialog.
This means there should be a method that BottomSheetDialogFragment uses to replace the default Dialog with a BottomSheetDialog.
The only method BottomSheetDialogFragment overrides is onCreateDialog(). So we're gonna use this public method to override our dialog style.
Recommended Method
In the fragment that extends BottomSheetDialogFragment overrDide onCreateDialog() which is a public method exposed by BottomSheetDialogFragment itself.
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
setStyle(STYLE_NO_FRAME, R.style.BottomSheetDialog)
return super.onCreateDialog(savedInstanceState)
}
besides that, in themes.xml override BottomSheetDialog theme and add transparent background.
<style name="BottomSheetDialog" parent="ThemeOverlay.MaterialComponents.BottomSheetDialog">
<item name="bottomSheetStyle">#style/BottomSheetModal</item>
</style>
<style name="BottomSheetModal" parent="Widget.Design.BottomSheet.Modal">
<item name="android:background">#android:color/transparent</item>
</style>
More about:
BottomSheetDialogFragment: here
onCreateDialog: here
theming the BottomSheetDialog: here
So, I figured out 2 solutions.
Best one:
Create an activity with transparent background just for your bottom sheet.
Implement your own layout with a coordinator layout and a bottom sheet.
Set the margin you want.
Set the content you want.
Not tested yet.
Lazy one:
Extends BottomSheetDialogFragment, in onActivityCreated add:
Resources resources = getResources();
// Set margin for Landscape Mode. Maybe a more elegant solution will be to implements our own bottom sheet with our own margins.
if (resources.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
assert getView() != null;
View parent = (View) getView().getParent();
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) parent.getLayoutParams();
layoutParams.setMargins(
resources.getDimensionPixelSize(R.dimen.bottom_sheet_margin_left), // 64dp
0,
resources.getDimensionPixelSize(R.dimen.bottom_sheet_margin_right), // 64dp
0
);
parent.setLayoutParams(layoutParams);
}
I had same problem, nothing helped.
Used this code to solve the problem:
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
val bottomSheet = (view!!.parent as View)
bottomSheet.backgroundTintMode = PorterDuff.Mode.CLEAR
bottomSheet.backgroundTintList = ColorStateList.valueOf(Color.TRANSPARENT)
bottomSheet.setBackgroundColor(Color.TRANSPARENT)
}
P.S. com.google.android.material:material:1.1.0-alpha09
BottomSheetDialog will get the R.attr.bottomSheetDialogTheme style from your context's theme, or else use the default R.style.Theme_Design_Light_BottomSheetDialog.
The layout xml of BottomSheetDialog is R.layout.design_bottom_sheet_dialog. The main content is a FrameLayout with id/design_bottom_sheet whose style is ?attr/bottomSheetStyle.
If you extends a style with parent Theme.Design.Light.BottomSheetDialog then all your default attrs like colorPrimary, colorAccent may be overrided. Thus ThemeOverlay is recommended to be used in View Theme tree. You should extend a style from ThemeOverlay.MaterialComponents.Light.BottomSheetDialog like this:
<style name="Widget.Test.ButtonSheetDialogTheme" parent="ThemeOverlay.MaterialComponents.Light.BottomSheetDialog">
<item name="bottomSheetStyle">#style/Widget.Test.BottomSheet.Modal</item>
</style>
<style name="Widget.Test.BottomSheet.Modal" parent="Widget.MaterialComponents.BottomSheet.Modal">
<item name="backgroundTint">#android:color/transparent</item>
</style>
You have to extend a style from Widget.MaterialComponents.BottomSheet.Modal, because the default style contains these:
<style name="Widget.MaterialComponents.BottomSheet" parent="Widget.Design.BottomSheet.Modal">
<item name="android:background">#null</item>
<item name="backgroundTint">?attr/colorSurface</item>
....
</style>
BottomSheetDialog's background is decided both by android:background and backgroundTint. But I am not sure why backgroundTint is effective while android:background is null. 🤔??
For more knowledge about Android Theme:
Android Styling: themes overlay
Late answer, but faced this problem myself and found better solution then any of suggested.
You can wrap your sheet layout with another layout with transparent background and add margin from it (16dp here):
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/transparent"
>
<android.support.v4.widget.NestedScrollView
android:layout_width="100dp"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_margin="16dp">
....
Then add transparent background to your sheet like in Gnzlt answer:
<style name="CustomBottomSheetDialogTheme" parent="Theme.Design.Light.BottomSheetDialog">
<item name="bottomSheetStyle">#style/CustomBottomSheetStyle</item>
</style>
<style name="CustomBottomSheetStyle" parent="Widget.Design.BottomSheet.Modal">
<item name="android:background">#android:color/transparent</item>
</style>
And voila, don't need another activity.
This worked for me.. Oncreate Dialog get the window set color
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
if(dialog.getWindow() !=null){
dialog.getWindow().setGravity(Gravity.BOTTOM);
dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
dialog.setCancelable(false);
}
return dialog;
}
use "setOnShowListener" for your dialog instance, like this in kotlin:
yourDialogInstance.setOnShowListener {
//this line transparent your dialog background
(dialogView.parent as ViewGroup).background =
ColorDrawable(Color.TRANSPARENT)
}
complete code in kotlin :
BottomSheetDialog(this).apply {
val dialogView = LayoutInflater.from(context)
.inflate(R.layout.your_dialog_layout, null, false)
setContentView(dialogView)
setOnShowListener {
(dialogView.parent as ViewGroup).background =
ColorDrawable(Color.TRANSPARENT)
}
show()
}
This is your answer :D
View contentView=LayoutInflater.from(getContext()).inflate(R.layout.bs_add_event,null);
mBottomSheetDialog.setContentView(contentView);
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) ((View) contentView.getParent()).getLayoutParams();
params.setMargins(50,50,50,50); // set margin as your wish.
and also change android:layout_width="100dp" in nestedScroolView to
android:layout_width="match_parent"
1. Firstly Add Style in your theme:
<style name="MyTransparentBottomSheetDialogTheme" parent="Theme.AppCompat.Light">
<item name="android:background">#android:color/transparent</item>
<item name="android:colorBackground">#android:color/transparent</item>
</style>
2. Then attach above style with BottomSheetDialogFragment same as below :
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new BottomSheetDialog(getContext(),R.style.MyTransparentBottomSheetDialogTheme);
}
1 - Initialize the bottom sheet dialog this way.
BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(YourActivity.this, R.style.BottomSheetDialog);
2 - Add this style as suggested by Gnzlt.
<style name="BottomSheetDialog" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
<item name="bottomSheetStyle">#style/BottomSheetDialogStyle</item>
</style>
<style name="BottomSheetDialogStyle" parent="Widget.MaterialComponents.BottomSheet.Modal">
<item name="android:background">#android:color/transparent</item>
<item name="android:backgroundTint">#android:color/transparent</item>
</style>
I know this question is old but I still answer the question and hope it useful.
By default, the layout specified in onCreateView() method will be added to a FrameLayout with white background by BottomSheetDialogFragment. Therefor, you should set the FrameLayout's background to transparent in onStart() method.
class YourDialog() : BaseBottomDialog() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.layout_your_dialog, container, false)
}
override fun onStart() {
super.onStart()
(view!!.parent as View).setBackgroundColor(Color.TRANSPARENT)
}
}
Found that I needed to use a variant on the accepted answer, by updating to MaterialComponents to make compatible with AndroidX as well as adding "backgroundTint" as transparent as well:
<style name="BottomSheetDialog" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
<item name="bottomSheetStyle">#style/BottomSheetDialogStyle</item>
</style>
<style name="BottomSheetDialogStyle" parent="Widget.MaterialComponents.BottomSheet.Modal">
<item name="android:background">#android:color/transparent</item>
<item name="android:backgroundTint">#android:color/transparent</item>
</style>
Apply the "BottomSheetDialog" style to the fragment as per the original answer:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(BottomSheetDialogFragment.STYLE_NORMAL, R.style.BottomSheetDialog);
}
Just Add the following code in your style.xml
<style name="BottomDialogStyle" parent="Theme.Design.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:statusBarColor">#android:color/transparent</item>
<item name="android:windowSoftInputMode">adjustResize</item>
<item name="bottomSheetStyle">#style/CustomBottomSheetStyle</item>
</style>
<style name="CustomBottomSheetStyle" parent="Widget.Design.BottomSheet.Modal">
<item name="android:background">#android:color/transparent</item>
</style>
Also, update the onCreate
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NORMAL, R.style.BottomDialogStyle)
}
If you are using BottomSheetBehavior then use the below code on collapse and Expand states
behavior.setState(BottomSheetBehavior.STATE_EXPANDED); ((View)getParent()).setBackgroundColor(getResources().getColor(<your desire color>));
and
behavior.setState(BottomSheetBehavior.STATE_COLLAPSED); ((View).getParent()).setBackgroundColor(getResources().getColor(android.R.color.transparent));
Also, use
behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_COLLAPSED) {
((View) mScrollview.getParent()).setBackgroundColor(getResources().getColor(android.R.color.transparent));
}
}
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset) {
// React to dragging events
}
});
If you want all your BottomSheets inherit that behavior, just do as follows:
<style name="Theme.InstaDownloader" parent="Theme.MaterialComponents.Light.NoActionBar">
...
<item name="bottomSheetDialogTheme">#style/BottomSheetTheme</item>
...
</style>
<style name="BottomSheetTheme" parent="Theme.Design.Light.BottomSheetDialog">
<item name="bottomSheetStyle">#style/BottomSheetStyle</item>
</style>
<style name="BottomSheetStyle" parent="Widget.Design.BottomSheet.Modal">
<item name="android:background">#android:color/transparent</item>
</style>
For me below worked:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
(view.parent as? View)?.setBackgroundColor(Color.TRANSPARENT)
}
<style name="BaseBottomSheetDialogTrasn" parent="#style/Theme.Design.Light.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="bottomSheetStyle">#style/BottomSheetTrans</item>
</style>
<style name="BottomSheetDialogThemeTrans" parent="BaseBottomSheetDialogTrasn">
<item name="android:statusBarColor">#android:color/transparent</item>
<item name="android:navigationBarColor">#color/white</item>
</style>
<style name="BottomSheetTrans" parent="#style/Widget.Design.BottomSheet.Modal">
<item name="android:background">#android:color/transparent</item>
</style>
And finally add the parameter in BottomSheetDialog(context,R.style.BottomSheetDialogThemeTrans)
I know I'm much late but in kotlin the thing that really helped me out is adding this line in your fragment in onCreate():
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NORMAL,R.style.CustomBottomSheetDialog)
}
And in styles():
<style name="CustomBottomSheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
<item name="bottomSheetStyle">#style/bottomSheetStyleWrapper
</item>
</style>
<style name="bottomSheetStyleWrapper"
parent="Widget.Design.BottomSheet.Modal">
<item
name="android:background">#android:color/transparent</item>
</style>
Works perfectly fine for me.
Adding android:background or android:colorBackground property will not make the bottom sheet transparent as suggested by many answers!
Adding, backgroundTint to sheetStyle is the key to making bottomsheet transparent.
Eg:
<style name="BottomSheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
<item name="bottomSheetStyle">#style/BottomSheetStyle</item>
</style>
The following piece is key,
<style name="BottomSheetStyle" parent="Widget.MaterialComponents.BottomSheet.Modal">
<item name="backgroundTint">#android:color/transparent</item>
</style>
Pass this style as second parameter while creating the BottomSheetDialog in java or kt.
Eg:
BottomSheetDialog(context, R.style.BottomSheetDialog)
Resource:
A good resource to learn more about BottomSheet https://m2.material.io/develop/android/components/bottom-sheet-dialog-fragment
I have a DialogFragment which I want to show in fullscreen. I do however still want a StatusBar present, and the hardware buttons at the bottom. I also want to set a background color of the StatusBar (for Lollipop).
My problem is that if I set the following flags in the DialogFragment:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
Both the StatusBar and Hardware keyboard becomes translucent, and the DialogFragment stretches behind these.
Here is the code, which has been greatly reduced to become readable:
public class CardDetailsDialog extends DialogFragment {
Setup parameters...
public static CardDetailsDialog newInstance(final long cardId, final long projectId){
CardDetailsDialog frag = new CardDetailsDialog();
frag.setStyle(DialogFragment.STYLE_NORMAL, R.style.CardDetailsDialogStyle);
return frag;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if(getDialog() != null) {
getDialog().getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
getDialog().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getDialog().getWindow().getAttributes().windowAnimations = R.style.DialogSlideAnimation;
getDialog().getWindow().setLayout(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
getDialog().getWindow().setStatusBarColor(Color.RED);
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.card_details, container, false);
Handle everything that happens inside the view...
return view;
}
}
Here is the referred theme:
<style name="CardDetailsDialogStyle" parent="#style/Theme.AppCompat.Light.Dialog" >
<item name="android:windowBackground">#null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowFrame">#null</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:windowAnimationStyle">#android:style/Animation.Dialog</item>
<item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
</style>
And the style of the fragment:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/pp.whiteBackgroundColor" >
<android.support.v7.widget.Toolbar xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/card_details_toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_alignParentTop="true"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/PopupMenutheme">
</android.support.v7.widget.Toolbar>
<ScrollView
android:id="#+id/details_scrollview"
android:layout_height="wrap_content"
android:layout_width="match_parent">
All subview elements here...
</ScrollView>
</RelativeLayout>
This is the result:
As you can see, the ToolBar extends over the StatusBar and hardware buttons. I don't know if I am approaching this correctly. Am I missing something?
EDIT
This is what the same view look likes when I remove
getDialog().getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
For anyone who's still having this problem, do the following. This just solves half of the problem that is posted i.e. black status bar.
Add following theme to res/value-v21/style
<style name="DialogTheme" parent="#style/Base.Theme.AppCompat.Light.Dialog">
<item name="android:windowTranslucentStatus">true</item>
</style>
And then apply Style on DialogFragment in onCreate
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NO_TITLE, R.style.DialogTheme);
}
Edit
if you've problem with your dialog theme then use this style e.g. colorAccent or colorControlHighlight etc
<style name="DialogTheme" parent="#style/ThemeOverlay.AppCompat.Dialog">
<item name="android:windowTranslucentStatus">true</item>
</style>
In my case SYSTEM_UI_FLAG_LAYOUT_STABLE solved problem with overlapping
int width = ViewGroup.LayoutParams.MATCH_PARENT;
int height = ViewGroup.LayoutParams.MATCH_PARENT;
dialog.getWindow().setLayout(width,height);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
dialog.getWindow().setStatusBarColor(getResources().getColor(R.color.darkGrayTransp));
dialog.getWindow().getDecorView().setSystemUiVisibility(SYSTEM_UI_FLAG_LAYOUT_STABLE);//solves issue with statusbar
dialog.getWindow().setGravity(Gravity.CENTER_HORIZONTAL| Gravity.TOP);
}
Try use the same Style from your App. I tested with simple dialog without fragment and works fine.
Like that:
new Dialog(context, R.style.CardDetailsDialogStyle);
You have to set fitsystemwindows = true. Other way is to add a Space with 0dp and change its height to 25dp when the dialog is going to show.
To change the space size, use layout params, check this post: How to create a RelativeLayout programmatically with two buttons one on top of the other?
<style name="DialogTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowIsFloating">false</item>
</style>
Just apply android:fitsSystemWindows="true" to your root ViewGroup:
`<FrameLayout
android:fitsSystemWindows="true">
<View .../>
I want to hide the divider between preferences in fragment.
The code is below:
1.SettingsActivity.java
public class SettingsActivity extends PreferenceActivity {
super.onCreate(savedInstanceState);
SettingsFragment settingsFragement = new SettingsFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.add(android.R.id.content, settingsFragement, "settings");
transaction.commitAllowingStateLoss();
}
2.SettingsFragment.java
public class SettingsFragment extends PreferenceFragment{
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
}
}
3.settings.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory>
<Preference
android:key="preference_a"
android:title="preferenceA"/>
<Preference
android:key="preference_b"
android:title="preferenceB"/>
<ListPreference
android:key="list_preference_c"
android:title="list_preferenceC"/>
</PreferenceCategory>
</PreferenceScreen>
There are system default dividers amoung the preferences.
I want to hide the dividers.
How to hide the dividers? Thanks a lot.
Thanks for everyone`s answer. But,the question is that I cannot get the listview from the activity and fragment.
ListView list = (ListView) findViewById(android.R.id.list);
if you are using PreferenceFragmentCompat , it is using Recycle view so you have to use this code . This automatically hides the divider
#Nullable
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
setDivider(new ColorDrawable(Color.TRANSPARENT));
setDividerHeight(0);
}
These solutions didn't work for me. Here's what I did in PreferenceFragmentCompat:
#Override
public void setDivider(Drawable divider) {
super.setDivider(new ColorDrawable(Color.TRANSPARENT));
}
#Override
public void setDividerHeight(int height) {
super.setDividerHeight(0);
}
Define custom preference theme without dividers in your style.xml:
<style name="PrefsTheme" parent="PreferenceThemeOverlay.v14.Material">
<item name="android:divider">#null</item>
<item name="android:dividerHeight">0dp</item>
</style>
and don't forget to use it in your main app theme which is also in style.xml:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- ... -->
<item name="preferenceTheme">#style/PrefsTheme</item>
</style>
You can remove your divider by style.
<style name="PreferenceFragment.Material">
<item name="android:divider">#null</item>
</style>
First: if used the listview in xml
set the android:dividerHeight="0dp" in listview in xml file ,
second:
ListView list = (ListView) findViewById(android.R.id.list);
list.setDivider(new ColorDrawable(Color.TRANSPARENT)); // or some other color int
list.setDividerHeight((int) getResources().getDisplayMetrics().density);
I need to create a dialog over a fragment (that takes up the whole screen). The dialog needs to be a floating dialog that will be positioned over the fragment with the fragment darkened out outside of the fragment..
For the custom Dialog, i have a linearLayout that has curved edges, no matter what i do, the dialog has a black bordering on all sides (very small). I've tried everything to make it transparent and go away (so that all of the dialog is just the linear layout - curved box)
For the DialogFragment, this is what I have for onCreateView
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
LinearLayout layout =(LinearLayout)inflater.inflate(R.layout.custom_dialog, null);
LinearLayout item = (LinearLayout)layout.findViewById(R.id.display_item);
populateItemData(item, inflater);
return layout;
}
custom_dialog is just a LinearLayout that has android:backgroung set to #000000
This is my style for the custom Dialog
<style name="CustomDialog" parent="android:style/Theme.Dialog">
<item name="android:windowBackground">#null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:alwaysDrawnWithCache">false</item>
<item name="android:windowContentOverlay">#null</item>
</style>
I tried all kinds of combinations in this style (from what I've seen online) and I can't get rid of that annoying black bordering, I can paint it white or any other color if i set that LinearLayout background to anything other than #000000...
I've spent literally 3-4 hours on this, i hope someone else can help out...
Try
getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
in your DialogFragment's onCreateView
Try this (How to I create a 100% custom DialogFragment)
this work for dialog
Dialog dialog = new Dialog(getActivity());
dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
// layout to display
dialog.setContentView(R.layout.add_edit);
// set color transpartent
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
dialog.show();
Set your theme like this worked for me
<style name="MyDialog" parent="Base.Theme.AppCompat.Light.Dialog">
<item name="android:windowBackground">#android:color/transparent</item>
</style>
And in your dialog fragment set like this
public class Progress extends DialogFragment {
int style = DialogFragment.STYLE_NO_TITLE;
int theme = R.style.MyDialog;
public Progress() {
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(style, theme);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.progress, container, false);
}
}
You can achieve by adding this in
Dialog Fragment or BottomSheetDialogFragment
In onCreateDialog Method
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.getWindow().setGravity(Gravity.BOTTOM);
dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
return dialog;
}
In onActivityCreated
getDialog().getWindow().getAttributes().alpha = 0.9f; // An alpha value to apply to this entire window. An alpha of 1.0 means fully opaque and 0.0 means fully transparent
for DialogFragment transparent
For completely transparent use:
setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme_Translucent_NoTitleBar_Fullscreen);
For custom background -create a style file in you values folder (values/style.xml) and use it:
setStyle(DialogFragment.STYLE_NO_FRAME, yourpackagename.R.style.YOURE_CUSTOM_STYLE);
in your style file override the atribute:
android:windowBackground to be #color/DialogBackgroundBlackSemiTransparent
<style name="BaseDialogTheme" parent="Base.Theme.AppCompat.Light.Dialog">
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
<item name="colorControlNormal">#color/colorAccent</item>
<item name="colorControlActivated">#color/colorAccent</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:windowBackground">#android:color/transparent</item>
<item name="android:colorBackgroundCacheHint">#null</item>
<item name="android:colorBackground">#android:color/transparent</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
<item name="android:windowActionModeOverlay">false</item>
<item name="android:windowCloseOnTouchOutside">true</item>
<item name="android:backgroundDimAmount">.00</item>//this line is changed alpha from 1.0 to 0.0(full transparent)
</style>
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(STYLE_NO_FRAME, R.style.BaseDialogTheme);
}
Those who are using AlertDialog builder in onCreateDialog instead of onCreateView can assign theme like following code. Complete set of themes can be found from R.style. Don't forget that some of them supported recently and are not available on old device phones.
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), android.R.style.Theme_Translucent);
View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_album, null);
builder.setView(view);
return builder.create();
}
Try this if you like to:
public TransparentDialog()
{
super();
setStyle(STYLE_NO_FRAME, R.style.AppTheme);
}
Per accepted answer, in Kotlin
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
var v = super.onCreateView(inflater, container, savedInstanceState)
dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
return v
}