[6.2.4][View点击态] 添加View的点击态
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
4
core/mogo-core-res/src/main/res/values/ids.xml
Normal file
4
core/mogo-core-res/src/main/res/values/ids.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<item name="click_pressed_attr_id" type="id" />
|
||||
</resources>
|
||||
@@ -13,4 +13,8 @@
|
||||
</declare-styleable>
|
||||
|
||||
|
||||
<declare-styleable name="ClickPressedStyle">
|
||||
<attr name="pressed_alpha" format="float" />
|
||||
<attr name="pressed_enabled" format="boolean" />
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
@@ -30,6 +30,9 @@ LancetX {
|
||||
main_block_check {
|
||||
enable rootProject.isJunkDetectEnable()
|
||||
}
|
||||
view_pressed_state {
|
||||
enable true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user