Android hook技术实现一键换肤,2024年最新android studio用户界面设计

本文探讨了如何使用Android Hook技术实现一键换肤,详细解析了在Android Studio中创建兼容性视图的过程,并通过反射和构造函数创建系统控件。文章指出,当系统创建的视图为空时,需要通过反射来手动创建,以确保主题生效。此外,介绍了如何收集需要换肤的View,并提供了换肤的实现逻辑。最后,作者分享了一套完整的Android移动开发学习资料,旨在帮助开发者提升技能和职业发展。
摘要由CSDN通过智能技术生成

@NonNull AttributeSet attrs, boolean inheritContext,

boolean readAndroidTheme, boolean readAppTheme, boolean wrapContext) {

final Context originalContext = context;

// We can emulate Lollipop’s android:theme attribute propagating down the view hierarchy

// by using the parent’s context

if (inheritContext && parent != null) {

context = parent.getContext();

}

if (readAndroidTheme || readAppTheme) {

// We then apply the theme on the context, if specified

context = themifyContext(context, attrs, readAndroidTheme, readAppTheme);

}

if (wrapContext) {

context = TintContextWrapper.wrap(context);

}

View view = null;

// We need to ‘inject’ our tint aware Views in place of the standard framework versions

switch (name) {

case “TextView”:

view = createTextView(context, attrs);

verifyNotNull(view, name);

break;

case “ImageView”:

view = createImageView(context, attrs);

verifyNotNull(view, name);

break;

case “Button”:

view = createButton(context, attrs);

verifyNotNull(view, name);

break;

case “EditText”:

view = createEditText(context, attrs);

verifyNotNull(view, name);

break;

case “Spinner”:

view = createSpinner(context, attrs);

verifyNotNull(view, name);

break;

case “ImageButton”:

view = createImageButton(context, attrs);

verifyNotNull(view, name);

break;

case “CheckBox”:

view = createCheckBox(context, attrs);

verifyNotNull(view, name);

break;

case “RadioButton”:

view = createRadioButton(context, attrs);

verifyNotNull(view, name);

break;

case “CheckedTextView”:

view = createCheckedTextView(context, attrs);

verifyNotNull(view, name);

break;

case “AutoCompleteTextView”:

view = createAutoCompleteTextView(context, attrs);

verifyNotNull(view, name);

break;

case “MultiAutoCompleteTextView”:

view = createMultiAutoCompleteTextView(context, attrs);

verifyNotNull(view, name);

break;

case “RatingBar”:

view = createRatingBar(context, attrs);

verifyNotNull(view, name);

break;

case “SeekBar”:

view = createSeekBar(context, attrs);

verifyNotNull(view, name);

break;

default:

// The fallback that allows extending class to take over view inflation

// for other tags. Note that we don’t check that the result is not-null.

// That allows the custom inflater path to fall back on the default one

// later in this method.

view = createView(context, name, attrs);

}

if (view == null && originalContext != context) {

// If the original context does not equal our themed context, then we need to manually

// inflate it using the name so that android:theme takes effect.

view = createViewFromTag(context, name, attrs);

}

if (view != null) {

// If we have created a view, check its android:onClick

checkOnClickListener(view, attrs);

}

return view;

}

这边利用了大量的switch case来进行系统控件的创建,例如:TextView

@NonNull

protected AppCompatTextView createTextView(Context context, AttributeSet attrs) {

return new AppCompatTextView(context, attrs);

}

都是new 出来一个具有兼容特性的TextView,返回出去。

但是,使用过switch 的人都知道,这种case形式的分支,无法涵盖所有的类型怎么办呢?这里switch之后,view仍然可能是null.

所以,switch之后,谷歌大佬加了一个if,但是很诡异,这段代码并未进入if,因为 originalContext != context并不满足…具体原因我也没查出来,(;´д`)ゞ

if (view == null && originalContext != context) {

// If the original context does not equal our themed context, then we need to manually

// inflate it using the name so that android:theme takes effect.

view = createViewFromTag(context, name, attrs);

}

然而,这里的补救措施没有执行,那自然有地方有另外的补救措施:

回到之前的LayoutInflater的下面这段代码:

if (mFactory2 != null) {

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值