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 Rect playQueueRect = new Rect();
private Rect globalRect = new Rect();
@Override
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) {
playQueue.getGlobalVisibleRect(playQueueRect);
if (playQueueRect.contains((int) ev.getRawX(), (int) ev.getRawY())) {
boolean visible = playQueue.getGlobalVisibleRect(globalRect);
if (visible && globalRect.contains((int) ev.getRawX(), (int) ev.getRawY())) {
allowScroll = false;
return false;
}

View file

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

View file

@ -306,6 +306,7 @@ public class VideoPlayerImpl extends VideoPlayer
playerCloseButton.setVisibility(View.GONE);
getTopControlsRoot().bringToFront();
getBottomControlsRoot().bringToFront();
onQueueClosed();
} else {
fullscreenButton.setVisibility(View.GONE);
setupScreenRotationButton(service.isLandscape());
@ -678,7 +679,10 @@ public class VideoPlayerImpl extends VideoPlayer
private void onQueueClosed() {
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;
}

View file

@ -4,61 +4,46 @@ import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
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) {
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
public boolean onInterceptTouchEvent(CoordinatorLayout parent, View child, MotionEvent event) {
// Behavior of globalVisibleRect is different on different APIs.
// 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
public boolean onInterceptTouchEvent(@NonNull CoordinatorLayout parent, @NonNull FrameLayout child, MotionEvent event) {
// Drop following when action ends
if (event.getAction() == MotionEvent.ACTION_CANCEL || event.getAction() == MotionEvent.ACTION_UP)
skippingInterception = false;
// Found that user still swipping, continue folowing
// Found that user still swiping, continue following
if (skippingInterception) return false;
// Without overriding scrolling will not work in detail_content_root_layout
ViewGroup controls = child.findViewById(R.id.detail_content_root_layout);
if (controls != null) {
visible = controls.getGlobalVisibleRect(rect);
if (rect.contains((int) event.getRawX(), (int) event.getRawY()) && visible) {
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;
// Without overriding scrolling will not work when user touches these elements
for (Integer element : skipInterceptionOfElements) {
ViewGroup viewGroup = child.findViewById(element);
if (viewGroup != null) {
visible = viewGroup.getGlobalVisibleRect(globalRect);
if (visible && globalRect.contains((int) event.getRawX(), (int) event.getRawY())) {
skippingInterception = true;
return false;
}
}
}

View file

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

View file

@ -22,30 +22,6 @@
android:layout_weight="5"
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
android:id="@+id/appbarlayout"
android:layout_width="match_parent"
@ -541,6 +517,23 @@
</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>
<FrameLayout

View file

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

View file

@ -13,37 +13,6 @@
android:layout_width="match_parent"
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
android:id="@+id/appbarlayout"
android:layout_width="match_parent"
@ -541,6 +510,23 @@
</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>
<RelativeLayout