NekoX/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java

738 lines
26 KiB
Java
Raw Normal View History

2017-03-31 01:58:05 +02:00
/*
2019-01-23 18:03:33 +01:00
* This is the source code of Telegram for Android v. 5.x.x.
2017-03-31 01:58:05 +02:00
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
2019-01-23 18:03:33 +01:00
* Copyright Nikolai Kudashov, 2013-2018.
2017-03-31 01:58:05 +02:00
*/
package org.telegram.ui.Components;
2018-07-30 04:07:02 +02:00
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
2019-01-23 18:03:33 +01:00
import android.annotation.SuppressLint;
2019-05-14 14:08:05 +02:00
import android.annotation.TargetApi;
2017-03-31 01:58:05 +02:00
import android.content.Context;
import android.graphics.Canvas;
2018-07-30 04:07:02 +02:00
import android.graphics.Color;
import android.graphics.Paint;
2017-03-31 01:58:05 +02:00
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.Rect;
2019-05-14 14:08:05 +02:00
import android.os.Build;
2017-03-31 01:58:05 +02:00
import android.os.SystemClock;
2019-05-14 14:08:05 +02:00
import androidx.annotation.Keep;
2017-03-31 01:58:05 +02:00
import android.text.Layout;
import android.text.StaticLayout;
2018-07-30 04:07:02 +02:00
import android.text.TextPaint;
import android.text.TextUtils;
2019-12-31 14:08:08 +01:00
import android.view.ActionMode;
2017-03-31 01:58:05 +02:00
import android.view.Gravity;
2019-12-31 14:08:08 +01:00
import android.view.Menu;
import android.view.MenuItem;
2017-03-31 01:58:05 +02:00
import android.view.View;
2019-01-23 18:03:33 +01:00
import android.view.ViewTreeObserver;
2019-05-14 14:08:05 +02:00
import android.view.accessibility.AccessibilityNodeInfo;
2017-03-31 01:58:05 +02:00
import android.widget.EditText;
import android.widget.TextView;
import org.telegram.messenger.AndroidUtilities;
2019-05-14 14:08:05 +02:00
import org.telegram.messenger.FileLog;
2018-07-30 04:07:02 +02:00
import org.telegram.messenger.LocaleController;
2017-03-31 01:58:05 +02:00
import org.telegram.messenger.R;
2019-12-31 14:08:08 +01:00
import org.telegram.ui.ActionBar.FloatingActionMode;
import org.telegram.ui.ActionBar.FloatingToolbar;
2017-03-31 01:58:05 +02:00
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class EditTextBoldCursor extends EditText {
private static Field mEditor;
private static Field mShowCursorField;
private static Field mScrollYField;
private static Method getVerticalOffsetMethod;
2019-05-14 14:08:05 +02:00
private static Class editorClass;
2019-12-31 14:08:08 +01:00
private static Field mCursorDrawableResField;
2018-07-30 04:07:02 +02:00
2019-05-14 14:08:05 +02:00
private Drawable mCursorDrawable;
2018-07-30 04:07:02 +02:00
private Object editor;
2017-03-31 01:58:05 +02:00
private GradientDrawable gradientDrawable;
2018-07-30 04:07:02 +02:00
2019-12-31 14:08:08 +01:00
private Runnable invalidateRunnable = new Runnable() {
@Override
public void run() {
invalidate();
if (attachedToWindow != null) {
AndroidUtilities.runOnUIThread(this, 500);
}
}
};
2018-07-30 04:07:02 +02:00
private Paint linePaint;
private TextPaint errorPaint;
2017-03-31 01:58:05 +02:00
private int cursorSize;
private int ignoreTopCount;
private int ignoreBottomCount;
private int scrollY;
private float lineSpacingExtra;
private Rect rect = new Rect();
private StaticLayout hintLayout;
2018-07-30 04:07:02 +02:00
private StaticLayout errorLayout;
private CharSequence errorText;
2017-03-31 01:58:05 +02:00
private int hintColor;
2018-07-30 04:07:02 +02:00
private int headerHintColor;
2017-03-31 01:58:05 +02:00
private boolean hintVisible = true;
private float hintAlpha = 1.0f;
private long lastUpdateTime;
private boolean allowDrawCursor = true;
2017-12-08 18:35:59 +01:00
private float cursorWidth = 2.0f;
2018-07-30 04:07:02 +02:00
private boolean supportRtlHint;
private int lineColor;
private int activeLineColor;
private int errorLineColor;
private float lineY;
private boolean nextSetTextAnimated;
private boolean transformHintToHeader;
private boolean currentDrawHintAsHeader;
private AnimatorSet headerTransformAnimation;
private float headerAnimationProgress;
2017-03-31 01:58:05 +02:00
2019-01-23 18:03:33 +01:00
private boolean fixed;
private ViewTreeObserver.OnPreDrawListener listenerFixer;
2019-12-31 14:08:08 +01:00
private FloatingToolbar floatingToolbar;
private FloatingActionMode floatingActionMode;
private ViewTreeObserver.OnPreDrawListener floatingToolbarPreDrawListener;
private View windowView;
private View attachedToWindow;
@TargetApi(23)
private class ActionModeCallback2Wrapper extends ActionMode.Callback2 {
private final ActionMode.Callback mWrapped;
public ActionModeCallback2Wrapper(ActionMode.Callback wrapped) {
mWrapped = wrapped;
}
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return mWrapped.onCreateActionMode(mode, menu);
}
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return mWrapped.onPrepareActionMode(mode, menu);
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return mWrapped.onActionItemClicked(mode, item);
}
public void onDestroyActionMode(ActionMode mode) {
mWrapped.onDestroyActionMode(mode);
cleanupFloatingActionModeViews();
floatingActionMode = null;
}
@Override
public void onGetContentRect(ActionMode mode, View view, Rect outRect) {
if (mWrapped instanceof ActionMode.Callback2) {
((ActionMode.Callback2) mWrapped).onGetContentRect(mode, view, outRect);
} else {
super.onGetContentRect(mode, view, outRect);
}
}
}
2017-03-31 01:58:05 +02:00
public EditTextBoldCursor(Context context) {
super(context);
2019-05-14 14:08:05 +02:00
if (Build.VERSION.SDK_INT >= 26) {
setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO);
}
init();
}
@TargetApi(Build.VERSION_CODES.O)
@Override
public int getAutofillType() {
return AUTOFILL_TYPE_NONE;
}
2017-03-31 01:58:05 +02:00
2019-05-14 14:08:05 +02:00
@SuppressLint("PrivateApi")
private void init() {
2018-07-30 04:07:02 +02:00
linePaint = new Paint();
errorPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
errorPaint.setTextSize(AndroidUtilities.dp(11));
2019-05-14 14:08:05 +02:00
if (Build.VERSION.SDK_INT >= 26) {
setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO);
}
2018-07-30 04:07:02 +02:00
2019-05-14 14:08:05 +02:00
try {
if (mScrollYField == null) {
2017-03-31 01:58:05 +02:00
mScrollYField = View.class.getDeclaredField("mScrollY");
mScrollYField.setAccessible(true);
2019-05-14 14:08:05 +02:00
}
} catch (Throwable ignore) {
}
try {
if (editorClass == null) {
mEditor = TextView.class.getDeclaredField("mEditor");
mEditor.setAccessible(true);
editorClass = Class.forName("android.widget.Editor");
mShowCursorField = editorClass.getDeclaredField("mShowCursor");
mShowCursorField.setAccessible(true);
getVerticalOffsetMethod = TextView.class.getDeclaredMethod("getVerticalOffset", boolean.class);
getVerticalOffsetMethod.setAccessible(true);
2017-03-31 01:58:05 +02:00
mShowCursorField = editorClass.getDeclaredField("mShowCursor");
mShowCursorField.setAccessible(true);
}
2019-05-14 14:08:05 +02:00
} catch (Throwable e) {
FileLog.e(e);
2017-03-31 01:58:05 +02:00
}
try {
gradientDrawable = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int[] {0xff54a1db, 0xff54a1db});
2019-12-31 14:08:08 +01:00
if (Build.VERSION.SDK_INT >= 29) {
setTextCursorDrawable(gradientDrawable);
}
2017-03-31 01:58:05 +02:00
editor = mEditor.get(this);
2019-12-31 14:08:08 +01:00
} catch (Throwable ignore) {
}
try {
if (mCursorDrawableResField == null) {
mCursorDrawableResField = TextView.class.getDeclaredField("mCursorDrawableRes");
mCursorDrawableResField.setAccessible(true);
}
if (mCursorDrawableResField != null) {
2018-08-27 10:33:11 +02:00
mCursorDrawableResField.set(this, R.drawable.field_carret_empty);
}
2019-01-23 18:03:33 +01:00
} catch (Throwable ignore) {
2017-03-31 01:58:05 +02:00
}
cursorSize = AndroidUtilities.dp(24);
}
2019-01-23 18:03:33 +01:00
@SuppressLint("PrivateApi")
public void fixHandleView(boolean reset) {
if (reset) {
fixed = false;
} else if (!fixed) {
try {
if (editorClass == null) {
editorClass = Class.forName("android.widget.Editor");
mEditor = TextView.class.getDeclaredField("mEditor");
mEditor.setAccessible(true);
editor = mEditor.get(this);
}
if (listenerFixer == null) {
Method initDrawablesMethod = editorClass.getDeclaredMethod("getPositionListener");
initDrawablesMethod.setAccessible(true);
listenerFixer = (ViewTreeObserver.OnPreDrawListener) initDrawablesMethod.invoke(editor);
}
AndroidUtilities.runOnUIThread(listenerFixer::onPreDraw, 500);
} catch (Throwable ignore) {
}
fixed = true;
}
}
2018-07-30 04:07:02 +02:00
public void setTransformHintToHeader(boolean value) {
if (transformHintToHeader == value) {
return;
}
transformHintToHeader = value;
if (headerTransformAnimation != null) {
headerTransformAnimation.cancel();
headerTransformAnimation = null;
}
}
2017-03-31 01:58:05 +02:00
public void setAllowDrawCursor(boolean value) {
allowDrawCursor = value;
2019-05-14 14:08:05 +02:00
invalidate();
2017-03-31 01:58:05 +02:00
}
2017-12-08 18:35:59 +01:00
public void setCursorWidth(float width) {
cursorWidth = width;
}
2017-03-31 01:58:05 +02:00
public void setCursorColor(int color) {
gradientDrawable.setColor(color);
invalidate();
}
public void setCursorSize(int value) {
cursorSize = value;
}
2018-07-30 04:07:02 +02:00
public void setErrorLineColor(int error) {
errorLineColor = error;
errorPaint.setColor(errorLineColor);
invalidate();
}
public void setLineColors(int color, int active, int error) {
lineColor = color;
activeLineColor = active;
errorLineColor = error;
errorPaint.setColor(errorLineColor);
invalidate();
}
2017-03-31 01:58:05 +02:00
public void setHintVisible(boolean value) {
if (hintVisible == value) {
return;
}
lastUpdateTime = System.currentTimeMillis();
hintVisible = value;
invalidate();
}
public void setHintColor(int value) {
hintColor = value;
invalidate();
}
2018-07-30 04:07:02 +02:00
public void setHeaderHintColor(int value) {
headerHintColor = value;
invalidate();
}
public void setNextSetTextAnimated(boolean value) {
nextSetTextAnimated = value;
}
public void setErrorText(CharSequence text) {
if (TextUtils.equals(text, errorText)) {
return;
}
errorText = text;
requestLayout();
}
2019-06-04 12:14:50 +02:00
@Override
public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
return super.requestFocus(direction, previouslyFocusedRect);
}
2018-07-30 04:07:02 +02:00
public boolean hasErrorText() {
return !TextUtils.isEmpty(errorText);
}
public StaticLayout getErrorLayout(int width) {
if (TextUtils.isEmpty(errorText)) {
return null;
} else {
return new StaticLayout(errorText, errorPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
}
}
public float getLineY() {
return lineY;
}
public void setSupportRtlHint(boolean value) {
supportRtlHint = value;
}
2020-03-30 14:00:09 +02:00
@Override
protected void onScrollChanged(int horiz, int vert, int oldHoriz, int oldVert) {
super.onScrollChanged(horiz, vert, oldHoriz, oldVert);
if (horiz != oldHoriz) {
getParent().requestDisallowInterceptTouchEvent(true);
}
}
2018-07-30 04:07:02 +02:00
@Override
public void setText(CharSequence text, BufferType type) {
super.setText(text, type);
checkHeaderVisibility(nextSetTextAnimated);
nextSetTextAnimated = false;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (hintLayout != null) {
lineY = (getMeasuredHeight() - hintLayout.getHeight()) / 2.0f + hintLayout.getHeight() + AndroidUtilities.dp(6);
}
}
2019-12-31 14:08:08 +01:00
public void setHintText(CharSequence text) {
if (text == null) {
text = "";
}
2018-07-30 04:07:02 +02:00
hintLayout = new StaticLayout(text, getPaint(), AndroidUtilities.dp(1000), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
}
2019-12-31 14:08:08 +01:00
public Layout getHintLayoutEx() {
return hintLayout;
}
2018-07-30 04:07:02 +02:00
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
super.onFocusChanged(focused, direction, previouslyFocusedRect);
checkHeaderVisibility(true);
}
private void checkHeaderVisibility(boolean animated) {
boolean newHintHeader = transformHintToHeader && (isFocused() || getText().length() > 0);
if (currentDrawHintAsHeader != newHintHeader) {
if (headerTransformAnimation != null) {
headerTransformAnimation.cancel();
headerTransformAnimation = null;
}
currentDrawHintAsHeader = newHintHeader;
if (animated) {
headerTransformAnimation = new AnimatorSet();
headerTransformAnimation.playTogether(ObjectAnimator.ofFloat(this, "headerAnimationProgress", newHintHeader ? 1.0f : 0.0f));
headerTransformAnimation.setDuration(200);
headerTransformAnimation.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT);
headerTransformAnimation.start();
} else {
headerAnimationProgress = newHintHeader ? 1.0f : 0.0f;
}
invalidate();
}
}
@Keep
public void setHeaderAnimationProgress(float value) {
headerAnimationProgress = value;
invalidate();
}
@Keep
public float getHeaderAnimationProgress() {
return headerAnimationProgress;
2017-03-31 01:58:05 +02:00
}
@Override
public void setLineSpacing(float add, float mult) {
super.setLineSpacing(add, mult);
lineSpacingExtra = add;
}
@Override
public int getExtendedPaddingTop() {
if (ignoreTopCount != 0) {
ignoreTopCount--;
return 0;
}
return super.getExtendedPaddingTop();
}
@Override
public int getExtendedPaddingBottom() {
if (ignoreBottomCount != 0) {
ignoreBottomCount--;
return scrollY != Integer.MAX_VALUE ? -scrollY : 0;
}
return super.getExtendedPaddingBottom();
}
@Override
protected void onDraw(Canvas canvas) {
int topPadding = getExtendedPaddingTop();
scrollY = Integer.MAX_VALUE;
try {
scrollY = mScrollYField.getInt(this);
mScrollYField.set(this, 0);
} catch (Exception e) {
//
}
ignoreTopCount = 1;
ignoreBottomCount = 1;
canvas.save();
canvas.translate(0, topPadding);
try {
super.onDraw(canvas);
} catch (Exception e) {
//
}
if (scrollY != Integer.MAX_VALUE) {
try {
mScrollYField.set(this, scrollY);
} catch (Exception e) {
//
}
}
canvas.restore();
2018-07-30 04:07:02 +02:00
if ((length() == 0 || transformHintToHeader) && hintLayout != null && (hintVisible || hintAlpha != 0)) {
2017-03-31 01:58:05 +02:00
if (hintVisible && hintAlpha != 1.0f || !hintVisible && hintAlpha != 0.0f) {
long newTime = System.currentTimeMillis();
long dt = newTime - lastUpdateTime;
if (dt < 0 || dt > 17) {
dt = 17;
}
lastUpdateTime = newTime;
if (hintVisible) {
hintAlpha += dt / 150.0f;
if (hintAlpha > 1.0f) {
hintAlpha = 1.0f;
}
} else {
hintAlpha -= dt / 150.0f;
if (hintAlpha < 0.0f) {
hintAlpha = 0.0f;
}
}
invalidate();
}
int oldColor = getPaint().getColor();
2018-07-30 04:07:02 +02:00
2017-03-31 01:58:05 +02:00
canvas.save();
2017-12-08 18:35:59 +01:00
int left = 0;
float lineLeft = hintLayout.getLineLeft(0);
2018-07-30 04:07:02 +02:00
float hintWidth = hintLayout.getLineWidth(0);
2017-12-08 18:35:59 +01:00
if (lineLeft != 0) {
left -= lineLeft;
}
2018-07-30 04:07:02 +02:00
if (supportRtlHint && LocaleController.isRTL) {
float offset = getMeasuredWidth() - hintWidth;
canvas.translate(left + getScrollX() + offset, lineY - hintLayout.getHeight() - AndroidUtilities.dp(6));
} else {
canvas.translate(left + getScrollX(), lineY - hintLayout.getHeight() - AndroidUtilities.dp(6));
}
if (transformHintToHeader) {
float scale = 1.0f - 0.3f * headerAnimationProgress;
float translation = -AndroidUtilities.dp(22) * headerAnimationProgress;
int rF = Color.red(headerHintColor);
int gF = Color.green(headerHintColor);
int bF = Color.blue(headerHintColor);
int aF = Color.alpha(headerHintColor);
int rS = Color.red(hintColor);
int gS = Color.green(hintColor);
int bS = Color.blue(hintColor);
int aS = Color.alpha(hintColor);
if (supportRtlHint && LocaleController.isRTL) {
canvas.translate((hintWidth + lineLeft) - (hintWidth + lineLeft) * scale, 0);
2019-02-08 03:30:32 +01:00
} else if (lineLeft != 0) {
canvas.translate(lineLeft * (1.0f - scale), 0);
2018-07-30 04:07:02 +02:00
}
canvas.scale(scale, scale);
canvas.translate(0, translation);
getPaint().setColor(Color.argb((int) (aS + (aF - aS) * headerAnimationProgress), (int) (rS + (rF - rS) * headerAnimationProgress), (int) (gS + (gF - gS) * headerAnimationProgress), (int) (bS + (bF - bS) * headerAnimationProgress)));
} else {
getPaint().setColor(hintColor);
getPaint().setAlpha((int) (255 * hintAlpha * (Color.alpha(hintColor) / 255.0f)));
}
2017-03-31 01:58:05 +02:00
hintLayout.draw(canvas);
getPaint().setColor(oldColor);
canvas.restore();
}
try {
2019-05-14 14:08:05 +02:00
if (allowDrawCursor && mShowCursorField != null) {
2019-12-31 14:08:08 +01:00
long mShowCursor = mShowCursorField.getLong(editor);
boolean showCursor = (SystemClock.uptimeMillis() - mShowCursor) % (2 * 500) < 500 && isFocused();
if (showCursor) {
canvas.save();
int voffsetCursor = 0;
if (getVerticalOffsetMethod != null) {
2019-07-18 15:01:39 +02:00
if ((getGravity() & Gravity.VERTICAL_GRAVITY_MASK) != Gravity.TOP) {
voffsetCursor = (int) getVerticalOffsetMethod.invoke(this, true);
}
2019-12-31 14:08:08 +01:00
} else {
if ((getGravity() & Gravity.VERTICAL_GRAVITY_MASK) != Gravity.TOP) {
voffsetCursor = getTotalPaddingTop() - getExtendedPaddingTop();
2019-07-18 15:01:39 +02:00
}
2017-03-31 01:58:05 +02:00
}
2019-12-31 14:08:08 +01:00
canvas.translate(getPaddingLeft(), getExtendedPaddingTop() + voffsetCursor);
Layout layout = getLayout();
int line = layout.getLineForOffset(getSelectionStart());
int lineCount = layout.getLineCount();
updateCursorPosition();
Rect bounds = gradientDrawable.getBounds();
rect.left = bounds.left;
rect.right = bounds.left + AndroidUtilities.dp(cursorWidth);
rect.bottom = bounds.bottom;
rect.top = bounds.top;
if (lineSpacingExtra != 0 && line < lineCount - 1) {
rect.bottom -= lineSpacingExtra;
}
rect.top = rect.centerY() - cursorSize / 2;
rect.bottom = rect.top + cursorSize;
gradientDrawable.setBounds(rect);
gradientDrawable.draw(canvas);
canvas.restore();
2017-03-31 01:58:05 +02:00
}
}
2019-05-14 14:08:05 +02:00
} catch (Throwable ignore) {
2017-03-31 01:58:05 +02:00
}
2018-07-30 04:07:02 +02:00
if (lineColor != 0 && hintLayout != null) {
int h;
if (!TextUtils.isEmpty(errorText)) {
linePaint.setColor(errorLineColor);
h = AndroidUtilities.dp(2);
} else if (isFocused()) {
linePaint.setColor(activeLineColor);
h = AndroidUtilities.dp(2);
} else {
linePaint.setColor(lineColor);
h = AndroidUtilities.dp(1);
}
canvas.drawRect(getScrollX(), (int) lineY, getScrollX() + getMeasuredWidth(), lineY + h, linePaint);
}
/*if (errorLayout != null) {
canvas.save();
canvas.translate(getScrollX(), lineY + AndroidUtilities.dp(3));
errorLayout.draw(canvas);
canvas.restore();
}*/
2017-03-31 01:58:05 +02:00
}
2019-05-14 14:08:05 +02:00
2019-12-31 14:08:08 +01:00
public void setWindowView(View view) {
windowView = view;
}
private boolean updateCursorPosition() {
final Layout layout = getLayout();
final int offset = getSelectionStart();
final int line = layout.getLineForOffset(offset);
final int top = layout.getLineTop(line);
final int bottom = layout.getLineTop(line + 1);
updateCursorPosition(top, bottom, layout.getPrimaryHorizontal(offset));
return true;
}
private Rect mTempRect;
private int clampHorizontalPosition(final Drawable drawable, float horizontal) {
horizontal = Math.max(0.5f, horizontal - 0.5f);
if (mTempRect == null) {
mTempRect = new Rect();
}
int drawableWidth = 0;
if (drawable != null) {
drawable.getPadding(mTempRect);
drawableWidth = drawable.getIntrinsicWidth();
} else {
mTempRect.setEmpty();
}
int scrollX = getScrollX();
float horizontalDiff = horizontal - scrollX;
int viewClippedWidth = getWidth() - getCompoundPaddingLeft() - getCompoundPaddingRight();
final int left;
if (horizontalDiff >= (viewClippedWidth - 1f)) {
left = viewClippedWidth + scrollX - (drawableWidth - mTempRect.right);
} else if (Math.abs(horizontalDiff) <= 1f || (TextUtils.isEmpty(getText()) && (1024 * 1024 - scrollX) <= (viewClippedWidth + 1f) && horizontal <= 1f)) {
left = scrollX - mTempRect.left;
} else {
left = (int) horizontal - mTempRect.left;
}
return left;
}
private void updateCursorPosition(int top, int bottom, float horizontal) {
final int left = clampHorizontalPosition(gradientDrawable, horizontal);
final int width = AndroidUtilities.dp(cursorWidth);
gradientDrawable.setBounds(left, top - mTempRect.top, left + width, bottom + mTempRect.bottom);
}
@Override
public float getLineSpacingExtra() {
return super.getLineSpacingExtra();
}
private void cleanupFloatingActionModeViews() {
if (floatingToolbar != null) {
floatingToolbar.dismiss();
floatingToolbar = null;
}
if (floatingToolbarPreDrawListener != null) {
getViewTreeObserver().removeOnPreDrawListener(floatingToolbarPreDrawListener);
floatingToolbarPreDrawListener = null;
}
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
attachedToWindow = getRootView();
AndroidUtilities.runOnUIThread(invalidateRunnable);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
attachedToWindow = null;
AndroidUtilities.cancelRunOnUIThread(invalidateRunnable);
}
@Override
public ActionMode startActionMode(ActionMode.Callback callback) {
if (Build.VERSION.SDK_INT >= 23 && (windowView != null || attachedToWindow != null)) {
if (floatingActionMode != null) {
floatingActionMode.finish();
}
cleanupFloatingActionModeViews();
floatingToolbar = new FloatingToolbar(getContext(), windowView != null ? windowView : attachedToWindow, getActionModeStyle());
floatingActionMode = new FloatingActionMode(getContext(), new ActionModeCallback2Wrapper(callback), this, floatingToolbar);
floatingToolbarPreDrawListener = () -> {
2019-12-31 20:46:59 +01:00
if (floatingActionMode != null) {
floatingActionMode.updateViewLocationInWindow();
}
2019-12-31 14:08:08 +01:00
return true;
};
callback.onCreateActionMode(floatingActionMode, floatingActionMode.getMenu());
extendActionMode(floatingActionMode, floatingActionMode.getMenu());
floatingActionMode.invalidate();
getViewTreeObserver().addOnPreDrawListener(floatingToolbarPreDrawListener);
invalidate();
return floatingActionMode;
} else {
return super.startActionMode(callback);
}
}
@Override
public ActionMode startActionMode(ActionMode.Callback callback, int type) {
if (Build.VERSION.SDK_INT >= 23 && (windowView != null || attachedToWindow != null)) {
return startActionMode(callback);
} else {
return super.startActionMode(callback, type);
}
}
protected void extendActionMode(ActionMode actionMode, Menu menu) {
}
protected int getActionModeStyle() {
return FloatingToolbar.STYLE_THEME;
}
@Override
public void setSelection(int start, int stop) {
try {
super.setSelection(start, stop);
} catch (Exception e) {
FileLog.e(e);
}
}
@Override
public void setSelection(int index) {
try {
super.setSelection(index);
} catch (Exception e) {
FileLog.e(e);
}
}
2019-05-14 14:08:05 +02:00
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName("android.widget.EditText");
2019-12-31 14:08:08 +01:00
if (hintLayout != null) {
info.setContentDescription(hintLayout.getText());
}
2019-05-14 14:08:05 +02:00
}
2017-03-31 01:58:05 +02:00
}