From 5ad7228b4e8650d1fa84bf28db8d810dd0b4aebf Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Mon, 23 Mar 2020 14:05:11 +0100 Subject: Going down the BottomSheetBehavior rabbit hole... BottomSheetBehavior only supports one scrolling child. Add support for a ViewPager. ViewPager.getChildAt sometimes does not match the actual position. Make sure that it keeps all children using setOffscreenPageLimit --- .../bottomsheet/ViewPagerBottomSheetBehavior.java | 75 ++++++++++++++++++++++ .../antennapod/adapter/ChaptersListAdapter.java | 3 - .../antennapod/fragment/AudioPlayerFragment.java | 12 +++- .../fragment/ItemDescriptionFragment.java | 6 +- .../view/LockableBottomSheetBehavior.java | 22 +++---- 5 files changed, 99 insertions(+), 19 deletions(-) create mode 100644 app/src/main/java/com/google/android/material/bottomsheet/ViewPagerBottomSheetBehavior.java (limited to 'app/src/main/java') diff --git a/app/src/main/java/com/google/android/material/bottomsheet/ViewPagerBottomSheetBehavior.java b/app/src/main/java/com/google/android/material/bottomsheet/ViewPagerBottomSheetBehavior.java new file mode 100644 index 000000000..2d211704d --- /dev/null +++ b/app/src/main/java/com/google/android/material/bottomsheet/ViewPagerBottomSheetBehavior.java @@ -0,0 +1,75 @@ +package com.google.android.material.bottomsheet; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.core.view.ViewCompat; +import androidx.viewpager.widget.ViewPager; + +import java.lang.ref.WeakReference; + +/** + * Override {@link #findScrollingChild(View)} to support {@link ViewPager}'s nested scrolling. + * By the way, In order to override package level method and field. + * This class put in the same package path where {@link BottomSheetBehavior} located. + * Source: https://medium.com/@hanru.yeh/funny-solution-that-makes-bottomsheetdialog-support-viewpager-with-nestedscrollingchilds-bfdca72235c3 + */ +public class ViewPagerBottomSheetBehavior extends BottomSheetBehavior { + + public ViewPagerBottomSheetBehavior() { + super(); + } + + public ViewPagerBottomSheetBehavior(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + View findScrollingChild(View view) { + if (ViewCompat.isNestedScrollingEnabled(view)) { + return view; + } + + if (view instanceof ViewPager) { + ViewPager viewPager = (ViewPager) view; + View currentViewPagerChild = viewPager.getChildAt(viewPager.getCurrentItem()); + return findScrollingChild(currentViewPagerChild); + } else if (view instanceof ViewGroup) { + ViewGroup group = (ViewGroup) view; + for (int i = 0, count = group.getChildCount(); i < count; i++) { + View scrollingChild = findScrollingChild(group.getChildAt(i)); + if (scrollingChild != null) { + return scrollingChild; + } + } + } + return null; + } + + public void updateScrollingChild() { + final View scrollingChild = findScrollingChild(viewRef.get()); + nestedScrollingChildRef = new WeakReference<>(scrollingChild); + } + + /** + * A utility function to get the {@link ViewPagerBottomSheetBehavior} associated with the {@code view}. + * + * @param view The {@link View} with {@link ViewPagerBottomSheetBehavior}. + * @return The {@link ViewPagerBottomSheetBehavior} associated with the {@code view}. + */ + @SuppressWarnings("unchecked") + public static ViewPagerBottomSheetBehavior from(V view) { + ViewGroup.LayoutParams params = view.getLayoutParams(); + if (!(params instanceof CoordinatorLayout.LayoutParams)) { + throw new IllegalArgumentException("The view is not a child of CoordinatorLayout"); + } + CoordinatorLayout.Behavior behavior = ((CoordinatorLayout.LayoutParams) params).getBehavior(); + if (!(behavior instanceof ViewPagerBottomSheetBehavior)) { + throw new IllegalArgumentException( + "The view is not associated with ViewPagerBottomSheetBehavior"); + } + return (ViewPagerBottomSheetBehavior) behavior; + } +} \ No newline at end of file diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java index 8b0aa537e..cb72a9150 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java @@ -2,7 +2,6 @@ package de.danoeh.antennapod.adapter; import android.content.Context; import android.text.TextUtils; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -116,7 +115,6 @@ public class ChaptersListAdapter extends RecyclerView.Adapter ((MainActivity) getActivity()).getBottomSheet().updateScrollingChild()); + } + }); pageIndicator = root.findViewById(R.id.page_indicator); pageIndicator.setViewPager(pager); pageIndicator.setOnClickListener(v -> @@ -468,7 +476,7 @@ public class AudioPlayerFragment extends Fragment implements return false; } - private static class AudioPlayerPagerAdapter extends FragmentStatePagerAdapter { + private static class AudioPlayerPagerAdapter extends FragmentPagerAdapter { private static final String TAG = "AudioPlayerPagerAdapter"; public AudioPlayerPagerAdapter(FragmentManager fm) { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java index 256615199..58cc9290c 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java @@ -10,6 +10,7 @@ import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; +import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.util.playback.PlaybackController; import de.danoeh.antennapod.core.util.playback.Timeline; import de.danoeh.antennapod.view.ShownotesWebView; @@ -35,7 +36,8 @@ public class ItemDescriptionFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Log.d(TAG, "Creating view"); - webvDescription = new ShownotesWebView(getActivity().getApplicationContext()); + View root = inflater.inflate(R.layout.item_description_fragment, container, false); + webvDescription = root.findViewById(R.id.webview); webvDescription.setTimecodeSelectedListener(time -> { if (controller != null) { controller.seekTo(time); @@ -46,7 +48,7 @@ public class ItemDescriptionFragment extends Fragment { webvDescription.postDelayed(ItemDescriptionFragment.this::restoreFromPreference, 50); }); registerForContextMenu(webvDescription); - return webvDescription; + return root; } @Override diff --git a/app/src/main/java/de/danoeh/antennapod/view/LockableBottomSheetBehavior.java b/app/src/main/java/de/danoeh/antennapod/view/LockableBottomSheetBehavior.java index f4c073fc6..8e8d98fc9 100644 --- a/app/src/main/java/de/danoeh/antennapod/view/LockableBottomSheetBehavior.java +++ b/app/src/main/java/de/danoeh/antennapod/view/LockableBottomSheetBehavior.java @@ -5,14 +5,13 @@ import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import androidx.coordinatorlayout.widget.CoordinatorLayout; -import com.google.android.material.bottomsheet.BottomSheetBehavior; +import com.google.android.material.bottomsheet.ViewPagerBottomSheetBehavior; /** * Based on https://stackoverflow.com/a/40798214 */ -public class LockableBottomSheetBehavior extends BottomSheetBehavior { - - private boolean mLocked = false; +public class LockableBottomSheetBehavior extends ViewPagerBottomSheetBehavior { + private boolean isLocked = false; public LockableBottomSheetBehavior() {} @@ -21,14 +20,14 @@ public class LockableBottomSheetBehavior extends BottomSheetBeha } public void setLocked(boolean locked) { - mLocked = locked; + isLocked = locked; } @Override public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) { boolean handled = false; - if (!mLocked) { + if (!isLocked) { handled = super.onInterceptTouchEvent(parent, child, event); } @@ -39,7 +38,7 @@ public class LockableBottomSheetBehavior extends BottomSheetBeha public boolean onTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) { boolean handled = false; - if (!mLocked) { + if (!isLocked) { handled = super.onTouchEvent(parent, child, event); } @@ -51,7 +50,7 @@ public class LockableBottomSheetBehavior extends BottomSheetBeha View target, int nestedScrollAxes) { boolean handled = false; - if (!mLocked) { + if (!isLocked) { handled = super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes); } @@ -61,14 +60,14 @@ public class LockableBottomSheetBehavior extends BottomSheetBeha @Override public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dx, int dy, int[] consumed) { - if (!mLocked) { + if (!isLocked) { super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed); } } @Override public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target) { - if (!mLocked) { + if (!isLocked) { super.onStopNestedScroll(coordinatorLayout, child, target); } } @@ -78,11 +77,10 @@ public class LockableBottomSheetBehavior extends BottomSheetBeha float velocityX, float velocityY) { boolean handled = false; - if (!mLocked) { + if (!isLocked) { handled = super.onNestedPreFling(coordinatorLayout, child, target, velocityX, velocityY); } return handled; - } } -- cgit v1.2.3