Reputation: 16798
I have the following bottom sheet dialog code:
abstract class BaseMvpBottomSheetFragment : BottomSheetDialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog
if (isFullscreen) { // true
dialog.setOnShowListener {
val bottomSheetDialog = it as BottomSheetDialog
bottomSheetDialog
.findViewById<FrameLayout>(com.google.android.material.R.id.design_bottom_sheet)
?.let { bottomSheetFl ->
from(bottomSheetFl).apply {
state = STATE_EXPANDED // This code is called, I've checked it with debugger
}
}
}
}
return dialog
}
And the following layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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/containerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorTransparent"
tools:background="#000000">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_bottom_sheet">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/headerLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/closeIv"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_close"
tools:ignore="ContentDescription" />
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/searchEt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:drawableEnd="@drawable/ic_search_clear"
android:imeOptions="actionSearch"
android:inputType="text"
android:lines="1"
android:maxLines="1"
app:layout_constraintTop_toBottomOf="@id/closeIv" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/modelsRv"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/headerLayout"
tools:listitem="@layout/view_item_model" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
I want dialog to be initially expanded (and layout to take all vertical space), but when RecyclerView
is empty, it takes no space at all:
I've tried other solutions on SO, but they did not work for me.
Upvotes: 1
Views: 3247
Reputation: 22832
As the height of the RecyclerView
is defined MATCH_CONSTRAINTS
, I think there is no way to do what you want except set its height explicitly. So, to achieve the desired height we can subtract the height of headerLayout
and the device status bar from the height of the screen.
Also, I have changed your code a bit:
setupDialog
and delegate the decision of being a full-screen bottom sheet, to the child class. setupDialog
, so we can remove the root FrameLayout
to achieve a smaller view hierarchy in the xml
file.
BaseMvpBottomSheetFragment.kt
import android.app.Dialog
import android.content.Context
import android.view.View
import androidx.annotation.LayoutRes
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
abstract class BaseMvpBottomSheetFragment(
@LayoutRes private val layoutResId: Int
) : BottomSheetDialogFragment() {
protected val activityContext: Context by lazy { activity!!.applicationContext }
protected lateinit var rootView: View
override fun setupDialog(dialog: Dialog, style: Int) {
super.setupDialog(dialog, style)
rootView = View.inflate(activityContext, layoutResId, null)
dialog.setContentView(rootView)
onInitViews(rootView)
}
abstract fun onInitViews(rootView: View)
}
FullScreenBottomSheetDialogFragment.kt
import android.app.Dialog
import android.content.Context
import android.graphics.Point
import android.view.Display
import android.view.View
import android.view.WindowManager
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.content.ContextCompat
import com.google.android.material.bottomsheet.BottomSheetBehavior
import kotlinx.android.synthetic.main.full_screen_bottom_sheet.view.*
class FullScreenBottomSheetDialogFragment : BaseMvpBottomSheetFragment(R.layout.full_screen_bottom_sheet) {
private var isFullscreen = true
override fun setupDialog(dialog: Dialog, style: Int) {
super.setupDialog(dialog, style)
val parentView = rootView.parent as View
parentView.setBackgroundColor(ContextCompat.getColor(activityContext, R.color.colorTransparent))
val params = parentView.layoutParams as CoordinatorLayout.LayoutParams
val behavior = params.behavior
if (behavior is BottomSheetBehavior<*>) {
behavior.state = BottomSheetBehavior.STATE_EXPANDED
if (isFullscreen) {
behavior.peekHeight = screenSize(activityContext).y
}
}
}
override fun onInitViews(rootView: View) {
with(rootView) {
if (isFullscreen) {
headerLayout.post {
modelsRv.layoutParams.height =
screenSize(activityContext).y -
headerLayout.measuredHeight - // height of the header view
statusBarHeight(activityContext) // height of the status bar
modelsRv.requestLayout()
}
}
// do other initializations...
}
}
private fun screenSize(context: Context): Point {
val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
val display: Display? = windowManager.defaultDisplay
val point = Point()
display?.getSize(point)
return point
}
private fun statusBarHeight(context: Context): Int {
var result = 0
val resourceId = context.resources.getIdentifier("status_bar_height", "dimen", "android")
if (resourceId > 0) result = context.resources.getDimensionPixelSize(resourceId)
return result
}
}
full_screen_bottom_sheet.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_bottom_sheet">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/headerLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/closeIv"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_close"
tools:ignore="ContentDescription" />
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/searchEt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:drawableEnd="@drawable/ic_search_clear"
android:imeOptions="actionSearch"
android:inputType="text"
android:lines="1"
android:maxLines="1"
app:layout_constraintTop_toBottomOf="@id/closeIv" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/modelsRv"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/headerLayout"
tools:listitem="@layout/view_item_model" />
</androidx.constraintlayout.widget.ConstraintLayout>
Upvotes: 2