NekoX/TMessagesProj/src/main/java/org/telegram/ui/KeyboardHideHelper.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);
}
}
}