I have a a persistent bottom sheet behavior in my main activity. The bottom sheet has a container for a fragment with a ViewPager2
. The problem is that the ViewPager2
prevents the bottom sheet from vertically scrolling.
I recreated the issue in the a sample app. As you can see from this gif right here, the vertical scrolling doesn't work if it's inside the ViewPager2
. Only when I drag all the way down outside the ViewPager2
, does it start ducking the bottom sheet. This makes scrolling awkward.
I tried the solution described here but it didn't change anything. The activity's root view is a CoordinatorLayout
and the fragment's root view is a LinearLayout
with a ConstraintLayout
around the ViewPager2
.
Here's the main activity layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center">
<Button
android:id="@+id/expand_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Expand Bottom Sheet" />
</LinearLayout>
<FrameLayout
android:id="@+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true"
android:focusableInTouchMode="true" />
</FrameLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Here's the fragment inside the bottom sheet's layout:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/purple_500">
<TextView
android:id="@+id/sheet_textview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:gravity="center_horizontal"
android:text="This is the sheet fragment"
android:textSize="24sp"
android:textAlignment="center"
android:textColor="@color/white" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="325dp"
android:layout_marginTop="75dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center_horizontal"
android:text="Outside viewpager"
android:textSize="24sp"
android:textAlignment="center"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/view_pager"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
Here's the MainActivity
:
package com.example.myapplication;
import android.os.Bundle;
import android.widget.Button;
import android.widget.FrameLayout;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomSheetBehavior<FrameLayout> bottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.bottom_sheet));
bottomSheetBehavior.setPeekHeight(200);
bottomSheetBehavior.setHideable(true);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
Button expandButton = findViewById(R.id.expand_button);
expandButton.setOnClickListener(view -> bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED));
Fragment sheetFragment = new SheetFragment();
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, sheetFragment).commit();
}
}
And here's the SheetFragment
:
package com.example.myapplication;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.widget.ViewPager2;
public class SheetFragment extends Fragment {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View contentView = inflater.inflate(R.layout.fragment_sheet, container, false);
ViewPager2 viewPager = contentView.findViewById(R.id.view_pager);
ViewPagerAdapter adapter = new ViewPagerAdapter();
viewPager.setAdapter(adapter);
return contentView;
}
public class ViewPagerAdapter extends RecyclerView.Adapter<ViewPagerHolder> {
@NonNull
@Override
public ViewPagerHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = getLayoutInflater().inflate(R.layout.pager_item, parent, false);
return new ViewPagerHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull ViewPagerHolder holder, int position) {
holder.bind(position);
}
@Override
public int getItemCount() {
return 5;
}
}
private class ViewPagerHolder extends RecyclerView.ViewHolder {
public ViewPagerHolder(@NonNull View itemView) {
super(itemView);
}
public void bind(int number) {
TextView textView = itemView.findViewById(R.id.pager_textview);
textView.setText(String.format("Inside ViewPager\nPage #%d", number));
}
}
}