mirror of
https://github.com/HighCapable/YukiHookAPI.git
synced 2025-09-04 09:45:19 +08:00
Added configuration params in Context.applyTheme in YukiHookFactory and ModuleContextThemeWrapper
This commit is contained in:
@@ -28,6 +28,8 @@
|
|||||||
|
|
||||||
[filename](public/ModuleAppCompatActivity.md ':include')
|
[filename](public/ModuleAppCompatActivity.md ':include')
|
||||||
|
|
||||||
|
[filename](public/ModuleContextThemeWrapper.md ':include')
|
||||||
|
|
||||||
[filename](public/YukiModuleResources.md ':include')
|
[filename](public/YukiModuleResources.md ':include')
|
||||||
|
|
||||||
[filename](public/YukiResources.md ':include')
|
[filename](public/YukiResources.md ':include')
|
||||||
|
31
docs/api/public/ModuleContextThemeWrapper.md
Normal file
31
docs/api/public/ModuleContextThemeWrapper.md
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
## ModuleContextThemeWrapper *- class*
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
class ModuleContextThemeWrapper private constructor(baseContext: Context, theme: Int, configuration: Configuration?) : ContextThemeWrapper
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.93` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 代理 `ContextThemeWrapper`。
|
||||||
|
|
||||||
|
通过包装,你可以轻松在 (Xposed) 宿主环境使用来自模块的主题资源。
|
||||||
|
|
||||||
|
### applyConfiguration *- method*
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun applyConfiguration(initiate: Configuration.() -> Unit): ModuleContextThemeWrapper
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.93` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 设置当前 `ModuleContextThemeWrapper` 的 `Configuration`。
|
||||||
|
|
||||||
|
设置后会自动调用 `Resources.updateConfiguration`。
|
@@ -342,7 +342,7 @@ context.startActivity(context, HostTestActivity::class.java)
|
|||||||
### Context.applyTheme *- ext-method*
|
### Context.applyTheme *- ext-method*
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
fun Context.applyTheme(theme: Int, isUseNewConfig: Boolean): ModuleContextThemeWrapper
|
fun Context.applyTheme(theme: Int, configuration: Configuration?): ModuleContextThemeWrapper
|
||||||
```
|
```
|
||||||
|
|
||||||
**变更记录**
|
**变更记录**
|
||||||
@@ -355,7 +355,7 @@ fun Context.applyTheme(theme: Int, isUseNewConfig: Boolean): ModuleContextThemeW
|
|||||||
|
|
||||||
在 Hook APP (宿主) 中使用此方法会自动调用 `injectModuleAppResources` 注入当前 Xposed 模块的资源。
|
在 Hook APP (宿主) 中使用此方法会自动调用 `injectModuleAppResources` 注入当前 Xposed 模块的资源。
|
||||||
|
|
||||||
如果在 Hook APP (宿主) 中使用此方法发生 `ClassCastException`,请设置 `isUseNewConfig` 为 `true`。
|
如果在 Hook APP (宿主) 中使用此方法发生 `ClassCastException`,请手动设置 `configuration`。
|
||||||
|
|
||||||
为防止资源 ID 互相冲突,你需要在当前 Xposed 模块项目的 `build.gradle` 中修改资源 ID。
|
为防止资源 ID 互相冲突,你需要在当前 Xposed 模块项目的 `build.gradle` 中修改资源 ID。
|
||||||
|
|
||||||
@@ -406,6 +406,33 @@ injectMember {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
你还可以对当前 `Context` 通过 `uiMode` 设置原生的夜间模式和日间模式,至少需要 Android 10 及以上系统版本支持且当前主题包含夜间模式相关元素。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
injectMember {
|
||||||
|
method {
|
||||||
|
name = "onCreate"
|
||||||
|
param(BundleClass)
|
||||||
|
}
|
||||||
|
afterHook {
|
||||||
|
// 定义当前模块中的主题资源
|
||||||
|
var appCompatContext: ModuleContextThemeWrapper
|
||||||
|
// <方案1> 直接得到 Configuration 对象设置
|
||||||
|
appCompatContext = instance<Activity>().applyTheme(R.style.Theme_AppCompat).applyConfiguration { uiMode = Configuration.UI_MODE_NIGHT_YES }
|
||||||
|
// <方案2> 创建一个新的 Configuration 对象,但会破坏当前宿主中原有的字体缩放大小等设置,你需要手动重新传递 densityDpi 等参数
|
||||||
|
appCompatContext = instance<Activity>().applyTheme(R.style.Theme_AppCompat, Configuration().apply { uiMode = Configuration.UI_MODE_NIGHT_YES })
|
||||||
|
// 直接使用这个包装了模块主题后的 Context 创建对话框
|
||||||
|
MaterialAlertDialogBuilder(appCompatContext)
|
||||||
|
.setTitle("AppCompat 主题对话框")
|
||||||
|
.setMessage("我是一个在宿主中显示的 AppCompat 主题对话框。")
|
||||||
|
.setPositiveButton("确定", null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
这样,我们就可以在宿主中非常简单地使用 `MaterialAlertDialogBuilder` 创建对话框了。
|
这样,我们就可以在宿主中非常简单地使用 `MaterialAlertDialogBuilder` 创建对话框了。
|
||||||
|
|
||||||
### ~~isSupportResourcesHook *- field*~~ <!-- {docsify-ignore} -->
|
### ~~isSupportResourcesHook *- field*~~ <!-- {docsify-ignore} -->
|
||||||
|
@@ -156,15 +156,15 @@ fun Context.registerModuleAppActivities(proxy: Any? = null) = AppParasitics.regi
|
|||||||
*
|
*
|
||||||
* 在 Hook APP (宿主) 中使用此方法会自动调用 [injectModuleAppResources] 注入当前 Xposed 模块的资源
|
* 在 Hook APP (宿主) 中使用此方法会自动调用 [injectModuleAppResources] 注入当前 Xposed 模块的资源
|
||||||
*
|
*
|
||||||
* - 如果在 Hook APP (宿主) 中使用此方法发生 [ClassCastException] - 请设置 [isUseNewConfig] 为 true
|
* - 如果在 Hook APP (宿主) 中使用此方法发生 [ClassCastException] - 请手动设置新的 [configuration]
|
||||||
*
|
*
|
||||||
* 详情请参考 [API 文档 - Context.applyTheme](https://fankes.github.io/YukiHookAPI/#/api/document?id=contextapplytheme-ext-method)
|
* 详情请参考 [API 文档 - Context.applyTheme](https://fankes.github.io/YukiHookAPI/#/api/document?id=contextapplytheme-ext-method)
|
||||||
* @param theme 主题资源 ID
|
* @param theme 主题资源 ID
|
||||||
* @param isUseNewConfig 是否使用新的 [Configuration] - 默认否
|
* @param configuration 使用的 [Configuration] - 默认空
|
||||||
* @return [ModuleContextThemeWrapper]
|
* @return [ModuleContextThemeWrapper]
|
||||||
*/
|
*/
|
||||||
fun Context.applyTheme(@StyleRes theme: Int, isUseNewConfig: Boolean = false) =
|
fun Context.applyTheme(@StyleRes theme: Int, configuration: Configuration? = null) =
|
||||||
ModuleContextThemeWrapper.wrapper(baseContext = this, theme, isUseNewConfig)
|
ModuleContextThemeWrapper.wrapper(baseContext = this, theme, configuration)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 仅判断模块是否在太极、无极中激活
|
* 仅判断模块是否在太极、无极中激活
|
||||||
|
@@ -26,6 +26,8 @@
|
|||||||
* This file is Created by fankes on 2022/8/15.
|
* This file is Created by fankes on 2022/8/15.
|
||||||
* Thanks for providing https://github.com/cinit/QAuxiliary/blob/main/app/src/main/java/io/github/qauxv/ui/CommonContextWrapper.java
|
* Thanks for providing https://github.com/cinit/QAuxiliary/blob/main/app/src/main/java/io/github/qauxv/ui/CommonContextWrapper.java
|
||||||
*/
|
*/
|
||||||
|
@file:Suppress("unused", "DEPRECATION")
|
||||||
|
|
||||||
package com.highcapable.yukihookapi.hook.xposed.parasitic.context.wrapper
|
package com.highcapable.yukihookapi.hook.xposed.parasitic.context.wrapper
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
@@ -42,9 +44,9 @@ import com.highcapable.yukihookapi.hook.xposed.parasitic.reference.ModuleClassLo
|
|||||||
* 通过包装 - 你可以轻松在 (Xposed) 宿主环境使用来自模块的主题资源
|
* 通过包装 - 你可以轻松在 (Xposed) 宿主环境使用来自模块的主题资源
|
||||||
* @param baseContext 原始 [Context]
|
* @param baseContext 原始 [Context]
|
||||||
* @param theme 使用的主题
|
* @param theme 使用的主题
|
||||||
* @param isUseNewConfig 是否使用新的 [Configuration]
|
* @param configuration 使用的 [Configuration]
|
||||||
*/
|
*/
|
||||||
class ModuleContextThemeWrapper private constructor(baseContext: Context, theme: Int, isUseNewConfig: Boolean) :
|
class ModuleContextThemeWrapper private constructor(baseContext: Context, theme: Int, configuration: Configuration?) :
|
||||||
ContextThemeWrapper(baseContext, theme) {
|
ContextThemeWrapper(baseContext, theme) {
|
||||||
|
|
||||||
internal companion object {
|
internal companion object {
|
||||||
@@ -53,13 +55,13 @@ class ModuleContextThemeWrapper private constructor(baseContext: Context, theme:
|
|||||||
* 从 [Context] 创建 [ModuleContextThemeWrapper]
|
* 从 [Context] 创建 [ModuleContextThemeWrapper]
|
||||||
* @param baseContext 对接的 [Context]
|
* @param baseContext 对接的 [Context]
|
||||||
* @param theme 需要使用的主题
|
* @param theme 需要使用的主题
|
||||||
* @param isUseNewConfig 是否使用新的 [Configuration]
|
* @param configuration 使用的 [Configuration]
|
||||||
* @return [ModuleContextThemeWrapper]
|
* @return [ModuleContextThemeWrapper]
|
||||||
* @throws IllegalStateException 如果重复装载
|
* @throws IllegalStateException 如果重复装载
|
||||||
*/
|
*/
|
||||||
internal fun wrapper(baseContext: Context, theme: Int, isUseNewConfig: Boolean) =
|
internal fun wrapper(baseContext: Context, theme: Int, configuration: Configuration?) =
|
||||||
if (baseContext !is ModuleContextThemeWrapper)
|
if (baseContext !is ModuleContextThemeWrapper)
|
||||||
ModuleContextThemeWrapper(baseContext, theme, isUseNewConfig)
|
ModuleContextThemeWrapper(baseContext, theme, configuration)
|
||||||
else error("ModuleContextThemeWrapper already loaded")
|
else error("ModuleContextThemeWrapper already loaded")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,11 +69,26 @@ class ModuleContextThemeWrapper private constructor(baseContext: Context, theme:
|
|||||||
private var baseResources: Resources? = null
|
private var baseResources: Resources? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (isUseNewConfig && baseContext.resources?.configuration != null)
|
configuration?.also {
|
||||||
baseResources = baseContext.createConfigurationContext(baseContext.resources.configuration)?.resources
|
baseResources = baseContext.createConfigurationContext(it)?.resources
|
||||||
|
baseResources?.updateConfiguration(it, baseContext.resources.displayMetrics)
|
||||||
|
}
|
||||||
if (YukiHookBridge.hasXposedBridge) resources?.injectModuleAppResources()
|
if (YukiHookBridge.hasXposedBridge) resources?.injectModuleAppResources()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置当前 [ModuleContextThemeWrapper] 的 [Configuration]
|
||||||
|
*
|
||||||
|
* 设置后会自动调用 [Resources.updateConfiguration]
|
||||||
|
* @param initiate [Configuration] 方法体
|
||||||
|
* @return [ModuleContextThemeWrapper]
|
||||||
|
*/
|
||||||
|
fun applyConfiguration(initiate: Configuration.() -> Unit): ModuleContextThemeWrapper {
|
||||||
|
resources?.configuration?.apply(initiate)
|
||||||
|
resources?.updateConfiguration(resources?.configuration, resources?.displayMetrics)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
override fun getClassLoader(): ClassLoader = ModuleClassLoader.instance()
|
override fun getClassLoader(): ClassLoader = ModuleClassLoader.instance()
|
||||||
|
|
||||||
override fun getResources(): Resources? = baseResources ?: super.getResources()
|
override fun getResources(): Resources? = baseResources ?: super.getResources()
|
||||||
|
Reference in New Issue
Block a user