How to open BottomSheetDialogFragment fully expanded in Kotlin? - android

I am able to open my BottomSheetDialogFragment with
val bottomSheet = BottomSheetFragment()
bottomSheet.show(fragmentManager!!, "BottomSheet")
but it only opens to show half of its content - I would like it to expand on opening to the full height of the screen without having to drag it up.
I have looked around and it seems one way is to set the BottomSheetBehavior state to STATE_EXPANDED, but I have not been able to find a solution on how to do this in Kotlin.
Any help would be appreciated!

You can set the BottomSheetBehavior state by placing this inside
onViewCreated of your BottomSheetDialogFragment.
dialog.setOnShowListener { dialog ->
val d = dialog as BottomSheetDialog
val bottomSheet = d.findViewById<View>(R.id.design_bottom_sheet) as FrameLayout
val bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet)
bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
}
You may also want to set the peek height to the height of your dialog to prevent the dialog getting stuck half way when attempting to dismiss it.
bottomSheetBehavior.peekHeight = bottomSheet.height

Related

Android - Snackbar position and overlay the soft keyboard

My applications have a Toast. But if the soft keyboard is displayed the Toast sort of merged with the soft keyboard and is hard to distinguish. So I looked up how to set a custom view to a Toast. But the View property (SetView and GetView methods) is deprecated.
Instead I was told to use a Snackbar.
I have managed to create a Snackbar with a custom view. I have these problems:
The Snackbar's position is in the lower left corner of my app.
I would like to display the Snackbar as a Toast is displayed:
At the bottom and in the middle of the screen.
Some distance between the Snackbar's bottom and the screen's bottom.
The Snackbar is displayed behind the soft keyboard.
I would like to display the Snackbar above the soft keyboard.
I can hide the soft keyboard to show the Snackbar. But I would prefer not to hide it.
I have googled a lot on these two problems, but have not found any solutions.
For problem #1 I have tried
How can you adjust Android SnackBar to a specific position on screen
I was not able to get the CoordinatorLayout to compile.
Setting the margin on a Layout didn't work.
For problem #2 I have tried
Show Android SnackBar above keyboard? but it didn't work.
Here is my code:
res/layout/snackbar.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView style="#style/SomeStyle"
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:id="#+id/tvSnackbarText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Snackbar" />
Fragment
private fun showSnackbarMessage(message: String) {
val view: View = LayoutInflater
.from(context)
.inflate(R.layout.snackbar, null)
val tvSnackbarText = view.findViewById<TextView>(R.id.tvSnackbarText)
tvSnackbarText.text = message
tvSnackbarText.gravity = Gravity.CENTER
val snackbar = Snackbar.make(requireView(), "", Snackbar.LENGTH_LONG)
snackbar.view.setBackgroundResource(R.drawable.rounded_corner_box_grey_stroke);
val params = snackbar.view.layoutParams as FrameLayout.LayoutParams
params.height = FrameLayout.LayoutParams.WRAP_CONTENT
params.width = FrameLayout.LayoutParams.WRAP_CONTENT
snackbar.view.layoutParams = params
val layout = snackbar.view as Snackbar.SnackbarLayout
layout.addView(view)
snackbar.show()
}

Bottom Sheet content is showing for a second before activity content in Jetpack compose

I have implemented bottom sheet in jetpack compose with BottomSheetScaffold in a screen and default state is initialValue = BottomSheetValue.Collapsed.
When screen appears on device then Bottom sheet content is displayed for a second and then activity scope layout are presented and then bottom sheet behaves like it should. I am trying to remove this glitch from bottom sheet. Please let me know the suggestions which I can implement to remove this glitch.
Bottom sheet is working fine but it appears for a second before screen content and then disappears. This glitch needs to be removed.
Use a state for initial value storage, try
rememberModalBottomSheetState(
initialValue = ModalBottomSheetValue.Hidden,
)
I use this way to show the bottom sheets
val bottomSheetState = rememberModalBottomSheetState(
initialValue = ModalBottomSheetValue.Hidden,
)
ModalBottomSheetLayout(
sheetState = bottomSheetState,
sheetContent = {
//Sheet content
},
scrimColor = <SCREEN OVERLAY COLOR>,
sheetBackgroundColor = <BACKGROUND COLOR>
) {//Your Screen Code}
Hope this work for you!

How to set half expand ratio to bottom sheet in Compose?

In XML we have material3 bottom sheet. It allows us to set behavior of bottom sheet. It can be updated like:
bottomSheetBehavior.halfExpandedRatio = 0.6
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HALF_EXPANDED
I'm migrating project to Compose. My app used this half expanded ratio for 3 positioned bottom sheet: collapsed, half expanded, expanded. Now i'm trying to create bottom sheet like that:
val sheetState = rememberBottomSheetState(
initialValue = BottomSheetValue.Collapsed
)
val scaffoldState = rememberBottomSheetScaffoldState(
bottomSheetState = sheetState
)
BottomSheetScaffold(
scaffoldState = scaffoldState,
sheetContent = {}
) {}
But it looks like we don't have those behavior attributes here. Can we get the same behavior as in XML with half expanded bottom sheet?
Yes, it's possible. But it's a little bit of work. You basically have to provide your own implementations of the classes BottomSheetScaffold and SwipeableState as well as any related enums, classes and Composable functions used by these two.
The main points to focus on:
provide a third value to BottomSheetValue for the half-expanded state
provide a function that animates the half-expansion (similar to functions expand() and collapse() in BottomSheetState) as well as a property that checks if the bottom sheet is half expanded (similar to val isExpanded: Boolean)
add a third swipeable anchor to BottomSheetScaffold with the half expansion value you want to achieve (check line fullHeight - peekHeightPx to Collapsed, here is where you want to add your custom anchor)
handle the half expanded state in the .semantics block of the Modifier in BottomSheetScaffold
You might need to tweak a few more things depending on your specific requirement. It can take a while to set up everything but once it's done, it works like a charm.

Show scrollable full screen Bottom sheet Android

I have countered a situation that needs to implement a scrollable modal bottom sheet. Basically, it will show half off the screen at first, then when scrolling up, it will stretch to 90% of the screen. If keep swiping up, it will scroll the content inside bottom sheet.
What I have tried
layout.xml
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/design_bottom_sheet"
style="#style/RootLayout"
android:background="#drawable/rounded_shape"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<...Content.../>
</android.core.widget.NestedScrollView>
</FrameLayout>
<androidx.coordinatorlayout.widget.CoordinatorLayout
Bottom Sheet Dialog class
I followed the answer here accepted answer
Result
It only shows half of the screen when opened, and not scroll the bottom sheet to Expanded State when I scroll the contents up like this result.
Expectation
I expected the above code should behave like this expectation
Does any one have the solution for this situation?
Thank you
So after more than a week, I found a solution for this problem,
I override the onCreateDialog method like below
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
// This will disable the behavior of bottom sheet to have a flat corner
//https://github.com/material-components/material-components-android/pull/437#issuecomment-678742683
val dialog = BottomSheetDialog(requireContext(), theme)
dialog.behavior.disableShapeAnimations()
dialog.setOnShowListener { dialogInterface ->
val bottomSheetDialog = dialogInterface as BottomSheetDialog
val parentLayout =
bottomSheetDialog.findViewById<View>(com.google.android.material.R.id.design_bottom_sheet)
parentLayout?.let { it1 ->
val behaviour = BottomSheetBehavior.from(it1)
it1.layoutParams.also {
it.height =
context?.resources?.displayMetrics?.heightPixels?.times(0.9)?.toInt()!!
}
behaviour.peekHeight =
context?.resources?.displayMetrics?.heightPixels?.times(0.6)?.toInt()!!
}
}
return dialog
}
What is happening in this code?
I was NOT use the dialog provider by BottomSheetDialog neither super.onCreateDialog()
Instead I used BottomSheetDialog(context,theme) in order to create my custom bottom sheet theme.
Then, I set listener for dialog, get parent layout and bottom sheet dialog like below. The most important part is dealing with behavior.
After achieved the behavior correctly, you are done. Setting it's state to be expanded as recommended by #Nitish Chaudhary and setting the layout height to the height that you want. That's all I need, also this code below is reusable to me wherever you follow the modal bottom sheet XML layout rule.
Happy coding.

Android Navigation: Keep previous fragment behind dialog. Works only with BottomSheetDialogFragment

I have a video application - a video list and tapping on an item goes to video details. I want video details to be a full screen dialog fragment (to be able to do the motion layout animation from here https://medium.com/vrt-digital-studio/picture-in-picture-video-overlay-with-motionlayout-a9404663b9e7). But the previous dialog is not preserved behind (a blank screen is displayed). Weird enough BottomSheetDialogFragment works but DialogFragment does not.
So the question is - Should a dialog fragment have the previous fragment displayed under it when using jetpack navigation? Why bottom sheet works and dialog not?
Navigation is done using android jetpack navigation:
<action
android:id="#+id/action_videosFragment_to_video_details_nav_graph"
app:destination="#id/video_details_nav_graph"/>
and details nav graph:
<navigation 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:id="#+id/video_details_nav_graph"
app:startDestination="#id/videoDetailsFragment">
<dialog
android:id="#+id/videoDetailsFragment"
android:name="com.myapp.mobile.ui.video.VideoDetailsFragment"
android:label="VideoDetailsFragment"
tools:layout="#layout/fragment_video_details">
</dialog>
</navigation>
Am I missing something? Thanks
After looking more into it, managed to make it work with:
override fun onStart() {
super.onStart()
val dialog: Dialog? = dialog
if (dialog != null) {
val width = ViewGroup.LayoutParams.MATCH_PARENT
val height = ViewGroup.LayoutParams.MATCH_PARENT
dialog.window?.setLayout(width, height)
dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
dialog.window?.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
}
}

Categories

Resources