mirror of https://github.com/NekoX-Dev/NekoX.git
193 lines
8.1 KiB
Java
193 lines
8.1 KiB
Java
|
package org.telegram.ui;
|
||
|
|
||
|
import android.animation.Animator;
|
||
|
import android.animation.AnimatorListenerAdapter;
|
||
|
import android.animation.ValueAnimator;
|
||
|
import android.graphics.Insets;
|
||
|
import android.os.Build;
|
||
|
import android.os.CancellationSignal;
|
||
|
import android.util.Log;
|
||
|
import android.view.MotionEvent;
|
||
|
import android.view.VelocityTracker;
|
||
|
import android.view.View;
|
||
|
import android.view.WindowInsetsAnimationControlListener;
|
||
|
import android.view.WindowInsetsAnimationController;
|
||
|
import android.view.animation.LinearInterpolator;
|
||
|
|
||
|
import androidx.annotation.NonNull;
|
||
|
import androidx.annotation.Nullable;
|
||
|
import androidx.core.math.MathUtils;
|
||
|
import androidx.core.view.WindowInsetsCompat;
|
||
|
import androidx.recyclerview.widget.GridLayoutManagerFixed;
|
||
|
import androidx.recyclerview.widget.RecyclerView;
|
||
|
|
||
|
import org.telegram.messenger.AndroidUtilities;
|
||
|
import org.telegram.ui.ActionBar.AdjustPanLayoutHelper;
|
||
|
import org.telegram.ui.Components.ChatActivityEnterView;
|
||
|
import org.telegram.ui.Components.CubicBezierInterpolator;
|
||
|
import org.telegram.ui.Components.RecyclerListView;
|
||
|
|
||
|
public class KeyboardHideHelper {
|
||
|
|
||
|
public static boolean ENABLED = false;
|
||
|
|
||
|
public KeyboardHideHelper() {
|
||
|
|
||
|
}
|
||
|
|
||
|
private View view, enterView;
|
||
|
private AdjustPanLayoutHelper panLayoutHelper;
|
||
|
private WindowInsetsAnimationController insetsController;
|
||
|
private boolean isKeyboard = false;
|
||
|
private boolean movingKeyboard = false, exactlyMovingKeyboard = false;
|
||
|
private boolean endingMovingKeyboard = false;
|
||
|
private boolean startedOutsideView = false;
|
||
|
private boolean startedAtBottom = false;
|
||
|
private VelocityTracker tracker;
|
||
|
private float rawT, lastT, lastDifferentT, t;
|
||
|
private float fromY;
|
||
|
private int keyboardSize, bottomNavBarSize;
|
||
|
|
||
|
public boolean onTouch(AdjustPanLayoutHelper panLayoutHelper, View view, RecyclerListView listView, ChatActivityEnterView enterView, ChatActivity ca, MotionEvent ev) {
|
||
|
if (!ENABLED) {
|
||
|
return false;
|
||
|
}
|
||
|
this.panLayoutHelper = panLayoutHelper;
|
||
|
this.view = view;
|
||
|
this.enterView = enterView;
|
||
|
|
||
|
if (view == null || enterView == null) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||
|
boolean isKeyboardVisible = view.getRootWindowInsets().getInsets(WindowInsetsCompat.Type.ime()).bottom > 0;
|
||
|
if (!movingKeyboard && !isKeyboardVisible && !endingMovingKeyboard /* && !enterView.isPopupShowing()*/) {
|
||
|
return false;
|
||
|
}
|
||
|
boolean insideEnterView = ev.getY() >= enterView.getTop();
|
||
|
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
|
||
|
startedOutsideView = !insideEnterView;
|
||
|
startedAtBottom = !listView.canScrollVertically(1);
|
||
|
}
|
||
|
if (!movingKeyboard && insideEnterView && startedOutsideView && ev.getAction() == MotionEvent.ACTION_MOVE) {
|
||
|
movingKeyboard = true;
|
||
|
isKeyboard = !enterView.isPopupShowing();
|
||
|
keyboardSize = (
|
||
|
isKeyboard ?
|
||
|
view.getRootWindowInsets().getInsets(WindowInsetsCompat.Type.ime()).bottom :
|
||
|
enterView.getEmojiPadding()
|
||
|
);
|
||
|
bottomNavBarSize = view.getRootWindowInsets().getInsets(WindowInsetsCompat.Type.navigationBars()).bottom;
|
||
|
view.getWindowInsetsController().controlWindowInsetsAnimation(
|
||
|
WindowInsetsCompat.Type.ime(),
|
||
|
-1,
|
||
|
new LinearInterpolator(),
|
||
|
new CancellationSignal(),
|
||
|
new WindowInsetsAnimationControlListener() {
|
||
|
@Override
|
||
|
public void onReady(@NonNull WindowInsetsAnimationController windowInsetsAnimationController, int i) {
|
||
|
insetsController = windowInsetsAnimationController;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void onFinished(@NonNull WindowInsetsAnimationController windowInsetsAnimationController) {
|
||
|
insetsController = null;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void onCancelled(@Nullable WindowInsetsAnimationController windowInsetsAnimationController) {
|
||
|
insetsController = null;
|
||
|
}
|
||
|
}
|
||
|
);
|
||
|
fromY = ev.getRawY();
|
||
|
exactlyMovingKeyboard = false;
|
||
|
panLayoutHelper.setEnabled(false);
|
||
|
update(0, false);
|
||
|
listView.stopScroll();
|
||
|
t = rawT = lastT = lastDifferentT = 0;
|
||
|
panLayoutHelper.OnTransitionStart(true, view.getHeight());
|
||
|
if (tracker == null) {
|
||
|
tracker = VelocityTracker.obtain();
|
||
|
}
|
||
|
tracker.clear();
|
||
|
}
|
||
|
|
||
|
if (movingKeyboard) {
|
||
|
tracker.addMovement(ev);
|
||
|
t = MathUtils.clamp(rawT = (ev.getRawY() - fromY) / keyboardSize, 0, 1);
|
||
|
if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) {
|
||
|
movingKeyboard = false;
|
||
|
exactlyMovingKeyboard = false;
|
||
|
endingMovingKeyboard = true;
|
||
|
tracker.computeCurrentVelocity(1000);
|
||
|
final boolean end = t > .15f && t >= lastDifferentT || t > .8f;
|
||
|
final float endT = end ? 1 : 0;
|
||
|
ValueAnimator va = ValueAnimator.ofFloat(t, endT);
|
||
|
va.addUpdateListener(a -> {
|
||
|
update(t = (float) a.getAnimatedValue(), true);
|
||
|
});
|
||
|
va.addListener(new AnimatorListenerAdapter() {
|
||
|
@Override
|
||
|
public void onAnimationEnd(Animator animation) {
|
||
|
if (insetsController != null && isKeyboard) {
|
||
|
insetsController.finish(!end);
|
||
|
}
|
||
|
update(1, false);
|
||
|
rawT = endT;
|
||
|
panLayoutHelper.OnTransitionEnd();
|
||
|
view.post(() -> {
|
||
|
panLayoutHelper.setEnabled(true);
|
||
|
endingMovingKeyboard = false;
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
va.setInterpolator(CubicBezierInterpolator.EASE_OUT);
|
||
|
va.setDuration(200);
|
||
|
va.start();
|
||
|
if (end && startedAtBottom && ca != null) {
|
||
|
ca.scrollToLastMessage(true);
|
||
|
}
|
||
|
startedOutsideView = false;
|
||
|
return true;
|
||
|
}
|
||
|
// if (t > .15f && !exactlyMovingKeyboard) {
|
||
|
// exactlyMovingKeyboard = true;
|
||
|
// }
|
||
|
// if (exactlyMovingKeyboard) {
|
||
|
update(t, true);
|
||
|
// }
|
||
|
if (lastT != t) {
|
||
|
lastDifferentT = lastT;
|
||
|
}
|
||
|
lastT = t;
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
public boolean disableScrolling() {
|
||
|
return ENABLED && (movingKeyboard || endingMovingKeyboard) && rawT >= 0;
|
||
|
}
|
||
|
|
||
|
private void update(float t, boolean withKeyboard) {
|
||
|
if (isKeyboard) {
|
||
|
float y = Math.max((1f - t) * keyboardSize - bottomNavBarSize - 1, 0);
|
||
|
panLayoutHelper.OnPanTranslationUpdate(y, t, true);
|
||
|
((View) ((View) view.getParent()).getParent()).setTranslationY(-y);
|
||
|
if (withKeyboard) {
|
||
|
if (insetsController != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||
|
insetsController.setInsetsAndAlpha(Insets.of(0, 0, 0, (int) (keyboardSize * (1f - t))), 1f, t);
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
float y = (1f - t) * keyboardSize;
|
||
|
panLayoutHelper.OnPanTranslationUpdate(y, t, true);
|
||
|
// ((View) ((View) view.getParent()).getParent()).setTranslationY(-y);
|
||
|
}
|
||
|
}
|
||
|
}
|