diff --git a/app/src/main/java/com/mogo/launcher/lancet/ViewPressedStateLancet.java b/app/src/main/java/com/mogo/launcher/lancet/ViewPressedStateLancet.java
new file mode 100644
index 0000000000..3ebd92187f
--- /dev/null
+++ b/app/src/main/java/com/mogo/launcher/lancet/ViewPressedStateLancet.java
@@ -0,0 +1,191 @@
+package com.mogo.launcher.lancet;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.TypedArray;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.StateListDrawable;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+import androidx.core.graphics.drawable.DrawableCompat;
+import androidx.core.view.ViewCompat;
+import com.knightboost.lancet.api.Origin;
+import com.knightboost.lancet.api.Scope;
+import com.knightboost.lancet.api.annotations.Group;
+import com.knightboost.lancet.api.annotations.ImplementedInterface;
+import com.knightboost.lancet.api.annotations.Insert;
+import com.knightboost.lancet.api.annotations.ReplaceInvoke;
+import com.knightboost.lancet.api.annotations.TargetClass;
+import com.knightboost.lancet.api.annotations.TargetMethod;
+import com.knightboost.lancet.api.annotations.Weaver;
+import com.mogo.launcher.R;
+
+@Weaver
+@Group("view_pressed_state")
+public class ViewPressedStateLancet {
+
+ @TargetClass(value = "android.view.View", scope = Scope.ALL)
+ @TargetMethod(methodName = "setOnClickListener")
+ @ReplaceInvoke
+ public static void setOnClickListener(View view, View.OnClickListener listener) {
+ Object tag = view.getTag(R.id.click_pressed_attr_id);
+ checkSetBgIfNeed(view, tag == null ? null : (AttributeSet) tag);
+ view.setOnClickListener(listener);
+ }
+
+ @TargetClass(value = "android.view.View", scope = Scope.ALL)
+ @TargetMethod(methodName = "setOnLongClickListener")
+ @ReplaceInvoke
+ public static void setOnLongClickListener(View view, View.OnLongClickListener listener) {
+ Object tag = view.getTag(R.id.click_pressed_attr_id);
+ checkSetBgIfNeed(view, tag == null ? null : (AttributeSet) tag);
+ view.setOnLongClickListener(listener);
+ }
+
+ @ImplementedInterface(value = "android.view.LayoutInflater$Factory", scope = Scope.LEAF)
+ @Insert(mayCreateSuper = true)
+ @TargetMethod(methodName = "onCreateView")
+ public View onCreateView(String name, Context context, AttributeSet attrs) {
+ View view = (View) Origin.call();
+ checkSetBgIfNeed(view, attrs);
+ return view;
+ }
+
+ @ImplementedInterface(value = "android.view.LayoutInflater$Factory2", scope = Scope.LEAF)
+ @Insert(mayCreateSuper = true)
+ @TargetMethod(methodName = "onCreateView")
+ public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
+ View view = (View) Origin.call();
+ checkSetBgIfNeed(view, attrs);
+ return view;
+ }
+
+ private static void checkSetBgIfNeed(View view, AttributeSet attr) {
+ try {
+ TypedArray t = null;
+ float alpha;
+ boolean enabled;
+ try {
+ if (view == null) {
+ return;
+ }
+ Context context = view.getContext();
+ if (context == null) {
+ return;
+ }
+ if (attr == null) {
+ return;
+ }
+ t = context.obtainStyledAttributes(attr, R.styleable.ClickPressedStyle);
+ enabled = t.getBoolean(R.styleable.ClickPressedStyle_pressed_enabled, true);
+ if (!enabled) {
+ return;
+ }
+ alpha = t.getFloat(R.styleable.ClickPressedStyle_pressed_alpha, 0.6f);
+ if (alpha > 1.0f) {
+ throw new AssertionError("view custom attr: alpha > 1.0f, must be in [0.0, 1.0]");
+ }
+ view.setTag(R.id.click_pressed_attr_id, attr);
+ } finally {
+ if (t != null) {
+ t.recycle();
+ }
+ }
+ if (view instanceof ImageView) {
+ ImageView image = (ImageView) view;
+ Drawable replaced = checkAndReplaceDrawable(image.getBackground(), alpha);
+ if (replaced != null) {
+ ViewCompat.setBackground(image, replaced);
+ return;
+ }
+ replaced = checkAndReplaceDrawable(image.getDrawable(), alpha);
+ if (replaced != null) {
+ image.setImageDrawable(replaced);
+ return;
+ }
+ }
+ if (view instanceof TextView) {
+ TextView text = (TextView) view;
+ Drawable replaced = checkAndReplaceDrawable(text.getBackground(), alpha);
+ if (replaced != null) {
+ ViewCompat.setBackground(text, replaced);
+ return;
+ }
+ ColorStateList textColor = text.getTextColors();
+ if (textColor != null) {
+ int pressed = textColor.getColorForState(new int[]{ android.R.attr.state_pressed }, Integer.MIN_VALUE);
+ if (pressed != Integer.MIN_VALUE) {
+ return;
+ }
+ int defaultColor = textColor.getDefaultColor();
+ int pressedColor = Color.argb((int)(Color.alpha(defaultColor) * alpha), Color.red(defaultColor), Color.green(defaultColor), Color.blue(defaultColor));
+ ColorStateList newColor = new ColorStateList(new int[][] { new int[] { -android.R.attr.state_pressed }, new int[] { android.R.attr.state_pressed }}, new int[] { defaultColor, pressedColor });
+ text.setTextColor(newColor);
+ }
+ }
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+
+ private static Drawable checkAndReplaceDrawable(Drawable old, float alpha) {
+ if (old == null) {
+ return null;
+ }
+ if (old instanceof StateListDrawable) {
+ StateListDrawable drawable = (StateListDrawable) old;
+ int[] states = drawable.getState();
+ boolean hasPressed = false;
+ int index = 0;
+ int targetIndex = -1;
+ for (int state : states) {
+ if (!hasPressed && state == android.R.attr.state_pressed) {
+ hasPressed = true;
+ }
+ if (targetIndex == -1 && state != -android.R.attr.state_enabled) {
+ targetIndex = index;
+ }
+ if (hasPressed && targetIndex != -1) {
+ break;
+ }
+ index ++;
+ }
+ if (hasPressed) {
+ return null;
+ }
+ if (targetIndex != -1) {
+ Drawable origin= null;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ origin = drawable.getStateDrawable(targetIndex);
+ } else {
+ origin = drawable.getCurrent();
+ }
+ if (origin != null) {
+ Drawable.ConstantState constantState = origin.getConstantState();
+ if (constantState != null) {
+ Drawable pressed = DrawableCompat.wrap(constantState.newDrawable().mutate());
+ pressed.setAlpha((int)(255 * alpha));
+ drawable.addState(new int[] {android.R.attr.state_pressed}, pressed);
+ return drawable;
+ }
+ }
+ return null;
+ }
+ return null;
+ }
+ Drawable.ConstantState constantState = old.getConstantState();
+ if (constantState != null) {
+ StateListDrawable result = new StateListDrawable();
+ result.addState(new int[] { -android.R.attr.state_pressed }, old);
+ Drawable pressed = DrawableCompat.wrap(constantState.newDrawable().mutate());
+ pressed.setAlpha((int)(255 * alpha));
+ result.addState(new int[] { android.R.attr.state_pressed }, pressed);
+ return result;
+ }
+ return null;
+ }
+}
diff --git a/core/mogo-core-res/src/main/res/values/ids.xml b/core/mogo-core-res/src/main/res/values/ids.xml
new file mode 100644
index 0000000000..fc995c989e
--- /dev/null
+++ b/core/mogo-core-res/src/main/res/values/ids.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/core/mogo-core-res/src/main/res/values/styles.xml b/core/mogo-core-res/src/main/res/values/styles.xml
index d983a865a0..e6496d2029 100644
--- a/core/mogo-core-res/src/main/res/values/styles.xml
+++ b/core/mogo-core-res/src/main/res/values/styles.xml
@@ -13,4 +13,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/gradle/bytex/bytex_lancetx.gradle b/gradle/bytex/bytex_lancetx.gradle
index d4cbbd960e..9f9ed05765 100644
--- a/gradle/bytex/bytex_lancetx.gradle
+++ b/gradle/bytex/bytex_lancetx.gradle
@@ -30,6 +30,9 @@ LancetX {
main_block_check {
enable rootProject.isJunkDetectEnable()
}
+ view_pressed_state {
+ enable true
+ }
}
}