2019-10-04 14:59:08 +02:00
|
|
|
package com.google.android.material.appbar;
|
2018-10-16 20:53:02 +02:00
|
|
|
|
|
|
|
import android.content.Context;
|
2019-12-31 17:06:39 +01:00
|
|
|
import android.graphics.Rect;
|
2018-10-16 20:53:02 +02:00
|
|
|
import android.util.AttributeSet;
|
2019-10-02 02:59:20 +02:00
|
|
|
import android.view.MotionEvent;
|
2019-12-31 17:06:39 +01:00
|
|
|
import android.view.View;
|
|
|
|
import android.view.ViewGroup;
|
2019-10-02 02:59:20 +02:00
|
|
|
import android.widget.OverScroller;
|
2018-10-16 20:53:02 +02:00
|
|
|
|
2019-10-04 14:59:08 +02:00
|
|
|
import androidx.annotation.Nullable;
|
|
|
|
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
2019-12-31 17:06:39 +01:00
|
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
import org.schabi.newpipe.R;
|
2019-10-04 14:59:08 +02:00
|
|
|
|
2019-10-02 02:59:20 +02:00
|
|
|
import java.lang.reflect.Field;
|
2018-10-16 20:53:02 +02:00
|
|
|
|
2019-10-02 02:59:20 +02:00
|
|
|
// check this https://stackoverflow.com/questions/56849221/recyclerview-fling-causes-laggy-while-appbarlayout-is-scrolling/57997489#57997489
|
|
|
|
public final class FlingBehavior extends AppBarLayout.Behavior {
|
2018-10-16 20:53:02 +02:00
|
|
|
|
|
|
|
public FlingBehavior(Context context, AttributeSet attrs) {
|
|
|
|
super(context, attrs);
|
|
|
|
}
|
|
|
|
|
2019-12-31 17:06:39 +01:00
|
|
|
private boolean allowScroll = true;
|
2020-02-12 20:33:23 +01:00
|
|
|
private Rect globalRect = new Rect();
|
2019-12-31 17:06:39 +01:00
|
|
|
|
2018-10-16 20:53:02 +02:00
|
|
|
@Override
|
2019-10-02 02:59:20 +02:00
|
|
|
public boolean onInterceptTouchEvent(CoordinatorLayout parent, AppBarLayout child, MotionEvent ev) {
|
2020-02-12 20:33:23 +01:00
|
|
|
ViewGroup playQueue = child.findViewById(R.id.playQueuePanel);
|
2019-12-31 17:06:39 +01:00
|
|
|
if (playQueue != null) {
|
2020-02-12 20:33:23 +01:00
|
|
|
boolean visible = playQueue.getGlobalVisibleRect(globalRect);
|
|
|
|
if (visible && globalRect.contains((int) ev.getRawX(), (int) ev.getRawY())) {
|
2019-12-31 17:06:39 +01:00
|
|
|
allowScroll = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
allowScroll = true;
|
|
|
|
|
|
|
|
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
|
|
|
// remove reference to old nested scrolling child
|
|
|
|
resetNestedScrollingChild();
|
|
|
|
// Stop fling when your finger touches the screen
|
|
|
|
stopAppBarLayoutFling();
|
2018-10-16 20:53:02 +02:00
|
|
|
}
|
2019-10-02 02:59:20 +02:00
|
|
|
return super.onInterceptTouchEvent(parent, child, ev);
|
2018-10-16 20:53:02 +02:00
|
|
|
}
|
|
|
|
|
2019-12-31 17:06:39 +01:00
|
|
|
@Override
|
|
|
|
public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes, int type) {
|
|
|
|
return allowScroll && super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes, type);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onNestedFling(@NotNull CoordinatorLayout coordinatorLayout, @NotNull AppBarLayout child, @NotNull View target, float velocityX, float velocityY, boolean consumed) {
|
|
|
|
return allowScroll && super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);
|
|
|
|
}
|
|
|
|
|
2019-10-02 02:59:20 +02:00
|
|
|
@Nullable
|
|
|
|
private OverScroller getScrollerField() {
|
|
|
|
try {
|
|
|
|
Class<?> headerBehaviorType = this.getClass().getSuperclass().getSuperclass().getSuperclass();
|
|
|
|
if (headerBehaviorType != null) {
|
|
|
|
Field field = headerBehaviorType.getDeclaredField("scroller");
|
|
|
|
field.setAccessible(true);
|
|
|
|
return ((OverScroller) field.get(this));
|
2018-10-16 20:53:02 +02:00
|
|
|
}
|
2019-10-02 02:59:20 +02:00
|
|
|
} catch (NoSuchFieldException | IllegalAccessException e) {
|
|
|
|
// ?
|
2018-10-16 20:53:02 +02:00
|
|
|
}
|
2019-10-02 02:59:20 +02:00
|
|
|
return null;
|
2018-10-16 20:53:02 +02:00
|
|
|
}
|
|
|
|
|
2019-10-02 02:59:20 +02:00
|
|
|
@Nullable
|
|
|
|
private Field getLastNestedScrollingChildRefField() {
|
|
|
|
try {
|
|
|
|
Class<?> headerBehaviorType = this.getClass().getSuperclass().getSuperclass();
|
|
|
|
if (headerBehaviorType != null) {
|
|
|
|
Field field = headerBehaviorType.getDeclaredField("lastNestedScrollingChildRef");
|
|
|
|
field.setAccessible(true);
|
|
|
|
return field;
|
|
|
|
}
|
|
|
|
} catch (NoSuchFieldException e) {
|
|
|
|
// ?
|
2018-10-16 20:53:02 +02:00
|
|
|
}
|
2019-10-02 02:59:20 +02:00
|
|
|
return null;
|
2018-10-16 20:53:02 +02:00
|
|
|
}
|
|
|
|
|
2019-10-02 02:59:20 +02:00
|
|
|
private void resetNestedScrollingChild(){
|
|
|
|
Field field = getLastNestedScrollingChildRefField();
|
|
|
|
if(field != null){
|
|
|
|
try {
|
|
|
|
Object value = field.get(this);
|
|
|
|
if(value != null) field.set(this, null);
|
|
|
|
} catch (IllegalAccessException e) {
|
|
|
|
// ?
|
2018-10-16 20:53:02 +02:00
|
|
|
}
|
|
|
|
}
|
2019-10-02 02:59:20 +02:00
|
|
|
}
|
2018-10-16 20:53:02 +02:00
|
|
|
|
2019-10-02 02:59:20 +02:00
|
|
|
private void stopAppBarLayoutFling() {
|
|
|
|
OverScroller scroller = getScrollerField();
|
|
|
|
if (scroller != null) scroller.forceFinished(true);
|
2018-10-16 20:53:02 +02:00
|
|
|
}
|
2019-10-02 02:59:20 +02:00
|
|
|
|
2018-10-16 20:53:02 +02:00
|
|
|
}
|