View pager with tabs layout is out of screen bounds - android

I'm using a tab layout and underneath a view pager to display the content of selected fragment.
On top of the layout there is the tab layout and underneath the view pager. Problem is: the view pager takes the height of the full screen and as a result (since it is constrained to the navigation tabs), its height goes out of the screen like so:
My 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=".activities.MeetActivity">
<com.google.android.material.tabs.TabLayout
android:id="#+id/navigationTabs"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#drawable/navigation_shadow"
app:layout_constraintTop_toTopOf="parent"
app:tabIndicator="#null"
app:tabMinWidth="#dimen/navigation_height"
app:tabRippleColor="#null" />
<!-- // the fragment will be displayed here:-->
<androidx.viewpager.widget.ViewPager
android:id="#+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="#+id/navigationTabs"/>
Is there a way to constrain the view pager to the top of the navigation tabs and force its height to stay within the bounds of the screen? This might look insignificant but it causes widgets in the fragments to appear outside of the screen

the view pager takes the height of the full screen
In ViewPager onMeasure function,wrap_content is calculated as the container size (in this case, ConstaraintLayout).
Try this.
<androidx.viewpager.widget.ViewPager
android:id="#+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="#+id/navigationTabs" />

Here your view pager is taking height of the full screen. Please use
below code to show the view pager below your tab :
<androidx.viewpager.widget.ViewPager
android:id="#+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="#+id/navigationTabs" />

Related

BottomNavigationView does not follow layout heirarchy

I am having a bottom navigation view and I would want to hide it by showing a dummy view on top of it. In the relative layout, I am placing the dummy view on top of the bottom navigation view. But always the bottom navigation view shows on top. Why does the bottom navigation view does not follow layout hierarchy?
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNavigationView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#color/white"
android:theme="#style/BottomBar"
android:visibility="visible"
app:itemTextAppearanceActive="#style/BottomNavigationViewTextStyle"
app:itemTextAppearanceInactive="#style/BottomNavigationViewTextStyle"
app:labelVisibilityMode="labeled"
app:menu="#menu/bottom_navigation_menu" />
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:background="#color/black" />
</RelativeLayout>
I expect the View to be shown on top of the bottom navigation view(So that the bottom navigation view is invisible), but bottom navigation view always shown on top
Based on the following link https://material.io/components/bottom-navigation/android, the bottom navigation view has a default elevation of 8dp. Changing the elevation of dummy layout will fix the issue.

ConstraintLayout from bottom to top

I have layout like this:
<androidx.constraintlayout.widget.ConstraintLayout
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">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#color/colorPrimary"
android:minHeight="300dp"
app:layout_constraintBottom_toTopOf="#+id/recyclerView"
app:layout_constraintHeight_min="300dp"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
FragmentContainerView and RecyclerView have dynamic sizes, and FragmentContainerView should not be less than 300dp and fit all available spase. RecyclerView should be on the bottom and can contains from 1 to 20 items. Current solution works ok only for case RecyclerView contains few items, but for other case it overlaps FragmentContainerView.
Is it possible to align RecyclerView to bottom but restrict max size to have free space = 300dp at the top?
I think you need to do:
Add app:layout_constraintTop_toBottomOf="#id/container" to the RecyclerView
Remove app:layout_constraintBottom_toTopOf="#+id/recyclerView" From the FragmentContainerView
This will make the FragmentContainerView height not restricted to the height of the RecyclerView .. and Make the RecyclerView height limited between the bottom of the FragmentContainerView & the bottom of the parent.
Try adding app:layout_constraintTop_toBottomOf="#id/container" in RecyclerView

Bottomsheet with Viewpager2 on Android

I am developing an app that uses a vertical bottom sheet. To be more specific, it is a LinearLayout with bottomSheetBehavior. This bottom sheet comprises two elements: a view pager that displays images and can be scrolled horizontally, and, below the view pager, a Recycler View whose elements can be scrolled vertically.
The good layout file looks like this:
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="?android:attr/colorBackground"
android:orientation="vertical">
<!-- works with and without frame layout-->
<FrameLayout
android:id="#+id/play_queue_square_frame"
android:layout_width="match_parent"
android:layout_height="350dp">
<androidx.viewpager.widget.ViewPager
android:id="#+id/play_queue_view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/play_queue_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"
app:layoutManager="LinearLayoutManager"
android:background="?android:attr/colorBackground"
tools:listitem="#layout/item_view_song_debug" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
With the above layout everything is working as expected. In particular, the view pager scrolls in horizontal direction, the recycler view scrolls in vertical direction, and dragging either the view pager or the recycler view in horizontal direction closes the bottom sheet.
However, when replacing the view pager by androidx.viewpager2.widget.ViewPager2 yields odd behaviour. Scrolling the view pager in horizontal direction is still possible, but vertical scrolling does no longer work. Any swipes downward simply close the bottom sheet.
Using a NestedScrollView yields better results but still has erroneous behaviour.
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="?android:attr/colorBackground"
android:orientation="vertical">
<FrameLayout
android:id="#+id/play_queue_square_frame"
android:layout_width="match_parent"
android:layout_height="300dp">
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/play_queue_view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/play_queue_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"
app:layoutManager="LinearLayoutManager"
android:background="?android:attr/colorBackground"
tools:listitem="#layout/item_view_song_debug" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
Scrolling in vertical direction is still possible, and also the horizontal scrolling for the view pager. However, dragging the view pager down does no longer close the bottom sheet, whereas a dragging the recycler view down does.
If I add the following code
viewPager.setUserInputEnabled(false)
the view pager does no longer allow horizontal scrolling (as expected). So my question is simply what I have to do in order to allow horizontal scrolling and make sure that a vertical swipe downwards (on the view pager) closes the bottom sheet.
I know that a somewhat similar question has already been asked (in this post)
but as there is no answer so far I take the liberty to ask this question. What confuses me most is that it is working with the old viewpager but not with viewpager2.
Any help is greatly appreciated!

Is it possible to make an ImageView cover the whole screen, if it's contained in a fragment in a ViewPager that doesn't cover the whole screen?

I am using a ViewPager in an activity layout which is a ConstraintLayout. This ViewPager is constrained in order to be displayed below a sibling widget. This ViewPager, so, doesn't cover the whole screen.
However, in the fragments of this ViewPager, there is an ImageView that must be displayed covering the whole screen. This ImageView is unique per fragment of this ViewPager (implying that each ImageView must actually be contained in each ViewPager's fragments).
The problem is: since this ImageView is within the fragments of the ViewPager that doesn't cover the whole screen, then it's impossible to use something like match_parent for this ImageView, since it will match the ViewPager which, obviously, doesn't cover all the screen (since it's shown below a sibling widget).
What could I do to make the ImageView fill the whole screen?
When you show the imageView fragment in view pager you can change your constraints programmatically. Here there is simple example for this
ConstraintLayout: change constraints programmatically
fragment.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">
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/viewPagerImage"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
viewpger_item.xml
<androidx.constraintlayout.widget.ConstraintLayout
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"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/imgPool"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="fitXY"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Applying max height to BottomSheetDialogFragment and apply height change transitions

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).

Categories

Resources