add CompoundButton hook

This commit is contained in:
Vologhat
2022-12-11 14:12:29 +03:00
parent 3eec52db3b
commit 04488314b5
11 changed files with 262 additions and 1323 deletions
Binary file not shown.
@@ -0,0 +1,66 @@
package com.vk.core.ui;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import org.xmlpull.v1.XmlPullParser;
import ru.vtosters.lite.themes.ViewInjector;
public class VKLayoutInflater extends LayoutInflater {
private final static String[] DEFAULT_PACKAGES = {
"android.widget.", "android.webkit.", "android.app."
};
public VKLayoutInflater(LayoutInflater original, Context context) {
super(original, context);
}
@Override
public LayoutInflater cloneInContext(Context newContext) {
return new VKLayoutInflater(this, newContext);
}
public final View createView(View parent, String name, Context context, AttributeSet attrs) {
if (!name.startsWith("android.")) {
try {
return onCreateView(parent, name, attrs);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
try {
return createView(name, null, attrs);
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
return null;
}
@Override
protected View onCreateView(String name, AttributeSet attrs) throws ClassNotFoundException {
for (var defPackage : DEFAULT_PACKAGES) {
try {
View view = createView(name, defPackage, attrs);
if (view != null) return view;
} catch (ClassCastException | ClassNotFoundException ignored) {
}
}
return super.onCreateView(name, attrs);
}
@Override
public View inflate(int resource, @Nullable ViewGroup root, boolean attachToRoot) {
var view = super.inflate(resource, root, attachToRoot);
return ViewInjector.inject(view, -1, attachToRoot);
}
@Override
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
var view = super.inflate(parser, root, attachToRoot);
return ViewInjector.inject(view, -1, attachToRoot);
}
}
@@ -0,0 +1,117 @@
package com.vk.core.ui;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Build;
import android.util.AttributeSet;
import android.view.InflateException;
import android.view.LayoutInflater;
import android.view.View;
import android.webkit.WebView;
import android.widget.CheckBox;
import android.widget.RadioButton;
import android.widget.Switch;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.appcompat.widget.SwitchCompat;
import com.vk.core.ui.themes.VKThemeHelper;
import com.vk.core.util.OsUtil;
import com.vk.core.view.NavigationSpinner;
import com.vk.core.view.TextViewColorStateListAndAlphaSupportPreV23;
import com.vk.core.view.VKAppBarLayout;
public class VKUILayoutFactory implements LayoutInflater.Factory2 {
private final static int[] FONT_ATTR = { android.R.attr.font };
private AppCompatDelegate mDelegate;
private VKLayoutInflater mInflater;
public VKUILayoutFactory(AppCompatDelegate delegate, VKLayoutInflater inflater) {
mDelegate = delegate;
mInflater = inflater;
}
private void setTypeface(TextView textView, Context context, AttributeSet attrs) {
TypedArray ta = context.obtainStyledAttributes(attrs, FONT_ATTR, android.R.attr.textViewStyle, 0);
if (ta == null) return;
Font font = Font.Companion.a(ta.getString(0));
if (font != null && Build.VERSION.SDK_INT < font.a())
textView.setTypeface(font.c());
ta.recycle();
}
@Nullable
@Override
public View onCreateView(@Nullable View parent, @NonNull String name, @NonNull Context context, @NonNull AttributeSet attrs) {
View view = null;
try {
if (!(parent instanceof NavigationSpinner) && !OsUtil.b())
view = new TextViewColorStateListAndAlphaSupportPreV23(context, attrs, 0);
else if (mDelegate != null)
view = mDelegate.createView(parent, name, context, attrs);
else if (mInflater != null)
view = mInflater.createView(parent, name, context, attrs);
} catch (Throwable unused) {
throw new InflateException(
"parent=" + parent.getClass().getName()
+ ":" + getResourceIdName(view)
+ ", view=" + name
+ ":" + getResourceIdName(context, attrs));
}
if (view == null &&
("com.google.android.material.appbar.AppBarLayout".equals(name)
|| "android.support.design.widget.AppBarLayout".equals(name)))
view = new VKAppBarLayout(context, attrs);
if (view != null) {
if (!(view.getTag() instanceof String)) {
if (view instanceof TextView) {
setTypeface((TextView) view, context, attrs);
if (view instanceof CheckBox)
VKThemeHelper.k.a((CheckBox) view);
else if (view instanceof RadioButton)
VKThemeHelper.k.a((RadioButton) view);
else if (view instanceof SwitchCompat)
VKThemeHelper.k.a((SwitchCompat) view);
else if (view instanceof Switch)
VKThemeHelper.k.a((Switch) view);
} else if (view instanceof WebView) {
VKThemeHelper.a((WebView) view);
}
VKThemeHelper.k.a(view, attrs);
}
}
return view;
}
private String getResourceIdName(View view) {
try {
if (view != null) {
if (view.getId() != -1)
return view.getResources().getResourceName(view.getId());
return "NO_ID";
}
return "null";
} catch (Throwable unused) {
return "FAILED_TO_GET_ID";
}
}
private String getResourceIdName(Context context, AttributeSet attrs) {
TypedArray ta = context.obtainStyledAttributes(attrs, new int[] { android.R.attr.id });
int resId = ta.getResourceId(0, -1);
ta.recycle();
return resId != -1
? context.getResources().getResourceName(resId)
: "NO_ID";
}
@Nullable
@Override
public View onCreateView(@NonNull String name, @NonNull Context context, @NonNull AttributeSet attrs) {
return onCreateView(null, name, context, attrs);
}
}
@@ -2,18 +2,10 @@ package ru.vtosters.lite.themes;
import android.view.View;
import android.view.ViewGroup;
import ru.vtosters.lite.themes.hooks.*;
import java.util.ArrayList;
import ru.vtosters.lite.themes.hooks.BaseHook;
import ru.vtosters.lite.themes.hooks.ButtonHook;
import ru.vtosters.lite.themes.hooks.ImageViewHook;
import ru.vtosters.lite.themes.hooks.ProgressWheelHook;
import ru.vtosters.lite.themes.hooks.TabLayoutHook;
import ru.vtosters.lite.themes.hooks.TextViewHook;
import ru.vtosters.lite.themes.hooks.ToolbarHook;
import ru.vtosters.lite.themes.hooks.VKImageViewHook;
public class ViewInjector {
public static ArrayList<BaseHook> hooks = new ArrayList<>();
@@ -25,6 +17,7 @@ public class ViewInjector {
hooks.add(new ToolbarHook());
hooks.add(new VKImageViewHook());
hooks.add(new ProgressWheelHook());
hooks.add(new CompoundButtonHook());
}
public static View inject(View view, int i, boolean z) {
@@ -0,0 +1,77 @@
package ru.vtosters.lite.themes.hooks;
import android.content.res.ColorStateList;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.RadioButton;
import android.widget.Switch;
import androidx.appcompat.widget.SwitchCompat;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.core.widget.CompoundButtonCompat;
import com.vk.core.ui.themes.VKThemeHelper;
import com.vk.core.util.ColorUtils;
import com.vtosters.lite.R;
import ru.vtosters.lite.utils.AndroidUtils;
import ru.vtosters.lite.utils.ThemesUtils;
public class CompoundButtonHook implements BaseHook {
private static final int[][] STATES = new int[][]{
{ android.R.attr.state_enabled, -android.R.attr.state_checked },
{ -android.R.attr.state_enabled, android.R.attr.state_checked },
{ -android.R.attr.state_checked },
{ android.R.attr.state_checked }
};
@Override
public void inject(View view, int i, boolean z) {
if (view instanceof CheckBox || view instanceof RadioButton)
recolorCompoundButton((CompoundButton) view);
else if (view instanceof Switch)
recolorSwitch((Switch) view);
else if (view instanceof SwitchCompat)
recolorSwitchCompat((SwitchCompat) view);
}
private void recolorCompoundButton(CompoundButton cb) {
var colors = new int[] {
ColorUtils.b(VKThemeHelper.d(R.attr.selection_off_icon), 0.4F),
ColorUtils.b(ThemesUtils.getAccentColor(), 0.4F),
VKThemeHelper.d(R.attr.selection_off_icon),
ThemesUtils.getAccentColor()
};
CompoundButtonCompat.setButtonTintList(cb,
new ColorStateList(STATES, colors));
}
private int[] getThumbColors() {
return new int[] {
AndroidUtils.getResources().getColor(
ThemesUtils.getCurrentTheme().a() ? R.color.steel_gray_150: R.color.white),
AndroidUtils.getResources().getColor(
ThemesUtils.getCurrentTheme().a() ? R.color.switch_disabled_on_dark : R.color.switch_disabled_on_light),
AndroidUtils.getResources().getColor(R.color.gray_20),
VKThemeHelper.d(R.attr.accent)
};
}
private int[] getTrackColors() {
return new int[] {
ColorUtils.b(VKThemeHelper.d(R.attr.loader_track_fill), 0.4F),
ColorUtils.b(ThemesUtils.getAccentColor(), 0.12F),
VKThemeHelper.d(R.attr.loader_track_fill),
ColorUtils.b(ThemesUtils.getAccentColor(), 0.48F)
};
}
private void recolorSwitch(Switch s) {
DrawableCompat.setTintList(DrawableCompat.wrap(s.getThumbDrawable()), new ColorStateList(STATES, getThumbColors()));
DrawableCompat.setTintList(DrawableCompat.wrap(s.getTrackDrawable()), new ColorStateList(STATES, getTrackColors()));
}
private void recolorSwitchCompat(SwitchCompat s) {
DrawableCompat.setTintList(DrawableCompat.wrap(s.getThumbDrawable()), new ColorStateList(STATES, getThumbColors()));
DrawableCompat.setTintList(DrawableCompat.wrap(s.getTrackDrawable()), new ColorStateList(STATES, getTrackColors()));
}
}