AppBarLayout scrolling awesomeness, PlayQueue layout touches interception, player's controls' margin

- made scrolling in appBarLayout awesome
- PlayQueue layout was intercepting touches while it was in GONE visibility state. Now it's not gonna happen
- removed margin between two lines of player's controls
- when a user leaves the app with two back presses the app will not stop MainPlayer service if popup or background players play
This commit is contained in:
Avently 2020-02-12 22:33:23 +03:00
parent f334a2740f
commit a47e6dd8c5
8 changed files with 69 additions and 102 deletions

View file

@ -23,14 +23,14 @@ public final class FlingBehavior extends AppBarLayout.Behavior {
} }
private boolean allowScroll = true; private boolean allowScroll = true;
private Rect playQueueRect = new Rect(); private Rect globalRect = new Rect();
@Override @Override
public boolean onInterceptTouchEvent(CoordinatorLayout parent, AppBarLayout child, MotionEvent ev) { public boolean onInterceptTouchEvent(CoordinatorLayout parent, AppBarLayout child, MotionEvent ev) {
ViewGroup playQueue = child.findViewById(R.id.playQueue); ViewGroup playQueue = child.findViewById(R.id.playQueuePanel);
if (playQueue != null) { if (playQueue != null) {
playQueue.getGlobalVisibleRect(playQueueRect); boolean visible = playQueue.getGlobalVisibleRect(globalRect);
if (playQueueRect.contains((int) ev.getRawX(), (int) ev.getRawY())) { if (visible && globalRect.contains((int) ev.getRawX(), (int) ev.getRawY())) {
allowScroll = false; allowScroll = false;
return false; return false;
} }

View file

@ -403,8 +403,9 @@ public class VideoDetailFragment
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
if (!activity.isFinishing()) unbind(); // Stop the service when user leaves the app with double back press if video player is selected. Otherwise unbind
else stopService(); if (activity.isFinishing() && player != null && player.videoPlayerSelected()) stopService();
else unbind();
PreferenceManager.getDefaultSharedPreferences(activity) PreferenceManager.getDefaultSharedPreferences(activity)
.unregisterOnSharedPreferenceChangeListener(this); .unregisterOnSharedPreferenceChangeListener(this);

View file

@ -306,6 +306,7 @@ public class VideoPlayerImpl extends VideoPlayer
playerCloseButton.setVisibility(View.GONE); playerCloseButton.setVisibility(View.GONE);
getTopControlsRoot().bringToFront(); getTopControlsRoot().bringToFront();
getBottomControlsRoot().bringToFront(); getBottomControlsRoot().bringToFront();
onQueueClosed();
} else { } else {
fullscreenButton.setVisibility(View.GONE); fullscreenButton.setVisibility(View.GONE);
setupScreenRotationButton(service.isLandscape()); setupScreenRotationButton(service.isLandscape());
@ -678,7 +679,10 @@ public class VideoPlayerImpl extends VideoPlayer
private void onQueueClosed() { private void onQueueClosed() {
animateView(queueLayout, SLIDE_AND_ALPHA, /*visible=*/false, animateView(queueLayout, SLIDE_AND_ALPHA, /*visible=*/false,
DEFAULT_CONTROLS_DURATION); DEFAULT_CONTROLS_DURATION, 0, () -> {
// Even when queueLayout is GONE it receives touch events and ruins normal behavior of the app. This line fixes it
queueLayout.setTranslationY(-queueLayout.getHeight() * 5);
});
queueVisible = false; queueVisible = false;
} }

View file

@ -4,61 +4,46 @@ import android.content.Context;
import android.graphics.Rect; import android.graphics.Rect;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.coordinatorlayout.widget.CoordinatorLayout;
import com.google.android.material.bottomsheet.BottomSheetBehavior; import com.google.android.material.bottomsheet.BottomSheetBehavior;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
public class CustomBottomSheetBehavior extends BottomSheetBehavior { import java.util.Arrays;
import java.util.List;
public class CustomBottomSheetBehavior extends BottomSheetBehavior<FrameLayout> {
public CustomBottomSheetBehavior(Context context, AttributeSet attrs) { public CustomBottomSheetBehavior(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
} }
boolean skippingInterception = false; boolean visible;
Rect globalRect = new Rect();
private boolean skippingInterception = false;
private List<Integer> skipInterceptionOfElements = Arrays.asList(
R.id.detail_content_root_layout, R.id.relatedStreamsLayout, R.id.playQueuePanel, R.id.viewpager);
@Override @Override
public boolean onInterceptTouchEvent(CoordinatorLayout parent, View child, MotionEvent event) { public boolean onInterceptTouchEvent(@NonNull CoordinatorLayout parent, @NonNull FrameLayout child, MotionEvent event) {
// Behavior of globalVisibleRect is different on different APIs. // Drop following when action ends
// For example, on API 19 getGlobalVisibleRect returns a filled rect of a collapsed view while on the latest API
// it returns empty rect in that case. So check visibility with return value too
boolean visible;
Rect rect = new Rect();
// Drop folowing when actions ends
if (event.getAction() == MotionEvent.ACTION_CANCEL || event.getAction() == MotionEvent.ACTION_UP) if (event.getAction() == MotionEvent.ACTION_CANCEL || event.getAction() == MotionEvent.ACTION_UP)
skippingInterception = false; skippingInterception = false;
// Found that user still swipping, continue folowing // Found that user still swiping, continue following
if (skippingInterception) return false; if (skippingInterception) return false;
// Without overriding scrolling will not work in detail_content_root_layout // Without overriding scrolling will not work when user touches these elements
ViewGroup controls = child.findViewById(R.id.detail_content_root_layout); for (Integer element : skipInterceptionOfElements) {
if (controls != null) { ViewGroup viewGroup = child.findViewById(element);
visible = controls.getGlobalVisibleRect(rect); if (viewGroup != null) {
if (rect.contains((int) event.getRawX(), (int) event.getRawY()) && visible) { visible = viewGroup.getGlobalVisibleRect(globalRect);
skippingInterception = true; if (visible && globalRect.contains((int) event.getRawX(), (int) event.getRawY())) {
return false; skippingInterception = true;
} return false;
} }
// Without overriding scrolling will not work on relatedStreamsLayout
ViewGroup relatedStreamsLayout = child.findViewById(R.id.relatedStreamsLayout);
if (relatedStreamsLayout != null) {
visible = relatedStreamsLayout.getGlobalVisibleRect(rect);
if (rect.contains((int) event.getRawX(), (int) event.getRawY()) && visible) {
skippingInterception = true;
return false;
}
}
ViewGroup playQueue = child.findViewById(R.id.playQueue);
if (playQueue != null) {
visible = playQueue.getGlobalVisibleRect(rect);
if (rect.contains((int) event.getRawX(), (int) event.getRawY()) && visible) {
skippingInterception = true;
return false;
} }
} }

View file

@ -157,7 +157,6 @@
android:minHeight="50dp" android:minHeight="50dp"
android:baselineAligned="false" android:baselineAligned="false"
android:gravity="top" android:gravity="top"
android:layout_marginBottom="7dp"
tools:ignore="RtlHardcoded"> tools:ignore="RtlHardcoded">
<ImageButton <ImageButton

View file

@ -22,30 +22,6 @@
android:layout_weight="5" android:layout_weight="5"
android:fitsSystemWindows="true"> android:fitsSystemWindows="true">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:fillViewport="true">
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.google.android.material.tabs.TabLayout
android:id="@+id/tablayout"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_gravity="bottom|center"
app:tabBackground="@drawable/tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"/>
</androidx.viewpager.widget.ViewPager>
</androidx.core.widget.NestedScrollView>
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbarlayout" android:id="@+id/appbarlayout"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -541,6 +517,23 @@
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tablayout"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_gravity="bottom|center"
app:tabBackground="@drawable/tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"/>
</androidx.viewpager.widget.ViewPager>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>
<FrameLayout <FrameLayout

View file

@ -155,7 +155,6 @@
android:minHeight="50dp" android:minHeight="50dp"
android:baselineAligned="false" android:baselineAligned="false"
android:gravity="top" android:gravity="top"
android:layout_marginBottom="7dp"
tools:ignore="RtlHardcoded"> tools:ignore="RtlHardcoded">
<ImageButton <ImageButton

View file

@ -13,37 +13,6 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<!--
You may wonder why this NestedScrollView locates on top of the file. That's because BottomSheetBehavior
can work well only with one element that implements nested scrolling. But we have two:
one NestedScrollView for ViewPager with id = viewpager here
second ViewPager with id = playQueue inside activity_main_player.xml.
By placing this NestedScrollView on top of the file we are getting this ViewPager working -->
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:fillViewport="true">
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.google.android.material.tabs.TabLayout
android:id="@+id/tablayout"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_gravity="bottom|center"
app:tabBackground="@drawable/tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"/>
</androidx.viewpager.widget.ViewPager>
</androidx.core.widget.NestedScrollView>
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbarlayout" android:id="@+id/appbarlayout"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -541,6 +510,23 @@
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tablayout"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_gravity="bottom|center"
app:tabBackground="@drawable/tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"/>
</androidx.viewpager.widget.ViewPager>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>
<RelativeLayout <RelativeLayout