In android, the Bottom Sheet we use for development requires a peek height to be specified which decides the height of the bottom sheet visible initially to the user. I want this to be related to another view in my Layout ( in this case I want the layout to be matched with the coordinator layout). Actually, I want the view to be like of MyAirtel / Paytm App which has the bottom sheet adjusted according to screen height and width.
Here is the coordinator layout code: -
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="#id/button_github_emoji"
app:layout_constraintBottom_toBottomOf="parent">
<FrameLayout
android:id="#+id/home_screen_bottom_sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/home_screen_bottom_sheet_color"
app:behavior_hideable="false"
app:behavior_peekHeight="600dp"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
<androidx.fragment.app.FragmentContainerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.example.daggerfirst.fragments.HomeFragment"
tools:layout="#layout/fragment_home" />
</FrameLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
The coordinator layout is stretched in its parent.
Just remove the app:behavior_peekHeight="600dp" and it will use the default height for the provided content. If the content covers the entire screen, then the peek height will be 50% of the screen height
Related
I have a layout activity in my project in which I am using a constraint layout and basically only 3 view, first is custom toolbar second a Recycler View and last one is a fragment view. I constrained recycler view to top toolbar and top of fragment view but I goes below fragment and even under screen.
This is my layout code.
<?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:theme="#style/Theme.Music.Font">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="#+id/header_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/bold"
android:text="#string/app_name"
android:textSize="26sp" />
<androidx.appcompat.widget.SearchView
android:id="#+id/searchView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
app:searchIcon="#drawable/search_icon" />
</androidx.appcompat.widget.Toolbar>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbarThumbVertical="#drawable/scroll_bar"
android:scrollbars="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/toolbar" />
<androidx.fragment.app.FragmentContainerView
android:id="#+id/nowPlaying"
android:name="com.example.music.NowPlaying"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:layout="#layout/fragment_now_playing" />
</androidx.constraintlayout.widget.ConstraintLayout>
And when I constrained with fragment also it goes on top overriding toolbar.
As shown in picture.
When you use wrap_content for the height or width, you're saying the view should expand to be as large as necessary to "display" the content. "Display" in air quotes because if there's a lot of content, parts of the view might end up off the screen.
Your constraints don't limit the size here, just the positioning. If you constrain one edge to something, you'll pin it, and it will expand off the screen at the other end. If you constrain opposite edges, then you're basically centering it around those constraints.
If you want to match those constraints, you need to set the height to 0dp. That way your constrained edges will actually be pinned where you want them, and that makes the view a certain height. It fits the space between its constrained edges.
Looking at your layout, I'm guessing the "now playing" part at the bottom is your FragmentContainerView. That's set to wrap_content but its contents seem to be a fixed size, so that's fine - exactly what you want! Same goes for the toolbar - it's wrap_content, but its contents are a fixed size.
So your RecyclerView also needs its bottom to be constrained to the top of nowPlaying, and it needs a layout_height of 0dp. That way, it's constrained to the space between the toolbar and the now playing bit, and its size fills that area. The other two take up as much space as they need, and the RecyclerView fills what's left - which is what you want, right?
Generally this is how it works for anything that scrolls, like a RecyclerView or ScrollView - the view in the layout is a window into the scrolling content, so the actual size of the view (layout_height and layout_width) controls the size of that window. The content just scrolls up and down behind it. If that window is the same size as the content, wrap_content, then the whole thing is visible (but possibly off the screen) and there's nothing to scroll! So for scrolling stuff, you always want to limit the size of the view.
I am using a ConstraintLayout as an overlay. It should be as wide and as tall as its parent container. However, for some strange reason it does not fill its parent vertically (but does horizontally). Here is the relevant XML:
<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"
tools:context=".ui.home.HomeFragment">
<androidx.constraintlayout.widget.ConstraintLayout <-- This is the overlay
android:id="#+id/overlay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#80000000"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
With the above code the overlay is not visible either (its height is 0dp). When I place a TextView inside, it expands to fit the TextView. In short, it is behaving as if its height was set to wrap_content.
How do I force it to fill its container while leaving it empty?
The problem is most likely your size specifications. From the documentation for ConstraintLayout:
Important: MATCH_PARENT is not recommended for widgets contained in a ConstraintLayout. Similar behavior can be defined by using MATCH_CONSTRAINT with the corresponding left/right or top/bottom constraints being set to "parent".
There really should be a lint rule for this or ConstraintLayout should reject match_parent.
I have a BottomSheetDialogFragment that holds multiple Fragments of different sizes as a content in the FrameLayout.
The max height of the BottomSheetDialogFragment container needs to set at 60% of the total height of the current window viewport.
In addition, I also need to apply transitions when the content displayed within the BottomSheetDialogFragment changes its height such that the height changes smoothens out while rendering.
In other words, the height of the container should stay fixed no matter whatever the content displayed be in BottomSheetDialogFragment. And once the height of the content exceeds the height of the specified height, the content becomes scrollable. Said that, there can be content whose height is less than the max height and hence the transition should be applied to layout height changes.
Here's a layout hierarchy that matches what I have:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="wrap_content"
android:animateLayoutChanges="true"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="#dimen/toolbar_short_height" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="#id/button_container"
app:layout_constraintTop_toTopOf="parent" />
<!-- This layout always sticks to the bottom of the BottomSheet when opened -->
<RelativeLayout
android:id="#+id/button_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
PS: The view hierarchy still can be simplified but I am trying to use BottomSheetDialogFragment which can be used without specifying BottomSheetBehavior and so it's intended to avoid using CoordinatorLayout.
As per https://material.io/develop/android/components/bottom-sheet-behavior/
Using BottomSheetDialogFragment provides a similar UI and interactions as BottomSheetBehavior, however BottomSheetDialogFragment does not require CoordinatorLayout and creates a modal bottom sheet (essentially a dialog).
I wish I had an example to show if it seems confusing, but basically what I want to do is show a bottom toolbar with a Right navigator button (e.g. go to next page) always anchored to bottom of the screen, but if the content on the page (middle section) grows, the toolbar will push down so that you have to scroll to get to it. I know it seems strange, but this is the requirements. What would be the best approach for this?
You can achieve this by combining a ScrollView using android:fillViewport="true" and a vertical LinearLayout that has a Space with android:layout_weight="1" between your content and your navigation bar.
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#ccc"/>
<Space
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<View
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="#eee"/>
</LinearLayout>
</ScrollView>
That first view is a placeholder for whatever content you want to display, and the second is a placeholder for your navigation bar. You can see that when the first view is short (200dp tall), you get the "content" at the top and the navigation bar at the bottom:
This works because the fillViewport attribute will "stretch" the child LinearLayout to fill the screen, at which point there is "extra" space and the layout_weight attribute on the Space element will consume all that space. (Note that, despite being a ScrollView, you can't actually scroll anything in this state, since the view is stretched to be the exact size of the screen.)
However, when the "content" is tall enough to fill the screen, the fillViewport attribute will have no effect, the LinearLayout won't be stretched, and there won't be any extra space to consume. So, once you scroll to the bottom, your content will fill right up to the edge of the navigation bar:
(Scrolled to the top on the left, and scrolled to the bottom on the right.)
I have a CoordinatorLayout with a RelativeLayout as a bottom sheet with com.android.support:design:25.1.0
<RelativeLayout
android:id="#+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="true"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
android:layout_marginTop="56dp"
app:behavior_peekHeight="100dp"
>
The peekHeight is set to 100dp, when I'm opening the activity the bottomsheet is showing but with less than 100dp height. When expanding and collapsing it with the finger, the height of the bottom sheet is 100dp.
Why at the first opening the activity the peek height is not correct? Is it the normal behavior? I would like to have always the same height.