├── .github
├── dependabot.yml
└── workflows
│ └── android.yml
├── .gitignore
├── .idea
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
└── icon.png
├── LICENSE
├── Pic
├── MiuiHome.png
├── Screenshot_EN.png
└── Screenshot_ZH.png
├── README.md
├── README_EN.md
├── app
├── .gitignore
├── build.gradle.kts
├── dict.txt
├── proguard-log.pro
├── proguard-rules.pro
└── src
│ ├── .gitignore
│ └── main
│ ├── AndroidManifest.xml
│ ├── assets
│ └── xposed_init
│ ├── kotlin
│ └── com
│ │ ├── yuk
│ │ └── miuihome
│ │ │ ├── CrashRecord.kt
│ │ │ ├── XposedInit.kt
│ │ │ ├── module
│ │ │ ├── AllowAllAppsToUseSmallWindow.kt
│ │ │ ├── AllowWidgetToMinus.kt
│ │ │ ├── AlwaysBlurWallpaper.kt
│ │ │ ├── AlwaysShowMIUIWidget.kt
│ │ │ ├── BaseClassAndMethodCheck.kt
│ │ │ ├── BuildWithEverything.kt
│ │ │ ├── DisableLog.kt
│ │ │ ├── DisableRecentsViewWallpaperDarken.kt
│ │ │ ├── DisableRecommendServer.kt
│ │ │ ├── DoubleTapController.kt
│ │ │ ├── EnableAllAppsContainerViewBlur.kt
│ │ │ ├── EnableBlurWhenOpenFolder.kt
│ │ │ ├── EnableClockGadget.kt
│ │ │ ├── EnableDockIconShadow.kt
│ │ │ ├── EnableFolderIconBlur.kt
│ │ │ ├── EnableHideStatusBarWhenEnterRecents.kt
│ │ │ ├── EnableLowEndDeviceUseMIUIWidgets.kt
│ │ │ ├── EnableMamlDownload.kt
│ │ │ ├── EnableRecentsViewHorizontal.kt
│ │ │ ├── EnableSimpleAnimation.kt
│ │ │ ├── EnableSmoothAnimation.kt
│ │ │ ├── HookSystemProperties.kt
│ │ │ ├── ModifyAnimDurationRatio.kt
│ │ │ ├── ModifyAppReturnBlur.kt
│ │ │ ├── ModifyBlurLevel.kt
│ │ │ ├── ModifyBlurRadius.kt
│ │ │ ├── ModifyCategory.kt
│ │ │ ├── ModifyCloseFolderOnLaunch.kt
│ │ │ ├── ModifyDockHook.kt
│ │ │ ├── ModifyDoubleTapToSleep.kt
│ │ │ ├── ModifyFolderColumnsCount.kt
│ │ │ ├── ModifyHideSeekPoints.kt
│ │ │ ├── ModifyHideWidgetTitles.kt
│ │ │ ├── ModifyIconTitleFontColor.kt
│ │ │ ├── ModifyIconTitleFontSize.kt
│ │ │ ├── ModifyIconTitleTopMargin.kt
│ │ │ ├── ModifyInfiniteScroll.kt
│ │ │ ├── ModifyPadA12DockBlur.kt
│ │ │ ├── ModifyRecents.kt
│ │ │ ├── ModifyShortcutItemCount.kt
│ │ │ ├── ModifyShowDockIconTitles.kt
│ │ │ ├── ModifyTaskHorizontal.kt
│ │ │ ├── ModifyTaskVertical.kt
│ │ │ ├── ModifyUnlockHotseatIcon.kt
│ │ │ ├── ResourcesHook.kt
│ │ │ └── SetDeviceLevel.kt
│ │ │ ├── utils
│ │ │ ├── Config.kt
│ │ │ ├── OwnSP.kt
│ │ │ ├── ResourcesHookData.kt
│ │ │ ├── ResourcesHookMap.kt
│ │ │ ├── SPBackup.kt
│ │ │ ├── ViewBuilder.kt
│ │ │ └── ktx
│ │ │ │ ├── AppUtil.kt
│ │ │ │ └── KotlinXposedHelper.kt
│ │ │ └── view
│ │ │ ├── CustomDialog.kt
│ │ │ ├── CustomSwitch.kt
│ │ │ ├── HookSettingsActivity.kt
│ │ │ ├── adapter
│ │ │ ├── ItemAdapter.kt
│ │ │ └── ListPopupWindowAdapter.kt
│ │ │ ├── base
│ │ │ ├── BaseView.kt
│ │ │ ├── LineV.kt
│ │ │ ├── LinearContainerV.kt
│ │ │ ├── SubtitleV.kt
│ │ │ ├── TextV.kt
│ │ │ ├── TextWithArrowV.kt
│ │ │ ├── TextWithSeekBarV.kt
│ │ │ ├── TextWithSpinnerV.kt
│ │ │ ├── TextWithSummaryV.kt
│ │ │ └── TextWithSwitchV.kt
│ │ │ └── data
│ │ │ ├── DataHelper.kt
│ │ │ ├── Item.kt
│ │ │ ├── LayoutPair.kt
│ │ │ └── Padding.kt
│ │ └── zhenxiang
│ │ └── blur
│ │ ├── BackgroundBlurDrawableExtensions.kt
│ │ ├── SystemBlurController.kt
│ │ ├── ViewExtensions.kt
│ │ ├── WindowBlurFrameLayout.kt
│ │ ├── WindowBlurLinearLayout.kt
│ │ └── model
│ │ └── CornerRadius.kt
│ └── res
│ ├── drawable
│ ├── button_left_background.xml
│ ├── button_left_background_no_pressed.xml
│ ├── button_left_background_pressed.xml
│ ├── button_right_background.xml
│ ├── button_right_background_no_pressed.xml
│ ├── button_right_background_pressed.xml
│ ├── dialog_background.xml
│ ├── dialog_pad_background.xml
│ ├── edit_view_background.xml
│ ├── ic_action_back.xml
│ ├── ic_click_check.xml
│ ├── ic_launcher.xml
│ ├── ic_launcher_background.xml
│ ├── ic_launcher_foreground.xml
│ ├── ic_main_bg.xml
│ ├── ic_main_down_bg.xml
│ ├── ic_popup_select.xml
│ ├── ic_right_arrow.xml
│ ├── ic_up_down.xml
│ ├── rounded_corners_pop.xml
│ ├── seekbar_progress_drawable.xml
│ ├── switch_thumb.xml
│ └── switch_track.xml
│ ├── layout
│ ├── dialog_layout.xml
│ ├── dialog_pad_layout.xml
│ ├── item.xml
│ └── settings_activity.xml
│ ├── values-af
│ └── strings.xml
│ ├── values-ar-rSA
│ └── strings.xml
│ ├── values-ar
│ └── strings.xml
│ ├── values-ca
│ └── strings.xml
│ ├── values-cs
│ └── strings.xml
│ ├── values-da
│ └── strings.xml
│ ├── values-de
│ └── strings.xml
│ ├── values-el
│ └── strings.xml
│ ├── values-en
│ └── strings.xml
│ ├── values-es-rES
│ └── strings.xml
│ ├── values-es
│ └── strings.xml
│ ├── values-fa
│ └── strings.xml
│ ├── values-fi
│ └── strings.xml
│ ├── values-fr
│ └── strings.xml
│ ├── values-he
│ └── strings.xml
│ ├── values-hi
│ └── strings.xml
│ ├── values-hu
│ └── strings.xml
│ ├── values-in
│ └── strings.xml
│ ├── values-it
│ └── strings.xml
│ ├── values-ja
│ └── strings.xml
│ ├── values-ka-rGE
│ └── strings.xml
│ ├── values-ka
│ └── strings.xml
│ ├── values-ko
│ └── strings.xml
│ ├── values-ml-rIN
│ └── strings.xml
│ ├── values-night
│ └── colors.xml
│ ├── values-nl
│ └── strings.xml
│ ├── values-no
│ └── strings.xml
│ ├── values-pl
│ └── strings.xml
│ ├── values-pt-rBR
│ └── strings.xml
│ ├── values-pt
│ └── strings.xml
│ ├── values-ro
│ └── strings.xml
│ ├── values-ru-rRU
│ └── strings.xml
│ ├── values-sr
│ └── strings.xml
│ ├── values-sv
│ └── strings.xml
│ ├── values-th
│ └── strings.xml
│ ├── values-tr
│ └── strings.xml
│ ├── values-uk
│ └── strings.xml
│ ├── values-ur-rPK
│ └── strings.xml
│ ├── values-ur
│ └── strings.xml
│ ├── values-uz-rUZ
│ └── strings.xml
│ ├── values-vi-rVN
│ └── strings.xml
│ ├── values-zh-rCN
│ └── strings.xml
│ ├── values-zh-rHK
│ └── strings.xml
│ ├── values-zh-rTW
│ └── strings.xml
│ └── values
│ ├── array.xml
│ ├── colors.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle.kts
├── crowdin.yml
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── hidden-api
├── .gitignore
├── build.gradle.kts
├── proguard-rules.pro
└── src
│ └── main
│ └── java
│ ├── android
│ └── view
│ │ └── ViewRootImpl.java
│ └── com
│ └── android
│ └── internal
│ └── graphics
│ └── drawable
│ └── BackgroundBlurDrawable.java
└── settings.gradle.kts
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: gradle
4 | directory: "/"
5 | schedule:
6 | interval: daily
7 | target-branch: main
8 |
--------------------------------------------------------------------------------
/.github/workflows/android.yml:
--------------------------------------------------------------------------------
1 | name: Android CI
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 | paths-ignore:
7 | - 'README.md'
8 | - 'README_EN.md'
9 |
10 | jobs:
11 | build:
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | - uses: actions/checkout@v2
16 | - name: Setup JDK 11
17 | uses: actions/setup-java@v1
18 | with:
19 | java-version: 11
20 |
21 | - uses: actions/cache@v2
22 | with:
23 | path: |
24 | ~/.gradle/caches
25 | ~/.gradle/wrapper
26 | !~/.gradle/caches/build-cache-*
27 | key: gradle-deps-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
28 | restore-keys: gradle-deps
29 |
30 | - uses: actions/cache@v2
31 | with:
32 | path: |
33 | ~/.gradle/caches/build-cache-*
34 | key: gradle-builds-${{ github.sha }}
35 |
36 | - name: Build with Gradle
37 | run: |
38 | echo ${{ secrets.SIGNING_KEY }} | base64 -d > keystore.jks
39 | bash ./gradlew assemble
40 | env:
41 | KEYSTORE_PATH: "../keystore.jks"
42 | KEYSTORE_PASS: ${{ secrets.KEY_STORE_PASSWORD }}
43 | KEY_ALIAS: ${{ secrets.ALIAS }}
44 | KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
45 |
46 | - name: Upload Release APK
47 | uses: actions/upload-artifact@v2
48 | with:
49 | name: MiuiHome_Release
50 | path: "app/build/outputs/apk/release/*.apk"
51 |
52 | - name: Upload Debug APK
53 | uses: actions/upload-artifact@v2
54 | with:
55 | name: MiuiHome_Debug
56 | path: "app/build/outputs/apk/debug/*.apk"
57 |
58 | - name: Find apk
59 | run: |
60 | echo "RELEASE=$(find 'app/build/outputs/apk/release' -name '*.apk')" >> $GITHUB_ENV
61 | echo "DEBUG=$(find 'app/build/outputs/apk/debug' -name '*.apk')" >> $GITHUB_ENV
62 |
63 | - name: Post to channel
64 | if: contains(github.event.head_commit.message, '[skip post]') == false
65 | env:
66 | CHANNEL_ID: ${{ secrets.CHANNEL_ID }}
67 | BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
68 | RELEASE: ${{ env.RELEASE }}
69 | DEBUG: ${{ env.DEBUG }}
70 | COMMIT_MESSAGE: |+
71 | New push in Github\!
72 | ```
73 | ${{ github.event.head_commit.message }}
74 | ```
75 | run: |
76 | ESCAPED=`python3 -c 'import json,os,urllib.parse; print(urllib.parse.quote(json.dumps(os.environ["COMMIT_MESSAGE"])))'`
77 | curl -v "https://api.telegram.org/bot${BOT_TOKEN}/sendMediaGroup?chat_id=${CHANNEL_ID}&media=%5B%7B%22type%22%3A%22document%22%2C%20%22media%22%3A%22attach%3A%2F%2Frelease%22%7D%2C%7B%22type%22%3A%22document%22%2C%20%22media%22%3A%22attach%3A%2F%2Fdebug%22%2C%22parse_mode%22%3A%22MarkdownV2%22%2C%22caption%22%3A${ESCAPED}%7D%5D" -F release="@$RELEASE" -F debug="@$DEBUG"
78 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 | *.aab
5 |
6 | # Files for the ART/Dalvik VM
7 | *.dex
8 |
9 | # Java class files
10 | *.class
11 |
12 | # Generated files
13 | bin/
14 | gen/
15 | out/
16 |
17 | # Gradle files
18 | .gradle/
19 | build/
20 |
21 | # Local configuration file (sdk path, etc)
22 | local.properties
23 |
24 | # Proguard folder generated by Eclipse
25 | proguard/
26 |
27 | # Log Files
28 | *.log
29 |
30 | # Android Studio Navigation editor temp files
31 | .navigation/
32 |
33 | # Android Studio captures folder
34 | captures/
35 |
36 | # IntelliJ
37 | *.iml
38 | .idea/
39 |
40 | # Keystore files
41 | # Uncomment the following lines if you do not want to check your keystore files in.
42 | #*.jks
43 | #*.keystore
44 |
45 | # External native build folder generated in Android Studio 2.2 and later
46 | .externalNativeBuild
47 |
48 | # Google Services (e.g. APIs or Firebase)
49 | google-services.json
50 |
51 | # Freeline
52 | freeline.py
53 | freeline/
54 | freeline_project_description.json
55 |
56 | # fastlane
57 | fastlane/report.xml
58 | fastlane/Preview.html
59 | fastlane/screenshots
60 | fastlane/test_output
61 | fastlane/readme.md
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qqlittleice/MiuiHome/3da7a684ca28b3b0aea0cfd401d6eb8ea3ebf0f8/.idea/icon.png
--------------------------------------------------------------------------------
/Pic/MiuiHome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qqlittleice/MiuiHome/3da7a684ca28b3b0aea0cfd401d6eb8ea3ebf0f8/Pic/MiuiHome.png
--------------------------------------------------------------------------------
/Pic/Screenshot_EN.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qqlittleice/MiuiHome/3da7a684ca28b3b0aea0cfd401d6eb8ea3ebf0f8/Pic/Screenshot_EN.png
--------------------------------------------------------------------------------
/Pic/Screenshot_ZH.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qqlittleice/MiuiHome/3da7a684ca28b3b0aea0cfd401d6eb8ea3ebf0f8/Pic/Screenshot_ZH.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
MiuiHome
4 |
5 | 针对 Miui 桌面的自定义扩展 - Xposed
6 |
7 | [English](https://github.com/qqlittleice/MiuiHome/blob/main/README_EN.md) 丨 简体中文
8 |
9 | 
10 |
11 |
12 | [](https://github.com/qqlittleice/MiuiHome/actions/workflows/android.yml)
13 | [](https://github.com/Xposed-Modules-Repo/com.yuk.miuihome/releases)
14 | [](https://crowdin.com/project/miuihome_xposed)
15 | [](https://github.com/Xposed-Modules-Repo/com.yuk.miuihome/releases/latest)
16 | [](https://t.me/MiuiHome_Xposed)
17 |
18 |
19 | -----
20 |
21 | ## 如何使用
22 |
23 | __在 LSPosed 管理器中激活本模块,重启系统桌面,打开桌面设置,点击"模块设置"即可.__
24 |
25 | ## 贡献翻译
26 |
27 | [Crowdin](https://zh.crowdin.com/project/miuihome_xposed)
28 |
29 | ## 引用库
30 |
31 |
32 |
33 | - [AndroidHiddenApiBypass](https://github.com/LSPosed/AndroidHiddenApiBypass)
34 | - [AndroidSystemBlur](https://github.com/Lucchetto/AndroidSystemBlur)
35 | - [androidx](https://android.googlesource.com/platform/frameworks/support)
36 | - [AppCenter](https://github.com/microsoft/appcenter)
37 | - [BiliRoaming](https://github.com/yujincheng08/BiliRoaming)
38 | - [blockmiui](https://github.com/577fkj/blockmiui)
39 | - [CustoMIUIzer](https://code.highspec.ru/Mikanoshi/CustoMIUIzer)
40 | - [FuckCoolapk](https://github.com/ejiaogl/FuckCoolapk)
41 | - [LSPosed](https://github.com/LSPosed/LSPosed)
42 | - [MIDock](https://github.com/lamprose/MIDock)
43 | - [MIUIDock](https://github.com/ouhoukyo/MIUIDock)
44 | - [MIUltra](https://github.com/lamprose/MIUltra)
45 | - [QNotified](https://github.com/ferredoxin/QNotified)
46 | - [XposedBridge](https://github.com/rovo89/XposedBridge)
47 | - [EzXHelper](https://github.com/KyuubiRan/EzXHelper)
48 |
49 |
50 | ## 屏幕截图
51 |
52 | 
53 |
54 | ## 许可证
55 |
56 | [GNU General Public License v3.0](LICENSE)
57 |
58 | ## Star 数量统计
59 |
60 | [](https://starchart.cc/qqlittleice/MiuiHome)
61 |
--------------------------------------------------------------------------------
/README_EN.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
MiuiHome
4 |
5 | Hook for MIUI Launcher - Xposed
6 |
7 | English 丨 [简体中文](https://github.com/qqlittleice/MiuiHome/blob/main/README.md)
8 |
9 | 
10 |
11 |
12 | [](https://github.com/qqlittleice/MiuiHome/actions/workflows/android.yml)
13 | [](https://github.com/Xposed-Modules-Repo/com.yuk.miuihome/releases)
14 | [](https://crowdin.com/project/miuihome_xposed)
15 | [](https://github.com/Xposed-Modules-Repo/com.yuk.miuihome/releases/latest)
16 | [](https://t.me/MiuiHome_Xposed)
17 |
18 |
19 | -----
20 |
21 | ## How to use
22 |
23 | __Activating this module in LSPosed Manager, restart Miui Launcher once, open Miui Launcher settings, and click on "Module Settings".__
24 |
25 | ## Translation Contributions
26 |
27 | [Crowdin](https://crowdin.com/project/miuihome_xposed)
28 |
29 | ## Credits
30 |
31 |
32 |
33 | - [AndroidHiddenApiBypass](https://github.com/LSPosed/AndroidHiddenApiBypass)
34 | - [AndroidSystemBlur](https://github.com/Lucchetto/AndroidSystemBlur)
35 | - [androidx](https://android.googlesource.com/platform/frameworks/support)
36 | - [AppCenter](https://github.com/microsoft/appcenter)
37 | - [BiliRoaming](https://github.com/yujincheng08/BiliRoaming)
38 | - [blockmiui](https://github.com/577fkj/blockmiui)
39 | - [CustoMIUIzer](https://code.highspec.ru/Mikanoshi/CustoMIUIzer)
40 | - [FuckCoolapk](https://github.com/ejiaogl/FuckCoolapk)
41 | - [LSPosed](https://github.com/LSPosed/LSPosed)
42 | - [MIDock](https://github.com/lamprose/MIDock)
43 | - [MIUIDock](https://github.com/ouhoukyo/MIUIDock)
44 | - [MIUltra](https://github.com/lamprose/MIUltra)
45 | - [QNotified](https://github.com/ferredoxin/QNotified)
46 | - [XposedBridge](https://github.com/rovo89/XposedBridge)
47 | - [EzXHelper](https://github.com/KyuubiRan/EzXHelper)
48 |
49 |
50 | ## Screenshot
51 |
52 | 
53 |
54 | ## License
55 |
56 | [GNU General Public License v3.0](LICENSE)
57 |
58 | ## Stargazers over time
59 |
60 | [](https://starchart.cc/qqlittleice/MiuiHome)
61 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /release
3 | /debug
4 | /noResHook
--------------------------------------------------------------------------------
/app/build.gradle.kts:
--------------------------------------------------------------------------------
1 | import com.android.build.gradle.internal.api.BaseVariantOutputImpl
2 | import java.util.Properties
3 |
4 | plugins {
5 | id("com.android.application")
6 | id("org.jetbrains.kotlin.android")
7 | }
8 |
9 | android {
10 | compileSdk = 33
11 | buildToolsVersion = "33.0.0"
12 | namespace = "com.yuk.miuihome"
13 | defaultConfig {
14 | applicationId = "com.yuk.miuihome"
15 | minSdk = 29
16 | targetSdk = 33
17 | versionCode = 4311
18 | versionName = "4.3.1" + (getGitHeadRefsSuffix(rootProject))
19 | }
20 | val properties = Properties()
21 | runCatching {
22 | properties.load(project.rootProject.file("local.properties").inputStream())
23 | }
24 | val keystorePath = properties.getProperty("KEYSTORE_PATH") ?: System.getenv("KEYSTORE_PATH")
25 | val keystorePwd = properties.getProperty("KEYSTORE_PASS") ?: System.getenv("KEYSTORE_PASS")
26 | val alias = properties.getProperty("KEY_ALIAS") ?: System.getenv("KEY_ALIAS")
27 | val pwd = properties.getProperty("KEY_PASSWORD") ?: System.getenv("KEY_PASSWORD")
28 | if (keystorePath != null) {
29 | signingConfigs {
30 | create("release") {
31 | storeFile = file(keystorePath)
32 | storePassword = keystorePwd
33 | keyAlias = alias
34 | keyPassword = pwd
35 | enableV3Signing = true
36 | }
37 | }
38 | }
39 | buildTypes {
40 | release {
41 | isMinifyEnabled = true
42 | isShrinkResources = true
43 | setProguardFiles(listOf("proguard-rules.pro", "proguard-log.pro"))
44 | if (keystorePath != null) {
45 | signingConfig = signingConfigs.getByName("release")
46 | }
47 | }
48 | debug {
49 | if (keystorePath != null) {
50 | signingConfig = signingConfigs.getByName("release")
51 | }
52 | }
53 | }
54 | compileOptions {
55 | sourceCompatibility = JavaVersion.VERSION_11
56 | targetCompatibility = JavaVersion.VERSION_11
57 | }
58 | kotlinOptions {
59 | jvmTarget = JavaVersion.VERSION_11.majorVersion
60 | }
61 | packagingOptions {
62 | resources {
63 | excludes += "/META-INF/**"
64 | excludes += "/kotlin/**"
65 | excludes += "/okhttp3/**"
66 | excludes += "/*.txt"
67 | excludes += "/*.bin"
68 | excludes += "/*.json"
69 | }
70 | dex {
71 | useLegacyPackaging = true
72 | }
73 | applicationVariants.all {
74 | outputs.all {
75 | (this as BaseVariantOutputImpl).outputFileName = "MiuiHome-$versionName($versionCode)-$name.apk"
76 | }
77 | }
78 | }
79 | androidResources.additionalParameters("--allow-reserved-package-id", "--package-id", "0x64")
80 | }
81 |
82 | fun getGitHeadRefsSuffix(project: Project): String {
83 | // .git/HEAD描述当前目录所指向的分支信息,内容示例:"ref: refs/heads/master\n"
84 | val headFile = File(project.rootProject.projectDir, ".git" + File.separator + "HEAD")
85 | if (headFile.exists()) {
86 | val string: String = headFile.readText(Charsets.UTF_8)
87 | val string1 = string.replace(Regex("""ref:|\s"""), "")
88 | val result = if (string1.isNotBlank() && string1.contains('/')) {
89 | val refFilePath = ".git" + File.separator + string1
90 | // 根据HEAD读取当前指向的hash值,路径示例为:".git/refs/heads/master"
91 | val refFile = File(project.rootProject.projectDir, refFilePath)
92 | // 索引文件内容为hash值+"\n",
93 | // 示例:"90312cd9157587d11779ed7be776e3220050b308\n"
94 | refFile.readText(Charsets.UTF_8).replace(Regex("""\s"""), "").subSequence(0, 7)
95 | } else {
96 | string.substring(0, 7)
97 | }
98 | println("commit_id: $result")
99 | return ".$result"
100 | } else {
101 | println("WARN: .git/HEAD does NOT exist")
102 | return ""
103 | }
104 | }
105 |
106 | dependencies {
107 | compileOnly(project(":hidden-api"))
108 | // Xposed
109 | compileOnly("de.robv.android.xposed:api:82")
110 | // EzXHelper
111 | implementation("com.github.kyuubiran:EzXHelper:1.0.3")
112 | // HiddenApiByPass
113 | implementation("org.lsposed.hiddenapibypass:hiddenapibypass:4.3")
114 | // Recyclerview
115 | implementation("androidx.recyclerview:recyclerview:1.3.0-alpha02")
116 | }
117 |
--------------------------------------------------------------------------------
/app/proguard-log.pro:
--------------------------------------------------------------------------------
1 | ##########################################################################################################
2 | # 作者:Sollyu
3 | # 日期:2020-11-02
4 | # 内容:发布版本移除日志,kotlin编译时带的而外信息,增强反调试难度
5 | # 使用:proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro', 'proguard-log.pro'
6 | ##########################################################################################################
7 |
8 | ##########################################################################################################
9 | # 删除安卓日志
10 | -assumenosideeffects class android.util.Log {
11 | public static *** d(...);
12 | public static *** v(...);
13 | public static *** w(...);
14 | public static *** e(...);
15 | }
16 |
17 | ##########################################################################################################
18 | # 删除Kotlin编译时可能生成显示变量的方法
19 | -assumenosideeffects class kotlin.jvm.internal.Intrinsics {
20 | public static void checkExpressionValueIsNotNull(java.lang.Object, java.lang.String);
21 | public static void checkFieldIsNotNull(java.lang.Object, java.lang.String);
22 | public static void checkFieldIsNotNull(java.lang.Object, java.lang.String, java.lang.String);
23 | public static void checkNotNull(java.lang.Object);
24 | public static void checkNotNull(java.lang.Object, java.lang.String);
25 | public static void checkNotNullExpressionValue(java.lang.Object, java.lang.String);
26 | public static void checkNotNullParameter(java.lang.Object, java.lang.String);
27 | public static void checkParameterIsNotNull(java.lang.Object, java.lang.String);
28 | public static void checkReturnedValueIsNotNull(java.lang.Object, java.lang.String);
29 | public static void throwUninitializedPropertyAccessException(java.lang.String);
30 | }
31 |
32 | ##########################################################################################################
33 | # 会暴露变量名称
34 | -assumenosideeffects class java.util.Objects {
35 | public static java.lang.Object requireNonNull(java.lang.Object, java.lang.String);
36 | }
37 |
38 | ##########################################################################################################
39 | # 删除slf4j的日志输出
40 | -assumenosideeffects interface org.slf4j.Logger {
41 | public void trace(...);
42 | public void debug(...);
43 | public void info(...);
44 | public void warn(...);
45 | public void error(...);
46 |
47 | public boolean isTraceEnabled(...);
48 | public boolean isDebugEnabled(...);
49 | public boolean isWarnEnabled(...);
50 | }
51 |
52 | -assumenosideeffects class org.slf4j.LoggerFactory {
53 | public static ** getLogger(...);
54 | }
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
23 | -repackageclasses "余空"
24 | -obfuscationdictionary dict.txt
25 | -classobfuscationdictionary dict.txt
26 | -packageobfuscationdictionary dict.txt
27 |
28 | -keep public class * extends android.app.Activity
29 |
30 | -keep class com.yuk.miuihome.XposedInit {
31 | ();
32 | }
33 |
34 | -assumenosideeffects class kotlin.jvm.internal.Intrinsics {
35 | public static void check*(...);
36 | public static void throw*(...);
37 | }
38 |
39 | -allowaccessmodification
40 | -overloadaggressively
--------------------------------------------------------------------------------
/app/src/.gitignore:
--------------------------------------------------------------------------------
1 | /androidTest
2 | /test
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
11 |
14 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/assets/xposed_init:
--------------------------------------------------------------------------------
1 | com.yuk.miuihome.XposedInit
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/CrashRecord.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.Context
5 | import com.yuk.miuihome.utils.Config
6 | import de.robv.android.xposed.XposedBridge
7 |
8 | @SuppressLint("StaticFieldLeak")
9 | object CrashRecord : Thread.UncaughtExceptionHandler {
10 |
11 | private var mDefaultHandler: Thread.UncaughtExceptionHandler? = null
12 | private var mContext: Context? = null
13 |
14 | fun init(context: Context) {
15 | mContext = context
16 | mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler()
17 | Thread.setDefaultUncaughtExceptionHandler(this)
18 | if (BuildConfig.DEBUG) XposedBridge.log("MiuiHome: CrashRecord Loaded")
19 | }
20 |
21 | override fun uncaughtException(p0: Thread, p1: Throwable) {
22 | XposedBridge.log("MiuiHome: Crash happened")
23 | mContext?.let {
24 | val pref = it.createDeviceProtectedStorageContext().getSharedPreferences("Crash_Handler", Context.MODE_PRIVATE)
25 | if (BuildConfig.DEBUG) {
26 | XposedBridge.log("${System.currentTimeMillis()}")
27 | XposedBridge.log("${pref.getLong("last_time", 0L)}")
28 | XposedBridge.log("${System.currentTimeMillis() - pref.getLong("last_time", 0L)}")
29 | }
30 | if (System.currentTimeMillis() - pref.getLong("last_time", 0L) < 60 * 1000L) {
31 | XposedBridge.log("MiuiHome: Crash happened again in one minute")
32 | if (pref.getInt("times", 0) >= 3) {
33 | it.createDeviceProtectedStorageContext().getSharedPreferences(Config.SP_NAME, Context.MODE_PRIVATE).edit().apply {
34 | clear()
35 | apply()
36 | }
37 | XposedBridge.log("MiuiHome: More than three times, clear MODULE_CONFIG")
38 | pref.edit().putInt("times", 0).apply()
39 | }
40 | pref.edit().putInt("times", pref.getInt("times", 0) + 1).apply()
41 | }
42 | pref.edit().putLong("last_time", System.currentTimeMillis()).apply()
43 | Thread.sleep(500)
44 | }
45 | mDefaultHandler?.uncaughtException(p0, p1)
46 | }
47 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/AllowAllAppsToUseSmallWindow.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.content.Context
4 | import com.yuk.miuihome.utils.OwnSP
5 | import com.yuk.miuihome.utils.ktx.hookBeforeMethod
6 |
7 | class AllowAllAppsToUseSmallWindow {
8 |
9 | fun init() {
10 | if (!OwnSP.ownSP.getBoolean("supportSmallWindow", false)) return
11 | "com.miui.home.launcher.RecentsAndFSGestureUtils".hookBeforeMethod(
12 | "isTaskSupportSmallWindow",
13 | Context::class.java,
14 | Int::class.javaPrimitiveType
15 | ) {
16 | it.result = true
17 | }
18 | "com.miui.home.launcher.RecentsAndFSGestureUtils".hookBeforeMethod(
19 | "isPkgSupportSmallWindow",
20 | Context::class.java,
21 | String::class.java
22 | ) {
23 | it.result = true
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/AllowWidgetToMinus.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import com.yuk.miuihome.utils.OwnSP
4 | import com.yuk.miuihome.utils.ktx.callMethod
5 | import com.yuk.miuihome.utils.ktx.getObjectField
6 | import com.yuk.miuihome.utils.ktx.hookBeforeMethod
7 | import com.yuk.miuihome.utils.ktx.setBooleanField
8 |
9 | class AllowWidgetToMinus {
10 |
11 | fun init() {
12 | if (!OwnSP.ownSP.getBoolean("widgetToMinus", false)) return
13 | "com.miui.home.launcher.Workspace".hookBeforeMethod("canDragToPa") {
14 | val currentDragObject = it.thisObject.getObjectField("mDragController")?.callMethod("getCurrentDragObject")
15 | val dragInfo = currentDragObject?.callMethod("getDragInfo")
16 | dragInfo?.setBooleanField("isMIUIWidget", true)
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/AlwaysBlurWallpaper.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.view.Window
4 | import com.yuk.miuihome.utils.OwnSP
5 | import com.yuk.miuihome.utils.ktx.hookBeforeMethod
6 |
7 | class AlwaysBlurWallpaper {
8 |
9 | fun init() {
10 | if (!OwnSP.ownSP.getBoolean("alwaysBlur", false) || OwnSP.ownSP.getBoolean("simpleAnimation", false)) return
11 | val value = OwnSP.ownSP.getFloat("blurRadius", 1f)
12 | "com.miui.home.launcher.common.BlurUtils".hookBeforeMethod("fastBlur", Float::class.java, Window::class.java, Boolean::class.java, Long::class.java
13 | ) {
14 | it.args[0] = value
15 | it.args[2] = true
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/AlwaysShowMIUIWidget.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.content.ComponentName
4 | import com.github.kyuubiran.ezxhelper.utils.findMethod
5 | import com.github.kyuubiran.ezxhelper.utils.hookMethod
6 | import com.yuk.miuihome.utils.OwnSP
7 | import com.yuk.miuihome.utils.ktx.hookAfterMethod
8 | import com.yuk.miuihome.utils.ktx.hookBeforeMethod
9 | import com.yuk.miuihome.utils.ktx.setBooleanField
10 | import de.robv.android.xposed.XC_MethodHook
11 |
12 | class AlwaysShowMIUIWidget {
13 |
14 | fun init() {
15 | if (!OwnSP.ownSP.getBoolean("alwaysShowMIUIWidget", false)) return
16 | var hook1: XC_MethodHook.Unhook? = null
17 | var hook2: XC_MethodHook.Unhook? = null
18 | try {
19 | findMethod("com.miui.home.launcher.widget.WidgetsVerticalAdapter") {
20 | name == "buildAppWidgetsItems"
21 | }
22 | } catch (e: Exception) {
23 | findMethod("com.miui.home.launcher.widget.BaseWidgetsVerticalAdapter") {
24 | name == "buildAppWidgetsItems"
25 | }
26 | }.hookMethod {
27 | before {
28 | hook1 = "com.miui.home.launcher.widget.MIUIAppWidgetInfo".hookAfterMethod(
29 | "initMiuiAttribute", ComponentName::class.java
30 | ) {
31 | it.thisObject.setBooleanField("isMIUIWidget", false)
32 | }
33 | hook2 = "com.miui.home.launcher.MIUIWidgetUtil".hookBeforeMethod(
34 | "isMIUIWidgetSupport"
35 | ) {
36 | it.result = false
37 | }
38 | }
39 | after {
40 | hook1?.unhook()
41 | hook2?.unhook()
42 | }
43 | }
44 | }
45 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/BaseClassAndMethodCheck.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import com.github.kyuubiran.ezxhelper.init.InitFields.ezXClassLoader
4 | import com.yuk.miuihome.BuildConfig
5 | import de.robv.android.xposed.XposedBridge
6 | import de.robv.android.xposed.XposedHelpers
7 | import de.robv.android.xposed.XposedHelpers.ClassNotFoundError
8 |
9 | interface BaseClassAndMethodCheck {
10 |
11 | fun classAndMethodList(): ArrayList
12 |
13 | private fun getAllMethods(cls: Class<*>): ArrayList {
14 | val methodNameList = ArrayList()
15 | var loopCls = cls
16 | while (loopCls != Any::class.java) {
17 | for (item in cls.methods) methodNameList.add(item.name)
18 | loopCls = cls.superclass
19 | }
20 | return methodNameList
21 | }
22 |
23 | fun checkClassAndMethodExist(): Boolean {
24 | val list = classAndMethodList()
25 | if (list.size % 2 != 0)
26 | throw RuntimeException("checkClassAndMethodExist() -> ClassAndMethodList.size should be an even number")
27 | try {
28 | for (i in 0 until list.size step 2) {
29 | val cls = XposedHelpers.findClass(list[i], ezXClassLoader)
30 | if (list[i + 1] !in getAllMethods(cls)) return false
31 | }
32 | } catch (e: ClassNotFoundError) {
33 | if (BuildConfig.DEBUG) {
34 | XposedBridge.log("MiuiHome: $list Class not found")
35 | }
36 | return false
37 | }
38 | if (BuildConfig.DEBUG) XposedBridge.log("MiuiHome: $list Class found successfully")
39 | return true
40 | }
41 | }
42 |
43 | inline fun BaseClassAndMethodCheck.runWithChecked(crossinline code: () -> Unit) =
44 | if (checkClassAndMethodExist()) code() else null
45 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/BuildWithEverything.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.os.Build
4 | import android.widget.Toast
5 | import com.github.kyuubiran.ezxhelper.init.InitFields.appContext
6 | import com.yuk.miuihome.utils.Config
7 | import java.io.BufferedReader
8 | import java.io.InputStream
9 | import java.io.InputStreamReader
10 |
11 | class BuildWithEverything {
12 |
13 | private fun readStream(input: InputStream) {
14 | val reader = BufferedReader(InputStreamReader(input))
15 | var read = ""
16 | while (true) {
17 | val temp: String = reader.readLine() ?: break
18 | read += temp
19 | }
20 | Toast.makeText(appContext, read, Toast.LENGTH_LONG).show()
21 | }
22 |
23 | fun init() {
24 | if (Build.VERSION.SDK_INT >= 31) {
25 | try {
26 | readStream(Runtime.getRuntime().exec("su -c cmd package compile -m everything ${Config.hostPackage}").inputStream)
27 | } catch (ignore: Exception) {
28 | }
29 | } else {
30 | readStream(Runtime.getRuntime().exec("cmd package compile -m everything ${Config.hostPackage}").inputStream)
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/DisableLog.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import com.github.kyuubiran.ezxhelper.utils.Log
4 | import com.yuk.miuihome.XposedInit
5 | import com.yuk.miuihome.utils.ktx.findClass
6 | import com.yuk.miuihome.utils.ktx.hookBeforeMethod
7 | import com.yuk.miuihome.utils.ktx.replaceMethod
8 |
9 | class DisableLog {
10 |
11 | fun init() {
12 | try {
13 | if (XposedInit().checkVersionCode() <= 426004312L) "com.miui.home.launcher.MiuiHomeLog".hookBeforeMethod(
14 | "setDebugLogState",
15 | Boolean::class.java
16 | ) {
17 | it.result = false
18 | }
19 | "com.miui.home.launcher.MiuiHomeLog".findClass().replaceMethod(
20 | "log",
21 | String::class.java,
22 | String::class.java
23 | ) {
24 | return@replaceMethod null
25 | }
26 | "com.xiaomi.onetrack.OneTrack".hookBeforeMethod("isDisable") {
27 | it.result = true
28 | }
29 | } catch (e: Throwable) {
30 | Log.ex(e)
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/DisableRecentsViewWallpaperDarken.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import com.yuk.miuihome.utils.OwnSP
4 | import com.yuk.miuihome.utils.ktx.findClass
5 | import com.yuk.miuihome.utils.ktx.hookBeforeMethod
6 | import com.yuk.miuihome.utils.ktx.setFloatField
7 |
8 | class DisableRecentsViewWallpaperDarken {
9 |
10 | fun init() {
11 | if (OwnSP.ownSP.getBoolean("simpleAnimation", false)) return
12 | else if (!OwnSP.ownSP.getBoolean("wallpaperDarken", false)) return
13 | val surfaceControlCompat = "com.android.systemui.shared.recents.system.SurfaceControlCompat".findClass()
14 | "com.miui.home.recents.DimLayer".hookBeforeMethod("dim", Float::class.java, surfaceControlCompat, Boolean::class.java
15 | ) {
16 | it.args[0] = 0.0f
17 | it.thisObject.setFloatField("mCurrentAlpha", 0.0f)
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/DisableRecommendServer.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import com.yuk.miuihome.utils.OwnSP
4 | import com.yuk.miuihome.utils.ktx.hookBeforeMethod
5 |
6 | class DisableRecommendServer {
7 |
8 | fun init() {
9 | if (!OwnSP.ownSP.getBoolean("recommendServer", false)) return
10 | "com.miui.home.launcher.DeviceConfig".hookBeforeMethod("isRecommendServerEnable") {
11 | it.result = false
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/DoubleTapController.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.content.Context
4 | import android.os.SystemClock
5 | import android.view.MotionEvent
6 | import android.view.ViewConfiguration
7 | import kotlin.math.abs
8 |
9 | class DoubleTapController internal constructor(mContext: Context) {
10 |
11 | private val maxDuration: Long = 500
12 | private var mActionDownRawX: Float = 0f
13 | private var mActionDownRawY: Float = 0f
14 | private var mClickCount: Int = 0
15 | private var mFirstClickRawX: Float = 0f
16 | private var mFirstClickRawY: Float = 0f
17 | private var mLastClickTime: Long = 0
18 | private val mTouchSlop: Int = ViewConfiguration.get(mContext).scaledTouchSlop * 2
19 | fun isDoubleTapEvent(motionEvent: MotionEvent): Boolean {
20 | val action = motionEvent.actionMasked
21 | return when {
22 | action == MotionEvent.ACTION_DOWN -> {
23 | mActionDownRawX = motionEvent.rawX
24 | mActionDownRawY = motionEvent.rawY
25 | false
26 | }
27 | action != MotionEvent.ACTION_UP -> false
28 | else -> {
29 | val rawX = motionEvent.rawX
30 | val rawY = motionEvent.rawY
31 | if (abs(rawX - mActionDownRawX) <= mTouchSlop.toFloat() && abs(rawY - mActionDownRawY) <= mTouchSlop.toFloat()) {
32 | if (SystemClock.elapsedRealtime() - mLastClickTime > maxDuration || rawY - mFirstClickRawY > mTouchSlop.toFloat() || rawX - mFirstClickRawX > mTouchSlop.toFloat()) mClickCount = 0
33 | mClickCount++
34 | if (mClickCount == 1) {
35 | mFirstClickRawX = rawX
36 | mFirstClickRawY = rawY
37 | mLastClickTime = SystemClock.elapsedRealtime()
38 | return false
39 | } else if (abs(rawY - mFirstClickRawY) <= mTouchSlop.toFloat() && abs(rawX - mFirstClickRawX) <= mTouchSlop.toFloat() && SystemClock.elapsedRealtime() - mLastClickTime <= maxDuration
40 | ) {
41 | mClickCount = 0
42 | return true
43 | }
44 | }
45 | mClickCount = 0
46 | false
47 | }
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/EnableAllAppsContainerViewBlur.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.os.Build
4 | import android.view.View
5 | import android.widget.FrameLayout
6 | import android.widget.RelativeLayout
7 | import android.widget.ViewSwitcher
8 | import com.github.kyuubiran.ezxhelper.utils.findMethod
9 | import com.github.kyuubiran.ezxhelper.utils.hookAfter
10 | import com.yuk.miuihome.XposedInit
11 | import com.yuk.miuihome.utils.OwnSP
12 | import com.yuk.miuihome.utils.ktx.findClass
13 | import com.yuk.miuihome.utils.ktx.getObjectField
14 | import com.zhenxiang.blur.WindowBlurFrameLayout
15 | import com.zhenxiang.blur.model.CornersRadius
16 |
17 | class EnableAllAppsContainerViewBlur {
18 | fun init() {
19 | if (!OwnSP.ownSP.getBoolean("allAppsBlur", false) || Build.VERSION.SDK_INT < 31) return
20 | findMethod("com.miui.home.launcher.allapps.BaseAllAppsContainerView".findClass(), true)
21 | { name == "onFinishInflate" }.hookAfter { hookParam ->
22 | val mCategoryContainer = hookParam.thisObject.getObjectField("mCategoryContainer") as ViewSwitcher
23 | val appsView = mCategoryContainer.parent as RelativeLayout
24 | val blur = WindowBlurFrameLayout(mCategoryContainer.context)
25 | val radius = XposedInit().getCornerRadiusTop().toFloat()
26 | blur.blurController.apply {
27 | cornerRadius = CornersRadius.custom(radius, radius, 0f, 0f)
28 | }
29 | val view = View(mCategoryContainer.context)
30 | blur.addView(view)
31 | (view.layoutParams as FrameLayout.LayoutParams).apply {
32 | width = FrameLayout.LayoutParams.MATCH_PARENT
33 | height = FrameLayout.LayoutParams.MATCH_PARENT
34 | }
35 | appsView.addView(blur, 0)
36 | findMethod("com.miui.home.launcher.allapps.BaseAllAppsContainerView".findClass(), true)
37 | { name == "onResume" }.hookAfter {
38 | blur.refreshDrawableState()
39 | }
40 | }
41 |
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/EnableBlurWhenOpenFolder.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.app.Activity
4 | import android.os.Bundle
5 | import android.view.View
6 | import com.yuk.miuihome.XposedInit
7 | import com.yuk.miuihome.utils.OwnSP
8 | import com.yuk.miuihome.utils.ktx.*
9 |
10 | class EnableBlurWhenOpenFolder {
11 |
12 | fun init() {
13 | if (OwnSP.ownSP.getBoolean("simpleAnimation", false)) {
14 | if (XposedInit().checkIsAlpha()) {
15 | "com.miui.home.launcher.common.BlurUtils".hookBeforeMethod("isUserBlurWhenOpenFolder") {
16 | it.result = false
17 | }
18 | }
19 | }
20 | else {
21 | if (OwnSP.ownSP.getBoolean("blurWhenOpenFolder", false)) {
22 | if (XposedInit().checkIsAlpha()) {
23 | "com.miui.home.launcher.common.BlurUtils".hookBeforeMethod("isUserBlurWhenOpenFolder") {
24 | it.result = true
25 | }
26 | }
27 | else {
28 | val blurClass = "com.miui.home.launcher.common.BlurUtils".findClass()
29 | val folderInfo = "com.miui.home.launcher.FolderInfo".findClass()
30 | val launcherClass = "com.miui.home.launcher.Launcher".findClass()
31 | val launcherStateClass = "com.miui.home.launcher.LauncherState".findClass()
32 | launcherClass.hookAfterMethod("onCreate", Bundle::class.java) {
33 | val activity = it.thisObject as Activity
34 | var isFolderShowing = false
35 | launcherClass.hookAfterMethod("isFolderShowing") { hookParam ->
36 | isFolderShowing = hookParam.result as Boolean
37 | }
38 | launcherClass.hookAfterMethod("openFolder", folderInfo, View::class.java) {
39 | blurClass.callStaticMethod("fastBlur", 1.0f, activity.window, true)
40 | }
41 | launcherClass.hookAfterMethod("closeFolder", Boolean::class.java) {
42 | blurClass.callStaticMethod("fastBlur", 0.0f, activity.window, true, 300L)
43 | }
44 | blurClass.hookAfterMethod("fastBlurWhenStartOpenOrCloseApp", Boolean::class.java, launcherClass) { hookParam ->
45 | if (isFolderShowing) hookParam.result = blurClass.callStaticMethod("fastBlur", 1.0f, activity.window, true, 0L)
46 | }
47 | blurClass.hookAfterMethod("fastBlurWhenFinishOpenOrCloseApp", launcherClass) { hookParam ->
48 | if (isFolderShowing) hookParam.result = blurClass.callStaticMethod("fastBlur", 1.0f, activity.window, true, 0L)
49 | }
50 | blurClass.hookAfterMethod("fastBlurWhenExitRecents", launcherClass, launcherStateClass, Boolean::class.java) { hookParam ->
51 | if (isFolderShowing) hookParam.result = blurClass.callStaticMethod("fastBlur", 1.0f, activity.window, true, 0L)
52 | }
53 | launcherClass.hookAfterMethod("onGesturePerformAppToHome") {
54 | if (isFolderShowing) blurClass.callStaticMethod("fastBlur", 1.0f, activity.window, true, 0L)
55 | }
56 | }
57 | }
58 | } else {
59 | if (XposedInit().checkIsAlpha())
60 | "com.miui.home.launcher.common.BlurUtils".hookBeforeMethod("isUserBlurWhenOpenFolder") {
61 | it.result = false
62 | }
63 | }
64 | }
65 | }
66 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/EnableClockGadget.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import com.yuk.miuihome.utils.OwnSP
4 | import com.yuk.miuihome.utils.ktx.hookBeforeMethod
5 |
6 | class EnableClockGadget {
7 |
8 | fun init() {
9 | if (!OwnSP.ownSP.getBoolean("clockGadget", false)) return
10 | "com.miui.home.launcher.Workspace".hookBeforeMethod(
11 | "isScreenHasClockGadget",
12 | Long::class.java
13 | ) { it.result = false }
14 | }
15 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/EnableDockIconShadow.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import com.yuk.miuihome.utils.OwnSP
4 | import com.yuk.miuihome.utils.ktx.hookBeforeMethod
5 |
6 |
7 | class EnableDockIconShadow {
8 |
9 | fun init() {
10 | if (!OwnSP.ownSP.getBoolean("isEnableIconShadow", false)) return
11 | "com.miui.home.launcher.Launcher".hookBeforeMethod("isEnableIconShadow") {
12 | it.result = true
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/EnableFolderIconBlur.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.graphics.Color
4 | import android.os.Build
5 | import android.view.Gravity
6 | import android.widget.FrameLayout
7 | import android.widget.ImageView
8 | import com.github.kyuubiran.ezxhelper.utils.findMethod
9 | import com.github.kyuubiran.ezxhelper.utils.hookAfter
10 | import com.yuk.miuihome.utils.OwnSP
11 | import com.yuk.miuihome.utils.ktx.findClass
12 | import com.yuk.miuihome.utils.ktx.getObjectField
13 | import com.zhenxiang.blur.WindowBlurFrameLayout
14 | import com.zhenxiang.blur.model.CornersRadius
15 |
16 | class EnableFolderIconBlur {
17 | fun init() {
18 | if (!OwnSP.ownSP.getBoolean("folderBlur", false) || Build.VERSION.SDK_INT < 31) return
19 | val value = OwnSP.ownSP.getFloat("folderBlurCorner", 30f)
20 | val value1 = OwnSP.ownSP.getFloat("folderBlurSide", 1.2f) * 100
21 | findMethod("com.miui.home.launcher.FolderIcon".findClass(), true)
22 | { name == "onFinishInflate" }.hookAfter { hookParam ->
23 | val mIconImageView = hookParam.thisObject.getObjectField("mIconImageView") as ImageView
24 | val mIconContainer = mIconImageView.parent as FrameLayout
25 | val blur = WindowBlurFrameLayout(mIconContainer.context)
26 | val view = FrameLayout(mIconImageView.context)
27 | blur.blurController.apply {
28 | backgroundColour = Color.parseColor("#44FFFFFF")
29 | cornerRadius = CornersRadius.all(value)
30 | }
31 | mIconContainer.removeView(mIconImageView)
32 | blur.addView(view)
33 | mIconContainer.addView(blur, 0)
34 | val lp1 = blur.layoutParams as FrameLayout.LayoutParams
35 | lp1.gravity = Gravity.CENTER
36 | lp1.height = value1.toInt()
37 | lp1.width = value1.toInt()
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/EnableHideStatusBarWhenEnterRecents.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import com.yuk.miuihome.utils.OwnSP
4 | import com.yuk.miuihome.utils.ktx.hookBeforeMethod
5 |
6 | class EnableHideStatusBarWhenEnterRecents {
7 |
8 | fun init() {
9 | if (OwnSP.ownSP.getBoolean("hideStatusBar", false)) {
10 | "com.miui.home.launcher.common.DeviceLevelUtils".hookBeforeMethod(
11 | "isHideStatusBarWhenEnterRecents"
12 | ) {
13 | it.result = true
14 | }
15 | "com.miui.home.launcher.DeviceConfig".hookBeforeMethod(
16 | "keepStatusBarShowingForBetterPerformance"
17 | ) {
18 | it.result = false
19 | }
20 | } else {
21 | "com.miui.home.launcher.common.DeviceLevelUtils".hookBeforeMethod(
22 | "isHideStatusBarWhenEnterRecents"
23 | ) {
24 | it.result = false
25 | }
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/EnableLowEndDeviceUseMIUIWidgets.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import com.yuk.miuihome.utils.OwnSP
4 | import com.yuk.miuihome.utils.ktx.hookBeforeMethod
5 |
6 | class EnableLowEndDeviceUseMIUIWidgets {
7 |
8 | fun init() {
9 | if (!OwnSP.ownSP.getBoolean("useMIUIWidgets", false)) return
10 | "com.miui.home.launcher.MIUIWidgetUtil".hookBeforeMethod("isMIUIWidgetSupport") {
11 | it.result = true
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/EnableMamlDownload.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import com.yuk.miuihome.utils.OwnSP
4 | import com.yuk.miuihome.utils.ktx.hookBeforeMethod
5 |
6 | class EnableMamlDownload {
7 |
8 | fun init() {
9 | if (OwnSP.ownSP.getBoolean("mamlDownload", false))
10 | "com.miui.home.launcher.common.CpuLevelUtils".hookBeforeMethod("needMamlDownload") {
11 | it.result = true
12 | }
13 | else
14 | "com.miui.home.launcher.common.CpuLevelUtils".hookBeforeMethod("needMamlDownload") {
15 | it.result = false
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/EnableRecentsViewHorizontal.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import com.yuk.miuihome.utils.OwnSP
4 | import com.yuk.miuihome.utils.ktx.hookBeforeMethod
5 |
6 | class EnableRecentsViewHorizontal {
7 |
8 | fun init() {
9 | if (!OwnSP.ownSP.getBoolean("horizontal", false)) return
10 | "com.miui.home.launcher.DeviceConfig".hookBeforeMethod("isKeepRecentsViewPortrait") {
11 | it.result = false
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/EnableSimpleAnimation.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import com.yuk.miuihome.utils.OwnSP
4 | import com.yuk.miuihome.utils.ktx.hookBeforeMethod
5 |
6 | class EnableSimpleAnimation {
7 |
8 | fun init() {
9 | if (OwnSP.ownSP.getBoolean("simpleAnimation", false))
10 | "com.miui.home.launcher.common.DeviceLevelUtils".hookBeforeMethod("isUseSimpleAnim") {
11 | it.result = true
12 | }
13 | else
14 | "com.miui.home.launcher.common.DeviceLevelUtils".hookBeforeMethod("isUseSimpleAnim") {
15 | it.result = false
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/EnableSmoothAnimation.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import com.yuk.miuihome.XposedInit
4 | import com.yuk.miuihome.utils.OwnSP
5 | import com.yuk.miuihome.utils.ktx.hookBeforeMethod
6 |
7 | class EnableSmoothAnimation {
8 |
9 | fun init() {
10 | if (XposedInit().checkVersionCode() >= 427004733L) return
11 | if (OwnSP.ownSP.getBoolean("simpleAnimation", false))
12 | "com.miui.home.launcher.common.Utilities".hookBeforeMethod("isUseSmoothAnimationEffect") {
13 | it.result = false
14 | }
15 | else {
16 | if (OwnSP.ownSP.getBoolean("smoothAnimation", false))
17 | "com.miui.home.launcher.common.Utilities".hookBeforeMethod("isUseSmoothAnimationEffect") {
18 | it.result = true
19 | }
20 | else
21 | "com.miui.home.launcher.common.Utilities".hookBeforeMethod("isUseSmoothAnimationEffect") {
22 | it.result = false
23 | }
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/HookSystemProperties.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import com.yuk.miuihome.utils.OwnSP
4 | import com.yuk.miuihome.utils.ktx.hookBeforeMethod
5 |
6 | class HookSystemProperties {
7 |
8 | fun init() {
9 | "android.os.SystemProperties".hookBeforeMethod("getBoolean", String::class.java, Boolean::class.java
10 | ) {
11 | if (it.args[0] == "ro.miui.backdrop_sampling_enabled") it.result = true
12 | }
13 | if (OwnSP.ownSP.getBoolean("lowEndAnim", false))
14 | "android.os.SystemProperties".hookBeforeMethod("getBoolean", String::class.java, Boolean::class.java
15 | ) {
16 | if (it.args[0] == "ro.config.low_ram.threshold_gb") it.result = false
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/ModifyAnimDurationRatio.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import com.yuk.miuihome.utils.OwnSP
4 | import com.yuk.miuihome.utils.ktx.hookBeforeMethod
5 |
6 | class ModifyAnimDurationRatio {
7 |
8 | fun init() {
9 | val value = OwnSP.ownSP.getFloat("animationLevel", -1f)
10 | if (value == -1f) return
11 | "com.miui.home.recents.util.RectFSpringAnim".hookBeforeMethod("getModifyResponse", Float::class.java) {
12 | it.result = it.args[0] as Float * value
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/ModifyAppReturnBlur.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.annotation.SuppressLint
4 | import android.app.Activity
5 | import android.os.Bundle
6 | import android.view.View
7 | import com.yuk.miuihome.utils.Config
8 | import com.yuk.miuihome.utils.OwnSP
9 | import com.yuk.miuihome.utils.ktx.callMethod
10 | import com.yuk.miuihome.utils.ktx.callStaticMethod
11 | import com.yuk.miuihome.utils.ktx.findClass
12 | import com.yuk.miuihome.utils.ktx.hookAfterMethod
13 |
14 | class ModifyAppReturnBlur {
15 |
16 | @SuppressLint("DiscouragedApi")
17 | fun init() {
18 | if (!OwnSP.ownSP.getBoolean("appReturnAmin", false)) return
19 | val value = (OwnSP.ownSP.getFloat("appReturnAminSpend", 2f) * 100).toLong()
20 | val blurClass = "com.miui.home.launcher.common.BlurUtils".findClass()
21 | val launcherClass = "com.miui.home.launcher.Launcher".findClass()
22 | val isUserBlurWhenOpenFolder = OwnSP.ownSP.getBoolean("blurWhenOpenFolder", false)
23 | launcherClass.hookAfterMethod("onResume") {
24 | val activity = it.thisObject as Activity
25 | val view: View = activity.findViewById(activity.resources.getIdentifier("recents_container", "id", Config.hostPackage))
26 | var isFolderShowing: Boolean
27 | var isInEditing: Boolean
28 | blurClass.hookAfterMethod("fastBlurWhenStartOpenOrCloseApp", Boolean::class.java, launcherClass) { hookParam ->
29 | val z = hookParam.args[0] as Boolean
30 | isInEditing = activity.callMethod("isInEditing") as Boolean
31 | if (view.visibility == View.GONE && !isInEditing && !z) {
32 | if (isUserBlurWhenOpenFolder) {
33 | isFolderShowing = activity.callMethod("isFolderShowing") as Boolean
34 | if (!isFolderShowing) {
35 | hookParam.result = blurClass.callStaticMethod("fastBlur", 0.0f, activity.window, true, value)
36 | }
37 | } else {
38 | hookParam.result = blurClass.callStaticMethod("fastBlur", 0.0f, activity.window, true, value)
39 | }
40 | }
41 | }
42 | launcherClass.hookAfterMethod("onGesturePerformAppToHome") {
43 | isInEditing = activity.callMethod("isInEditing") as Boolean
44 | if (view.visibility == View.GONE && !isInEditing) {
45 | if (isUserBlurWhenOpenFolder) {
46 | isFolderShowing = activity.callMethod("isFolderShowing") as Boolean
47 | if (!isFolderShowing) {
48 | blurClass.callStaticMethod("fastBlur", 1.0f, activity.window, true, 0L)
49 | blurClass.callStaticMethod("fastBlur", 0.0f, activity.window, true, value)
50 | }
51 | } else {
52 | blurClass.callStaticMethod("fastBlur", 1.0f, activity.window, true, 0L)
53 | blurClass.callStaticMethod("fastBlur", 0.0f, activity.window, true, value)
54 | }
55 | }
56 | }
57 | }
58 | }
59 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/ModifyBlurLevel.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import com.yuk.miuihome.utils.OwnSP
4 | import com.yuk.miuihome.utils.ktx.hookBeforeMethod
5 |
6 | class ModifyBlurLevel : BaseClassAndMethodCheck {
7 |
8 | companion object {
9 | var checked = false
10 | }
11 |
12 | fun init() {
13 | val blurLevel = OwnSP.ownSP.getString("blurLevel", "SimpleBlur")
14 | if (OwnSP.ownSP.getBoolean("simpleAnimation", false)) {
15 | "com.miui.home.launcher.common.BlurUtils".hookBeforeMethod("getBlurType") {
16 | it.result = 0
17 | }
18 | "com.miui.home.launcher.common.BlurUtils".hookBeforeMethod("isUseCompleteBlurOnDev") {
19 | it.result = false
20 | }
21 | } else {
22 | "com.miui.home.launcher.common.BlurUtils".hookBeforeMethod("getBlurType") {
23 | when (blurLevel) {
24 | "CompleteBlur" -> it.result = 2
25 | "SimpleBlur" -> it.result = 1
26 | "NoneBlur" -> it.result = 0
27 | }
28 | }
29 | "com.miui.home.launcher.common.BlurUtils".hookBeforeMethod("isUseCompleteBlurOnDev") {
30 | when (blurLevel) {
31 | "TestBlur" -> it.result = true
32 | }
33 | }
34 | runWithChecked {
35 | checked = true
36 | "com.miui.home.launcher.common.BlurUtils".hookBeforeMethod("isUseBasicBlur") {
37 | when (blurLevel) {
38 | "BasicBlur" -> it.result = true
39 | }
40 | }
41 | }
42 | }
43 | }
44 |
45 | override fun classAndMethodList(): ArrayList = arrayListOf("com.miui.home.launcher.common.BlurUtils", "isUseBasicBlur")
46 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/ModifyBlurRadius.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import com.yuk.miuihome.utils.OwnSP
4 | import com.yuk.miuihome.utils.ktx.findClass
5 | import com.yuk.miuihome.utils.ktx.hookBeforeAllMethods
6 |
7 | class ModifyBlurRadius {
8 |
9 | fun init() {
10 | val value = OwnSP.ownSP.getFloat("blurRadius", -1f)
11 | if (value == -1f || value == 1f) return
12 | val blurUtilsClass = "com.miui.home.launcher.common.BlurUtils".findClass()
13 | blurUtilsClass.hookBeforeAllMethods("fastBlur") {
14 | it.args[0] = it.args[0] as Float * value
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/ModifyCategory.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.view.View
4 | import com.yuk.miuihome.XposedInit
5 | import com.yuk.miuihome.utils.OwnSP
6 | import com.yuk.miuihome.utils.ktx.callMethod
7 | import com.yuk.miuihome.utils.ktx.findClass
8 | import com.yuk.miuihome.utils.ktx.getObjectField
9 | import com.yuk.miuihome.utils.ktx.hookAfterMethod
10 |
11 | class ModifyCategory {
12 |
13 | fun init() {
14 | if (OwnSP.ownSP.getBoolean("categoryHideAll", false)) {
15 | val cla = if (XposedInit().checkVersionCode() >= 427004483L) "com.miui.home.launcher.allapps.category.BaseAllAppsCategoryListContainer" else "com.miui.home.launcher.allapps.category.AllAppsCategoryListContainer"
16 | cla.hookAfterMethod("buildSortCategoryList"
17 | ) {
18 | val list = it.result as ArrayList<*>
19 | if (list.size > 1) {
20 | list.removeAt(0)
21 | it.result = list
22 | }
23 | }
24 | }
25 | if (OwnSP.ownSP.getBoolean("CategoryPagingHideEdit", false))
26 | "com.miui.home.launcher.allapps.AllAppsGridAdapter".hookAfterMethod("onBindViewHolder", "com.miui.home.launcher.allapps.AllAppsGridAdapter.ViewHolder".findClass(), Int::class.javaPrimitiveType
27 | ) {
28 | if ((it.args[0].callMethod("getItemViewType") as Int) == 64)
29 | (it.args[0].getObjectField("itemView") as View).visibility = View.INVISIBLE
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/ModifyCloseFolderOnLaunch.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 |
4 | import android.view.View
5 | import com.yuk.miuihome.utils.OwnSP
6 | import com.yuk.miuihome.utils.ktx.callMethod
7 | import com.yuk.miuihome.utils.ktx.getBooleanField
8 | import com.yuk.miuihome.utils.ktx.hookAfterMethod
9 |
10 | class ModifyCloseFolderOnLaunch {
11 |
12 | fun init() {
13 | if (!OwnSP.ownSP.getBoolean("closeFolder", false)) return
14 | "com.miui.home.launcher.Launcher".hookAfterMethod("launch", "com.miui.home.launcher.ShortcutInfo", View::class.java
15 | ) {
16 | val mHasLaunchedAppFromFolder = it.thisObject.getBooleanField("mHasLaunchedAppFromFolder")
17 | if (mHasLaunchedAppFromFolder) it.thisObject.callMethod("closeFolder")
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/ModifyDockHook.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.annotation.SuppressLint
4 | import android.app.Activity
5 | import android.content.Context
6 | import android.graphics.Color
7 | import android.os.Build
8 | import android.os.Bundle
9 | import android.view.View
10 | import android.widget.FrameLayout
11 | import android.widget.RelativeLayout
12 | import com.github.kyuubiran.ezxhelper.init.InitFields.appContext
13 | import com.github.kyuubiran.ezxhelper.utils.Log
14 | import com.yuk.miuihome.utils.OwnSP
15 | import com.yuk.miuihome.utils.ktx.*
16 | import com.zhenxiang.blur.WindowBlurFrameLayout
17 | import com.zhenxiang.blur.model.CornersRadius
18 | import de.robv.android.xposed.XposedHelpers
19 |
20 | class ModifyDockHook {
21 |
22 | @SuppressLint("DiscouragedApi")
23 | fun init() {
24 | if (!OwnSP.ownSP.getBoolean("dockSettings", false) || Build.VERSION.SDK_INT < 31) return
25 | try {
26 | val deviceConfigClass = "com.miui.home.launcher.DeviceConfig".findClass()
27 | val launcherClass = "com.miui.home.launcher.Launcher".findClass()
28 | val launcherStateManagerClass = "com.miui.home.launcher.LauncherStateManager".findClass()
29 | // Dock距屏幕两侧
30 | deviceConfigClass.hookBeforeMethod("calcSearchBarWidth", Context::class.java) {
31 | val deviceWidth = px2dp(appContext.resources.displayMetrics.widthPixels)
32 | it.result = dp2px(deviceWidth - OwnSP.ownSP.getFloat("dockSide", 3.0f) * 10)
33 | }
34 | // Dock距屏幕底部
35 | deviceConfigClass.hookBeforeMethod("calcSearchBarMarginBottom", Context::class.java, Boolean::class.java) {
36 | it.result = dp2px(OwnSP.ownSP.getFloat("dockBottom", 2.3f) * 10)
37 | }
38 | // 图标距屏幕底部
39 | deviceConfigClass.hookBeforeMethod("calcHotSeatsMarginBottom", Context::class.java, Boolean::class.java, Boolean::class.java) {
40 | it.result = dp2px(OwnSP.ownSP.getFloat("dockIconBottom", 3.5f) * 10)
41 | }
42 | // 页面指示器距离图标距离
43 | deviceConfigClass.hookBeforeMethod("calcHotSeatsMarginTop", Context::class.java, Boolean::class.java) {
44 | it.result = dp2px(OwnSP.ownSP.getFloat("dockMarginTop", 0.6f) * 10)
45 | }
46 | // 页面指示器距离屏幕底部
47 | deviceConfigClass.hookBeforeMethod("getWorkspaceIndicatorMarginBottom",) {
48 | it.result = dp2px(OwnSP.ownSP.getFloat("dockMarginBottom", 11.0f) * 10)
49 | }
50 | // 宽度变化量
51 | deviceConfigClass.hookBeforeMethod("getSearchBarWidthDelta") {
52 | it.result = 0
53 | }
54 | launcherClass.hookAfterMethod("onCreate", Bundle::class.java) { it ->
55 | val activity = it.thisObject as Activity
56 | val searchBarObject = activity.callMethod("getSearchBar") as FrameLayout
57 | val searchBarDrawer = searchBarObject.getChildAt(1) as RelativeLayout
58 | val searchBarDesktop = searchBarObject.getChildAt(0) as RelativeLayout
59 | val searchBarContainer = searchBarObject.parent as FrameLayout
60 | val searchEdgeLayout = searchBarContainer.parent as FrameLayout
61 | val blur = WindowBlurFrameLayout(searchBarObject.context)
62 | blur.blurController.apply {
63 | backgroundColour = Color.parseColor("#44FFFFFF")
64 | cornerRadius = CornersRadius.all(dp2px((OwnSP.ownSP.getFloat("dockRadius", 2.5f) * 10)).toFloat())
65 | }
66 | // 重新给搜索框容器排序
67 | searchEdgeLayout.removeView(searchBarContainer)
68 | searchEdgeLayout.addView(searchBarContainer, 0)
69 | // 清空搜索图标和小爱同学
70 | searchBarDesktop.removeAllViews()
71 | // 修改高度
72 | searchBarObject.layoutParams.height = dp2px((OwnSP.ownSP.getFloat("dockHeight", 7.9f) * 10))
73 | // 添加 A12 模糊
74 | if (OwnSP.ownSP.getBoolean("searchBarBlur", false)) {
75 | searchBarObject.removeAllViews()
76 | searchBarObject.addView(blur)
77 | launcherStateManagerClass.hookAfterMethod("getState") {
78 | val state = it.result.toString()
79 | val a = state.lastIndexOf("LauncherState")
80 | if (a != -1) blur.visibility = View.VISIBLE
81 | else blur.visibility = View.GONE
82 | }
83 | }
84 | // 修改应用列表搜索框
85 | val mAllAppViewField = launcherClass.getDeclaredField("mAppsView")
86 | mAllAppViewField.isAccessible = true
87 | val mAllAppView = mAllAppViewField.get(it.thisObject) as RelativeLayout
88 | val mAllAppSearchView = mAllAppView.getChildAt(mAllAppView.childCount - 1) as FrameLayout
89 | mAllAppSearchView.addView(searchBarDrawer)
90 | searchBarDrawer.bringToFront()
91 | val layoutParams = searchBarDrawer.layoutParams as FrameLayout.LayoutParams
92 | searchBarDrawer.layoutParams.height = dp2px(43f)
93 | layoutParams.leftMargin = dp2px(15f)
94 | layoutParams.rightMargin = dp2px(15f)
95 | searchBarDrawer.layoutParams = layoutParams
96 | }
97 | } catch (e: XposedHelpers.ClassNotFoundError) {
98 | Log.ex(e)
99 | }
100 | }
101 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/ModifyDoubleTapToSleep.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.content.Context
4 | import android.content.Intent
5 | import android.view.MotionEvent
6 | import com.yuk.miuihome.utils.OwnSP
7 | import com.yuk.miuihome.utils.ktx.*
8 | import de.robv.android.xposed.XposedHelpers
9 |
10 | class ModifyDoubleTapToSleep {
11 |
12 | fun init() {
13 | if (!OwnSP.ownSP.getBoolean("doubleTap", false)) return
14 | val workspace = "com.miui.home.launcher.Workspace".findClass()
15 | workspace.hookAfterAllConstructors {
16 | var mDoubleTapControllerEx = XposedHelpers.getAdditionalInstanceField(it.thisObject, "mDoubleTapControllerEx")
17 | if (mDoubleTapControllerEx != null) return@hookAfterAllConstructors
18 | mDoubleTapControllerEx = DoubleTapController((it.args[0] as Context))
19 | XposedHelpers.setAdditionalInstanceField(it.thisObject, "mDoubleTapControllerEx", mDoubleTapControllerEx)
20 | }
21 | "com.miui.home.launcher.Workspace".hookBeforeMethod("dispatchTouchEvent", MotionEvent::class.java
22 | ) {
23 | val mDoubleTapControllerEx = XposedHelpers.getAdditionalInstanceField(it.thisObject, "mDoubleTapControllerEx") as DoubleTapController
24 | if (!mDoubleTapControllerEx.isDoubleTapEvent(it.args[0] as MotionEvent)) return@hookBeforeMethod
25 | val mCurrentScreenIndex = it.thisObject.getIntField("mCurrentScreenIndex")
26 | val cellLayout = it.thisObject.callMethod("getCellLayout", mCurrentScreenIndex)
27 | if (cellLayout != null) if (cellLayout.callMethod("lastDownOnOccupiedCell") as Boolean) return@hookBeforeMethod
28 | if (it.thisObject.callMethod("isInNormalEditingMode") as Boolean) return@hookBeforeMethod
29 | val context = it.thisObject.callMethod("getContext") as Context
30 | context.sendBroadcast(Intent("com.miui.app.ExtraStatusBarManager.action_TRIGGER_TOGGLE").putExtra("com.miui.app.ExtraStatusBarManager.extra_TOGGLE_ID", 10))
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/ModifyFolderColumnsCount.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.view.ViewGroup
4 | import android.widget.GridView
5 | import com.yuk.miuihome.utils.OwnSP
6 | import com.yuk.miuihome.utils.ktx.findClass
7 | import com.yuk.miuihome.utils.ktx.hookAfterAllMethods
8 | import de.robv.android.xposed.XposedHelpers
9 |
10 | class ModifyFolderColumnsCount {
11 |
12 | fun init() {
13 | val value = OwnSP.ownSP.getInt("folderColumns", -1)
14 | if (value == -1 || value == 3) return
15 | "com.miui.home.launcher.Folder".findClass().hookAfterAllMethods("bind"
16 | ) {
17 | val columns: Int = value
18 | val mContent = XposedHelpers.getObjectField(it.thisObject, "mContent") as GridView
19 | mContent.numColumns = columns
20 | if (OwnSP.ownSP.getBoolean("folderWidth", false) && (columns > 3)) {
21 | mContent.setPadding(0,0,0,0)
22 | val lp = mContent.layoutParams
23 | lp.width = ViewGroup.LayoutParams.MATCH_PARENT
24 | mContent.layoutParams = lp
25 | }
26 | if (columns > 3) {
27 | val mBackgroundView = XposedHelpers.getObjectField(it.thisObject, "mBackgroundView") as ViewGroup
28 | mBackgroundView.setPadding(mBackgroundView.paddingLeft / 3, mBackgroundView.paddingTop, mBackgroundView.paddingRight / 3, mBackgroundView.paddingBottom)
29 | }
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/ModifyHideSeekPoints.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.view.View
4 | import android.view.ViewGroup
5 | import com.yuk.miuihome.utils.OwnSP
6 | import com.yuk.miuihome.utils.ktx.callMethod
7 | import com.yuk.miuihome.utils.ktx.getObjectField
8 | import com.yuk.miuihome.utils.ktx.hookBeforeMethod
9 |
10 |
11 | class ModifyHideSeekPoints {
12 |
13 | fun init() {
14 | "com.miui.home.launcher.ScreenView".hookBeforeMethod("updateSeekPoints", Int::class.javaPrimitiveType
15 | ) {
16 | showSeekBar(it.thisObject as View)
17 | }
18 | "com.miui.home.launcher.ScreenView".hookBeforeMethod("addView", View::class.java, Int::class.javaPrimitiveType, ViewGroup.LayoutParams::class.java
19 | ) {
20 | showSeekBar(it.thisObject as View)
21 | }
22 | "com.miui.home.launcher.ScreenView".hookBeforeMethod("removeScreen", Int::class.javaPrimitiveType
23 | ) {
24 | showSeekBar(it.thisObject as View)
25 | }
26 | "com.miui.home.launcher.ScreenView".hookBeforeMethod("removeScreensInLayout", Int::class.javaPrimitiveType, Int::class.javaPrimitiveType
27 | ) {
28 | showSeekBar(it.thisObject as View)
29 | }
30 | }
31 |
32 | private fun showSeekBar(workspace: View) {
33 | if ("Workspace" != workspace.javaClass.simpleName) return
34 | val isInEditingMode = workspace.callMethod("isInNormalEditingMode") as Boolean
35 | val mScreenSeekBar = workspace.getObjectField("mScreenSeekBar") as View
36 | mScreenSeekBar.animate().cancel()
37 | if (!isInEditingMode && OwnSP.ownSP.getBoolean("hideSeekPoints", false)) {
38 | mScreenSeekBar.alpha = 0.0f
39 | mScreenSeekBar.visibility = View.GONE
40 | return
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/ModifyHideWidgetTitles.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.content.Context
4 | import android.view.View
5 | import com.yuk.miuihome.utils.OwnSP
6 | import com.yuk.miuihome.utils.ktx.callMethod
7 | import com.yuk.miuihome.utils.ktx.findClass
8 | import com.yuk.miuihome.utils.ktx.hookAfterMethod
9 | import java.util.function.Predicate
10 |
11 | class ModifyHideWidgetTitles {
12 |
13 | fun init() {
14 | if (!OwnSP.ownSP.getBoolean("hideWidgetTitles", false)) return
15 | val widgetInfo = "com.miui.home.launcher.LauncherAppWidgetInfo".findClass()
16 | val widgetProviderInfo = "android.appwidget.AppWidgetProviderInfo".findClass()
17 | val maMlWidgetInfo = "com.miui.home.launcher.maml.MaMlWidgetInfo".findClass()
18 | "com.miui.home.launcher.LauncherAppWidgetHost".hookAfterMethod("createLauncherWidgetView", Context::class.java, Int::class.javaPrimitiveType, widgetInfo, widgetProviderInfo
19 | ) {
20 | val view = it.result as Any
21 | view.callMethod("getTitleView")?.callMethod("setVisibility", View.GONE)
22 | }
23 | "com.miui.home.launcher.Launcher".hookAfterMethod("addMaMl", maMlWidgetInfo, Boolean::class.java, Predicate::class.java
24 | ) {
25 | val view = it.result as Any
26 | view.callMethod("getTitleView")?.callMethod("setVisibility", View.GONE)
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/ModifyIconTitleFontColor.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.content.Context
4 | import android.graphics.Color
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import android.widget.TextView
8 | import com.github.kyuubiran.ezxhelper.utils.Log
9 | import com.yuk.miuihome.utils.Config
10 | import com.yuk.miuihome.utils.OwnSP
11 | import com.yuk.miuihome.utils.ktx.callMethod
12 | import com.yuk.miuihome.utils.ktx.findClass
13 | import com.yuk.miuihome.utils.ktx.getObjectField
14 | import com.yuk.miuihome.utils.ktx.hookAfterMethod
15 |
16 | class ModifyIconTitleFontColor {
17 |
18 | fun init() {
19 | val value = OwnSP.ownSP.getString("iconTitleFontColor", "")
20 | val launcherClass = "com.miui.home.launcher.Launcher".findClass()
21 | val shortcutInfoClass = "com.miui.home.launcher.ShortcutInfo".findClass()
22 | if (value == "") return
23 | try {
24 | "com.miui.home.launcher.ItemIcon".hookAfterMethod("onFinishInflate"
25 | ) {
26 | val mTitle = it.thisObject.getObjectField("mTitle") as TextView
27 | mTitle.setTextColor(Color.parseColor(value))
28 | }
29 | "com.miui.home.launcher.maml.MaMlWidgetView".hookAfterMethod("onFinishInflate"
30 | ) {
31 | val mTitle = it.thisObject.getObjectField("mTitleTextView") as TextView
32 | mTitle.setTextColor(Color.parseColor(value))
33 | }
34 | "com.miui.home.launcher.LauncherMtzGadgetView".hookAfterMethod("onFinishInflate"
35 | ) {
36 | val mTitle = it.thisObject.getObjectField("mTitleTextView") as TextView
37 | mTitle.setTextColor(Color.parseColor(value))
38 | }
39 | "com.miui.home.launcher.LauncherWidgetView".hookAfterMethod("onFinishInflate"
40 | ) {
41 | val mTitle = it.thisObject.getObjectField("mTitleTextView") as TextView
42 | mTitle.setTextColor(Color.parseColor(value))
43 | }
44 | "com.miui.home.launcher.ShortcutIcon".hookAfterMethod("fromXml", Int::class.javaPrimitiveType, launcherClass, ViewGroup::class.java, shortcutInfoClass
45 | ) {
46 | val buddyIconView = it.args[3].callMethod("getBuddyIconView", it.args[2]) as View
47 | val mTitle = buddyIconView.getObjectField("mTitle") as TextView
48 | mTitle.setTextColor(Color.parseColor(value))
49 | }
50 | "com.miui.home.launcher.ShortcutIcon".hookAfterMethod("createShortcutIcon", Int::class.javaPrimitiveType, launcherClass, ViewGroup::class.java
51 | ) {
52 | val buddyIcon = it.result as View
53 | val mTitle = buddyIcon.getObjectField("mTitle") as TextView
54 | mTitle.setTextColor(Color.parseColor(value))
55 | }
56 | "com.miui.home.launcher.common.Utilities".hookAfterMethod("adaptTitleStyleToWallpaper", Context::class.java, TextView::class.java, Int::class.javaPrimitiveType, Int::class.javaPrimitiveType
57 | ) {
58 | val mTitle = it.args[1] as TextView
59 | if (mTitle.id == mTitle.resources.getIdentifier("icon_title", "id", Config.hostPackage))
60 | mTitle.setTextColor(Color.parseColor(value))
61 | }
62 | } catch (e: Throwable) {
63 | Log.ex(e)
64 | }
65 | }
66 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/ModifyIconTitleFontSize.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.content.Context
4 | import android.util.TypedValue
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import android.widget.TextView
8 | import com.github.kyuubiran.ezxhelper.utils.Log
9 | import com.yuk.miuihome.utils.Config
10 | import com.yuk.miuihome.utils.OwnSP
11 | import com.yuk.miuihome.utils.ktx.callMethod
12 | import com.yuk.miuihome.utils.ktx.findClass
13 | import com.yuk.miuihome.utils.ktx.getObjectField
14 | import com.yuk.miuihome.utils.ktx.hookAfterMethod
15 |
16 | class ModifyIconTitleFontSize {
17 |
18 | fun init() {
19 | val value = OwnSP.ownSP.getFloat("iconTitleFontSize", -1f)
20 | val launcherClass = "com.miui.home.launcher.Launcher".findClass()
21 | val shortcutInfoClass = "com.miui.home.launcher.ShortcutInfo".findClass()
22 | if (value == -1f || value == 12f) return
23 | try {
24 | "com.miui.home.launcher.ItemIcon".hookAfterMethod("onFinishInflate"
25 | ) {
26 | val mTitle = it.thisObject.getObjectField("mTitle") as TextView
27 | mTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, value)
28 | }
29 | "com.miui.home.launcher.maml.MaMlWidgetView".hookAfterMethod(
30 | "onFinishInflate"
31 | ) {
32 | val mTitle = it.thisObject.getObjectField("mTitleTextView") as TextView
33 | mTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, value)
34 | }
35 | "com.miui.home.launcher.LauncherMtzGadgetView".hookAfterMethod("onFinishInflate"
36 | ) {
37 | val mTitle = it.thisObject.getObjectField("mTitleTextView") as TextView
38 | mTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, value)
39 | }
40 | "com.miui.home.launcher.LauncherWidgetView".hookAfterMethod("onFinishInflate"
41 | ) {
42 | val mTitle = it.thisObject.getObjectField("mTitleTextView") as TextView
43 | mTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, value)
44 | }
45 | "com.miui.home.launcher.ShortcutIcon".hookAfterMethod("fromXml", Int::class.javaPrimitiveType, launcherClass, ViewGroup::class.java, shortcutInfoClass
46 | ) {
47 | val buddyIconView = it.args[3].callMethod("getBuddyIconView", it.args[2]) as View
48 | val mTitle = buddyIconView.getObjectField("mTitle") as TextView
49 | mTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, value)
50 | }
51 | "com.miui.home.launcher.ShortcutIcon".hookAfterMethod("createShortcutIcon", Int::class.javaPrimitiveType, launcherClass, ViewGroup::class.java
52 | ) {
53 | val buddyIcon = it.result as View
54 | val mTitle = buddyIcon.getObjectField("mTitle") as TextView
55 | mTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, value)
56 | }
57 | "com.miui.home.launcher.common.Utilities".hookAfterMethod("adaptTitleStyleToWallpaper", Context::class.java, TextView::class.java, Int::class.javaPrimitiveType, Int::class.javaPrimitiveType
58 | ) {
59 | val mTitle = it.args[1] as TextView
60 | if (mTitle.id == mTitle.resources.getIdentifier("icon_title", "id", Config.hostPackage))
61 | mTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, value)
62 | }
63 | } catch (e: Throwable) {
64 | Log.ex(e)
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/ModifyIconTitleTopMargin.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.view.ViewGroup
4 | import android.widget.RelativeLayout
5 | import com.yuk.miuihome.utils.OwnSP
6 | import com.yuk.miuihome.utils.ktx.getObjectField
7 | import com.yuk.miuihome.utils.ktx.hookAfterMethod
8 | import kotlin.math.roundToInt
9 |
10 | class ModifyIconTitleTopMargin {
11 |
12 | fun init() {
13 | val titleTopMargin = OwnSP.ownSP.getInt("titleTopMargin", -1)
14 | if (titleTopMargin == -1) return
15 | "com.miui.home.launcher.ItemIcon".hookAfterMethod("onFinishInflate") {
16 | val mTitleContainer = it.thisObject.getObjectField("mTitleContainer") as ViewGroup
17 | val lp = mTitleContainer.layoutParams
18 | val opt = ((titleTopMargin - 11) * mTitleContainer.resources.displayMetrics.density).roundToInt()
19 | if (lp is RelativeLayout.LayoutParams) {
20 | lp.topMargin = opt
21 | mTitleContainer.layoutParams = lp
22 | } else {
23 | mTitleContainer.translationY = opt.toFloat()
24 | mTitleContainer.clipChildren = false
25 | mTitleContainer.clipToPadding = false
26 | (mTitleContainer.parent as ViewGroup).clipChildren = false
27 | (mTitleContainer.parent as ViewGroup).clipToPadding = false
28 | }
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/ModifyInfiniteScroll.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import com.yuk.miuihome.utils.OwnSP
4 | import com.yuk.miuihome.utils.ktx.callMethod
5 | import com.yuk.miuihome.utils.ktx.getIntField
6 | import com.yuk.miuihome.utils.ktx.hookAfterMethod
7 |
8 | class ModifyInfiniteScroll {
9 |
10 | fun init() {
11 | if (OwnSP.ownSP.getBoolean("infiniteScroll", false)) {
12 | "com.miui.home.launcher.ScreenView".hookAfterMethod("getSnapToScreenIndex", Int::class.javaPrimitiveType, Int::class.javaPrimitiveType, Int::class.javaPrimitiveType
13 | ) {
14 | if (it.args[0] !== it.result) return@hookAfterMethod
15 | val screenCount = it.thisObject.callMethod("getScreenCount") as Int
16 | if (it.args[2] as Int == -1 && it.args[0] as Int == 0) it.result = screenCount
17 | else if (it.args[2] as Int == 1 && it.args[0] as Int == screenCount - 1) it.result = 0
18 | }
19 | "com.miui.home.launcher.ScreenView".hookAfterMethod("getSnapUnitIndex", Int::class.javaPrimitiveType
20 | ) {
21 | val mCurrentScreenIndex = it.thisObject.getIntField("mCurrentScreenIndex")
22 | if (mCurrentScreenIndex != it.result as Int) return@hookAfterMethod
23 | val screenCount = it.thisObject.callMethod("getScreenCount") as Int
24 | if (it.result as Int == 0) it.result = screenCount
25 | else if (it.result as Int == screenCount - 1) it.result = 0
26 | }
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/ModifyPadA12DockBlur.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.annotation.SuppressLint
4 | import android.app.Activity
5 | import android.graphics.Color
6 | import android.os.Build
7 | import android.os.Bundle
8 | import android.view.ViewGroup
9 | import com.github.kyuubiran.ezxhelper.utils.Log
10 | import com.yuk.miuihome.utils.Config
11 | import com.yuk.miuihome.utils.OwnSP
12 | import com.yuk.miuihome.utils.ktx.hookAfterMethod
13 | import com.zhenxiang.blur.WindowBlurFrameLayout
14 | import com.zhenxiang.blur.model.CornersRadius
15 | import de.robv.android.xposed.XposedHelpers
16 |
17 | class ModifyPadA12DockBlur {
18 |
19 | @SuppressLint("DiscouragedApi")
20 | fun init() {
21 | if (!OwnSP.ownSP.getBoolean("PadDockBlur", false) || Build.VERSION.SDK_INT < 31) return
22 | try {
23 | "com.miui.home.launcher.Launcher".hookAfterMethod("onCreate", Bundle::class.java) {
24 | val activity = it.thisObject as Activity
25 | val view = activity.findViewById(activity.resources.getIdentifier("hotseat_background", "id", Config.hostPackage)) as ViewGroup
26 | val blur = WindowBlurFrameLayout(view.context)
27 | blur.blurController.apply {
28 | backgroundColour = Color.parseColor("#44FFFFFF")
29 | cornerRadius = CornersRadius.all(40f)
30 | }
31 | view.addView(blur)
32 | }
33 | } catch (e:XposedHelpers.ClassNotFoundError) {
34 | Log.ex(e)
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/ModifyRecents.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.graphics.Color
4 | import android.util.TypedValue
5 | import android.view.View
6 | import android.widget.ImageView
7 | import android.widget.TextView
8 | import com.yuk.miuihome.utils.OwnSP
9 | import com.yuk.miuihome.utils.ktx.*
10 |
11 | class ModifyRecents {
12 |
13 | fun init() {
14 | val recentsContainerClass = "com.miui.home.recents.views.RecentsContainer".findClass()
15 | val taskViewHeaderClass = "com.miui.home.recents.views.TaskViewHeader".findClass()
16 | val recentTextSize = OwnSP.ownSP.getFloat("recentTextSize", -1f)
17 | val emptyViewText: String = OwnSP.ownSP.getString("recentText", "").toString()
18 | val appCardBgColor = OwnSP.ownSP.getString("appCardBgColor", "")
19 | if (OwnSP.ownSP.getBoolean("smallWindow", false)) {
20 | recentsContainerClass.hookAfterMethod(
21 | "onFinishInflate"
22 | ) {
23 | val mTitle = it.thisObject.getObjectField("mTxtSmallWindow") as TextView
24 | mTitle.visibility = View.GONE
25 | }
26 | }
27 | if (OwnSP.ownSP.getBoolean("cleanUp", false)) {
28 | recentsContainerClass.hookAfterMethod(
29 | "onFinishInflate"
30 | ) {
31 | val mView = it.thisObject.getObjectField("mClearAnimView") as View
32 | mView.visibility = View.GONE
33 | }
34 | }
35 | if (recentTextSize != -1f) {
36 | taskViewHeaderClass.hookAfterMethod(
37 | "onFinishInflate"
38 | ) {
39 | val mTitle = it.thisObject.getObjectField("mTitleView") as TextView
40 | mTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, recentTextSize)
41 | }
42 | }
43 | if (OwnSP.ownSP.getBoolean("recentIcon", false)) {
44 | taskViewHeaderClass.hookAfterMethod(
45 | "onFinishInflate"
46 | ) {
47 | val mImage = it.thisObject.getObjectField("mIconView") as ImageView
48 | mImage.visibility = View.GONE
49 | }
50 | }
51 | if (emptyViewText != "") {
52 | "com.miui.home.recents.views.RecentsView".hookAfterMethod(
53 | "showEmptyView", Int::class.javaPrimitiveType
54 | ) {
55 | (it.thisObject.getObjectField("mEmptyView") as TextView).apply {
56 | this.text = emptyViewText
57 | }
58 | }
59 | }
60 | if (appCardBgColor != "") {
61 | "com.miui.home.recents.views.TaskViewThumbnail".findClass().hookAfterAllConstructors {
62 | it.thisObject.setIntField("mBgColorForSmallWindow", Color.parseColor(appCardBgColor))
63 | }
64 | }
65 | }
66 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/ModifyShortcutItemCount.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import com.yuk.miuihome.utils.OwnSP
4 | import com.yuk.miuihome.utils.ktx.callMethod
5 | import com.yuk.miuihome.utils.ktx.hookAfterMethod
6 |
7 | class ModifyShortcutItemCount {
8 |
9 | fun init() {
10 | val value = OwnSP.ownSP.getInt("shortcutCount", 6)
11 | if (!OwnSP.ownSP.getBoolean("unlockShortcutCount", false)) return
12 | "com.miui.home.launcher.shortcuts.AppShortcutMenu".hookAfterMethod("getMaxCountInCurrentOrientation") {
13 | it.result = value
14 | }
15 | "com.miui.home.launcher.shortcuts.AppShortcutMenu".hookAfterMethod("getMaxShortcutItemCount") {
16 | it.result = value
17 | }
18 | "com.miui.home.launcher.shortcuts.AppShortcutMenu".hookAfterMethod("getMaxVisualHeight") {
19 | it.result = it.thisObject.callMethod("getItemHeight")
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/ModifyShowDockIconTitles.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.content.Context
4 | import com.github.kyuubiran.ezxhelper.init.InitFields.moduleRes
5 | import com.yuk.miuihome.utils.OwnSP
6 | import com.yuk.miuihome.utils.ktx.hookAfterMethod
7 | import com.yuk.miuihome.utils.ktx.hookBeforeMethod
8 |
9 | class ModifyShowDockIconTitles {
10 |
11 | fun init() {
12 | if (!OwnSP.ownSP.getBoolean("showDockIconTitles", false)) return
13 | "com.miui.home.launcher.DeviceConfig".hookBeforeMethod("isHotseatsAppTitleHided") {
14 | it.result = false
15 | }
16 | "com.miui.home.launcher.DeviceConfig".hookAfterMethod(
17 | "calcHotSeatsHeight", Context::class.java, Boolean::class.java
18 | ) {
19 | val height = it.result as Int
20 | it.result = (height + 8 * moduleRes.displayMetrics.density).toInt()
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/ModifyTaskHorizontal.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.graphics.RectF
4 | import com.yuk.miuihome.utils.OwnSP
5 | import com.yuk.miuihome.utils.ktx.callMethod
6 | import com.yuk.miuihome.utils.ktx.callStaticMethod
7 | import com.yuk.miuihome.utils.ktx.findClass
8 | import com.yuk.miuihome.utils.ktx.hookAfterMethod
9 |
10 | class ModifyTaskHorizontal {
11 |
12 | fun init() {
13 | val value1 = OwnSP.ownSP.getFloat("task_horizontal1", -1f)
14 | val value2 = OwnSP.ownSP.getFloat("task_horizontal2", -1f)
15 | if ((value1 == -1f || value2 == -1f) || (value1 == 1f && value2 == 1f)) return
16 | "com.miui.home.recents.views.TaskStackViewsAlgorithmHorizontal".hookAfterMethod("scaleTaskView", RectF::class.java,
17 | ) {
18 | "com.miui.home.recents.util.Utilities".findClass().callStaticMethod("scaleRectAboutCenter", it.args[0], if (it.thisObject.callMethod("isLandscapeVisually") as Boolean) value2 else value1)
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/ModifyTaskVertical.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.graphics.RectF
4 | import com.github.kyuubiran.ezxhelper.init.InitFields.appContext
5 | import com.yuk.miuihome.utils.OwnSP
6 | import com.yuk.miuihome.utils.ktx.*
7 |
8 | class ModifyTaskVertical {
9 |
10 | fun init() {
11 | val value = OwnSP.ownSP.getFloat("task_vertical", 1000f) / 1000f
12 | if (value == 1f) return
13 | "com.miui.home.recents.views.TaskStackViewsAlgorithmVertical".replaceMethod("scaleTaskView", RectF::class.java
14 | ) {
15 | "com.miui.home.recents.util.Utilities".findClass().callStaticMethod("scaleRectAboutCenter", it.args[0], value * "com.miui.home.recents.util.Utilities".findClass().callStaticMethod("getTaskViewScale", appContext) as Float)
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/ModifyUnlockHotseatIcon.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import com.yuk.miuihome.utils.OwnSP
4 | import com.yuk.miuihome.utils.ktx.hookBeforeMethod
5 |
6 | class ModifyUnlockHotseatIcon {
7 |
8 | fun init() {
9 | if (!OwnSP.ownSP.getBoolean("unlockIcons", false)) return
10 | "com.miui.home.launcher.DeviceConfig".hookBeforeMethod("getHotseatMaxCount") {
11 | it.result = 99
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/ResourcesHook.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import android.content.res.Resources
4 | import com.github.kyuubiran.ezxhelper.init.InitFields.appContext
5 | import com.yuk.miuihome.BuildConfig
6 | import com.yuk.miuihome.XposedInit
7 | import com.yuk.miuihome.utils.OwnSP
8 | import com.yuk.miuihome.utils.ResourcesHookData
9 | import com.yuk.miuihome.utils.ResourcesHookMap
10 | import com.yuk.miuihome.utils.ktx.dp2px
11 | import com.yuk.miuihome.utils.ktx.findClass
12 | import com.yuk.miuihome.utils.ktx.hookBeforeAllMethods
13 | import com.yuk.miuihome.utils.ktx.hookBeforeMethod
14 | import de.robv.android.xposed.XC_MethodHook
15 | import de.robv.android.xposed.XposedBridge
16 |
17 | class ResourcesHook {
18 |
19 | private fun hook(param: XC_MethodHook.MethodHookParam) {
20 | try {
21 | val resName = appContext.resources.getResourceEntryName(param.args[0] as Int)
22 | val resType = appContext.resources.getResourceTypeName(param.args[0] as Int)
23 | if (hookMap.isKeyExist(resName))
24 | if (hookMap[resName]?.type == resType) {
25 | param.result = hookMap[resName]?.afterValue
26 | if (BuildConfig.DEBUG) XposedBridge.log("MiuiHome: [$resName] hooked, now it's ${hookMap[resName]?.afterValue}")
27 | }
28 | } catch (ignore: Exception) {
29 | }
30 | }
31 |
32 | fun init() {
33 | Resources::class.java.hookBeforeMethod("getBoolean", Int::class.javaPrimitiveType) { hook(it) }
34 | Resources::class.java.hookBeforeMethod("getDimension", Int::class.javaPrimitiveType) { hook(it) }
35 | Resources::class.java.hookBeforeMethod("getDimensionPixelOffset", Int::class.javaPrimitiveType) { hook(it) }
36 | Resources::class.java.hookBeforeMethod("getDimensionPixelSize", Int::class.javaPrimitiveType) { hook(it) }
37 | Resources::class.java.hookBeforeMethod("getInteger", Int::class.javaPrimitiveType) { hook(it) }
38 | Resources::class.java.hookBeforeMethod("getText", Int::class.javaPrimitiveType) { hook(it) }
39 |
40 | val value = OwnSP.ownSP.getFloat("recents_task_view_rounded_corners_radius", -1f)
41 | val value1 = OwnSP.ownSP.getFloat("recents_task_view_header_height", -1f)
42 | val value2 = OwnSP.ownSP.getInt("config_cell_count_x_drawer_mode", 3)
43 |
44 | if (OwnSP.ownSP.getBoolean("unlockGrids", false)) {
45 | val deviceClass = "com.miui.home.launcher.compat.LauncherCellCountCompatDevice".findClass()
46 | deviceClass.hookBeforeAllMethods("shouldUseDeviceValue") { it.result = false }
47 | hookMap["config_cell_count_x"] = ResourcesHookData("integer", 3)
48 | hookMap["config_cell_count_y"] = ResourcesHookData("integer", 4)
49 | hookMap["config_cell_count_x_min"] = ResourcesHookData("integer", 3)
50 | hookMap["config_cell_count_y_min"] = ResourcesHookData("integer", 4)
51 | hookMap["config_cell_count_x_max"] = ResourcesHookData("integer", 16)
52 | hookMap["config_cell_count_y_max"] = ResourcesHookData("integer", 18)
53 | if (XposedInit().checkVersionCode() == 427004546L && OwnSP.ownSP.getBoolean("unlockGrids", false)) hookMap["config_cell_count_x_drawer_mode"] = ResourcesHookData("integer", value2)
54 | }
55 |
56 | if (value != -1f && value != 20f) {
57 | hookMap["recents_task_view_rounded_corners_radius_min"] = ResourcesHookData("dimen", dp2px(value))
58 | hookMap["recents_task_view_rounded_corners_radius_max"] = ResourcesHookData("dimen", dp2px(value))
59 | }
60 |
61 | if (value1 != -1f && value1 != 40f)
62 | hookMap["recents_task_view_header_height"] = ResourcesHookData("dimen", dp2px(value1))
63 |
64 | }
65 |
66 | companion object {
67 | val hookMap = ResourcesHookMap()
68 | }
69 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/module/SetDeviceLevel.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.module
2 |
3 | import com.github.kyuubiran.ezxhelper.utils.Log
4 | import com.yuk.miuihome.utils.ktx.hookBeforeMethod
5 |
6 | class SetDeviceLevel : BaseClassAndMethodCheck {
7 |
8 | fun init() {
9 | try {
10 | "com.miui.home.launcher.common.DeviceLevelUtils".hookBeforeMethod("getDeviceLevel") {
11 | it.result = 2
12 | }
13 | "com.miui.home.launcher.common.CpuLevelUtils".hookBeforeMethod("getQualcommCpuLevel", String::class.java) {
14 | it.result = 2
15 | }
16 | "com.miui.home.launcher.DeviceConfig".hookBeforeMethod("isSupportCompleteAnimation") {
17 | it.result = true
18 | }
19 | "com.miui.home.launcher.common.DeviceLevelUtils".hookBeforeMethod("isLowLevelOrLiteDevice") {
20 | it.result = false
21 | }
22 | "com.miui.home.launcher.DeviceConfig".hookBeforeMethod("isDefaultIcon") {
23 | it.result = true
24 | }
25 | "com.miui.home.launcher.DeviceConfig".hookBeforeMethod("isMiuiLiteVersion") {
26 | it.result = false
27 | }
28 | runWithChecked {
29 | "com.miui.home.launcher.util.noword.NoWordSettingHelperKt".hookBeforeMethod("isNoWordAvailable") {
30 | it.result = true
31 | }
32 | }
33 | } catch (e: Throwable) {
34 | Log.ex(e)
35 | }
36 | }
37 |
38 | override fun classAndMethodList(): ArrayList = arrayListOf("com.miui.home.launcher.util.noword.NoWordSettingHelperKt", "isNoWordAvailable")
39 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/utils/Config.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.utils
2 |
3 | import com.yuk.miuihome.BuildConfig
4 |
5 | object Config {
6 | const val modulePackage = BuildConfig.APPLICATION_ID
7 | const val hostPackage = "com.miui.home"
8 | const val hostActivityProxy = "com.miui.home.settings.DefaultHomeSettings"
9 | const val SP_NAME = "MiuiHomePerf"
10 | const val TAG = "MiuiHome"
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/utils/OwnSP.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.utils
2 |
3 | import android.content.Context
4 | import android.content.SharedPreferences
5 | import com.github.kyuubiran.ezxhelper.init.InitFields.appContext
6 |
7 | object OwnSP {
8 |
9 | val ownSP: SharedPreferences = appContext.createDeviceProtectedStorageContext().getSharedPreferences(Config.SP_NAME, Context.MODE_PRIVATE)
10 |
11 | private val ownEditor: SharedPreferences.Editor = ownSP.edit()
12 |
13 | fun set(key: String, any: Any) {
14 | when (any) {
15 | is Int -> ownEditor.putInt(key, any)
16 | is Float -> ownEditor.putFloat(key, any)
17 | is String -> ownEditor.putString(key, any)
18 | is Boolean -> ownEditor.putBoolean(key, any)
19 | is Long -> ownEditor.putLong(key, any)
20 | }
21 | ownEditor.apply()
22 | }
23 |
24 | fun remove(key: String) {
25 | ownEditor.remove(key)
26 | ownEditor.apply()
27 | }
28 |
29 | fun clear() {
30 | ownEditor.clear()
31 | ownEditor.apply()
32 | }
33 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/utils/ResourcesHookData.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.utils
2 |
3 | data class ResourcesHookData(val type: String, val afterValue: Any)
4 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/utils/ResourcesHookMap.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.utils
2 |
3 | class ResourcesHookMap : HashMap() {
4 | fun isKeyExist(key: String): Boolean = getOrDefault(key, null) != null
5 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/utils/SPBackup.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.utils
2 |
3 | import android.app.Activity
4 | import android.content.Intent
5 | import android.content.SharedPreferences
6 | import org.json.JSONObject
7 |
8 | class SPBackup(private val activity: Activity, private val sp: SharedPreferences) {
9 |
10 | fun getWriteJson(): String {
11 | val json = JSONObject()
12 | val map = mutableMapOf()
13 | sp.all.forEach { (key: String, any: Any?) ->
14 | when (any) {
15 | is Int -> { map[key] = "int;$any" }
16 | is Float -> { map[key] = "float;$any" }
17 | is String -> { map[key] = "string;$any" }
18 | is Boolean -> { map[key] = "boolean;$any" }
19 | is Long -> { map[key] = "long;$any" }
20 | is Double -> { map[key] = "double;$any" }
21 | }
22 | }
23 | val config = JSONObject(map.toMap())
24 | json.put("config", config)
25 | return json.toString()
26 | }
27 |
28 | fun convertJsonToSP(text: String): Boolean {
29 | try {
30 | val json = JSONObject(text)
31 | val config = json.getJSONObject("config")
32 | val editor = sp.edit()
33 | editor.clear()
34 | config.keys().forEach {
35 | val rawValue = config[it] as String
36 | val type = rawValue.split(";")[0]
37 | val value = rawValue.split(";")[1]
38 | when (type) {
39 | "int" -> { editor.putInt(it, value.toInt()) }
40 | "float" -> { editor.putFloat(it, value.toFloat()) }
41 | "string" -> { editor.putString(it, value) }
42 | "boolean" -> { editor.putBoolean(it, value.toBoolean()) }
43 | "long" -> { editor.putLong(it, value.toLong()) }
44 | "double" -> { editor.putFloat(it, value.toFloat()) }
45 | else -> { throw RuntimeException("key: $it value: $value type: ${value::class.java.typeName}") }
46 | }
47 | }
48 | editor.apply()
49 | return true
50 | } catch (e: Exception) {
51 | return false
52 | }
53 | }
54 |
55 | fun requestWriteToFile(fileName: String) {
56 | val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
57 | addCategory(Intent.CATEGORY_OPENABLE)
58 | type = "text/plain"
59 | putExtra(Intent.EXTRA_TITLE, fileName)
60 | }
61 | activity.startActivityForResult(intent, createCode)
62 | }
63 |
64 | fun requestReadFromFile() {
65 | val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
66 | addCategory(Intent.CATEGORY_OPENABLE)
67 | type = "text/plain"
68 | }
69 | activity.startActivityForResult(intent, readCode)
70 | }
71 | companion object {
72 | const val createCode = 2333
73 | const val readCode = 114514
74 | }
75 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/utils/ViewBuilder.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.utils
2 |
3 | import android.content.Context
4 | import android.view.View
5 | import com.yuk.miuihome.view.base.BaseView
6 |
7 | object ViewBuilder {
8 |
9 | fun build(context: Context, view: BaseView): View? {
10 | if (view.hasLoad) return null
11 | return view.create(context).also { view.hasLoad = true }
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/utils/ktx/AppUtil.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.utils.ktx
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.res.Configuration
5 | import android.util.TypedValue
6 | import com.github.kyuubiran.ezxhelper.init.InitFields
7 |
8 | fun dp2px(dpValue: Float): Int = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, InitFields.appContext.resources.displayMetrics).toInt()
9 |
10 | fun px2dp(pxValue: Int): Int = (pxValue / InitFields.appContext.resources.displayMetrics.density + 0.5f).toInt()
11 |
12 | fun getDensityDpi(): Int = (InitFields.appContext.resources.displayMetrics.widthPixels / InitFields.appContext.resources.displayMetrics.density).toInt()
13 |
14 | fun isDarkMode(): Boolean = InitFields.appContext.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
15 |
16 | @SuppressLint("PrivateApi")
17 | @Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
18 | fun getProp(mKey: String): String = Class.forName("android.os.SystemProperties").getMethod("get", String::class.java).invoke(Class.forName("android.os.SystemProperties"), mKey).toString()
19 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/view/CustomSwitch.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.view
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.Context
5 | import android.widget.Switch
6 | import com.yuk.miuihome.utils.ktx.dp2px
7 | import java.lang.reflect.Field
8 |
9 | class CustomSwitch(context: Context) : Switch(context) {
10 |
11 | @SuppressLint("DiscouragedPrivateApi")
12 | override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
13 | super.onMeasure(widthMeasureSpec, heightMeasureSpec)
14 | val switchWidth: Field = Switch::class.java.getDeclaredField("mSwitchWidth")
15 | switchWidth.isAccessible = true
16 | switchWidth.setInt(this, dp2px(48f))
17 | }
18 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/view/HookSettingsActivity.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.view
2 |
3 | import android.content.Intent
4 | import android.os.Bundle
5 | import android.view.View
6 | import android.widget.ImageView
7 | import android.widget.TextView
8 | import android.widget.Toast
9 | import androidx.recyclerview.widget.LinearLayoutManager
10 | import androidx.recyclerview.widget.RecyclerView
11 | import com.github.kyuubiran.ezxhelper.utils.Log
12 | import com.github.kyuubiran.ezxhelper.utils.parasitics.TransferActivity
13 | import com.yuk.miuihome.R
14 | import com.yuk.miuihome.utils.OwnSP
15 | import com.yuk.miuihome.utils.SPBackup
16 | import com.yuk.miuihome.utils.ktx.dp2px
17 | import com.yuk.miuihome.view.adapter.ItemAdapter
18 | import com.yuk.miuihome.view.data.DataHelper
19 | import com.yuk.miuihome.view.data.Item
20 | import java.io.BufferedReader
21 | import java.io.InputStreamReader
22 | import kotlin.concurrent.thread
23 | import kotlin.system.exitProcess
24 |
25 | class HookSettingsActivity: TransferActivity() {
26 |
27 | val spBackup = SPBackup(this, OwnSP.ownSP)
28 | private val itemList = arrayListOf- ()
29 | private lateinit var recyclerView: RecyclerView
30 | private lateinit var adapter: ItemAdapter
31 | private lateinit var back: ImageView
32 | private lateinit var title: TextView
33 |
34 | override fun onCreate(savedInstanceState: Bundle?) {
35 | super.onCreate(savedInstanceState)
36 | setContentView(R.layout.settings_activity)
37 | window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
38 | DataHelper.currentActivity = this
39 | itemList.addAll(DataHelper.getItems())
40 | initBack()
41 | recyclerView = findViewById(R.id.settings_recycler)
42 | title = findViewById(R.id.title)
43 | val layoutManager = LinearLayoutManager(this)
44 | recyclerView.layoutManager = layoutManager
45 | adapter = ItemAdapter(itemList)
46 | recyclerView.adapter = adapter
47 | if (OwnSP.ownSP.getBoolean("isFirstUse", true)) showFirstUseDialog()
48 | recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
49 | override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
50 | super.onScrolled(recyclerView, dx, dy)
51 | val y = recyclerView.computeVerticalScrollOffset()
52 | val o = dp2px(100f)-y*2
53 | if (o > dp2px(0f)) title.setPadding(0, o,0,0)
54 | else title.setPadding(0, dp2px(0f),0,0)
55 | }
56 | })
57 | }
58 |
59 | private fun initBack() {
60 | back = findViewById(R.id.settings_back)
61 | back.setOnClickListener {
62 | if (DataHelper.thisItems == DataHelper.main) DataHelper.currentActivity.finish()
63 | else DataHelper.setItems(DataHelper.main)
64 | }
65 | }
66 |
67 | override fun onBackPressed() {
68 | if (DataHelper.thisItems != DataHelper.main) DataHelper.setItems(DataHelper.main)
69 | else super.onBackPressed()
70 | }
71 |
72 | private fun showFirstUseDialog() {
73 | CustomDialog(this).apply {
74 | setTitle(R.string.Welcome)
75 | setMessage(R.string.Tips)
76 | setCancelable(false)
77 | setCButton(R.string.Yes) {
78 | OwnSP.clear()
79 | OwnSP.set("isFirstUse",false)
80 | OwnSP.set("blurWhenOpenFolder", true)
81 | OwnSP.set("smoothAnimation", true)
82 | OwnSP.set("mamlDownload", true)
83 | OwnSP.set("blurLevel", "CompleteBlur")
84 | OwnSP.set("animationLevel", 1.0f)
85 | OwnSP.set("task_vertical", 1000.0f)
86 | OwnSP.set("task_horizontal1", 1.0f)
87 | OwnSP.set("task_horizontal2", 1.0f)
88 | OwnSP.set("folderColumns", 3)
89 | OwnSP.set("config_cell_count_x_drawer_mode", 3)
90 | OwnSP.set("appReturnAminSpend", 5f)
91 | dismiss()
92 | thread {
93 | Log.toast(msg = DataHelper.currentActivity.getString(R.string.Reboot2))
94 | Thread.sleep(1000)
95 | exitProcess(0)
96 | }
97 | }
98 | show()
99 | }
100 | }
101 |
102 | override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
103 | data ?: return
104 | val uri = data.data ?: return
105 | if (requestCode == SPBackup.createCode && resultCode == RESULT_OK) {
106 | val outputSteam = contentResolver.openOutputStream(uri)
107 | outputSteam?.use {
108 | it.write(spBackup.getWriteJson().toByteArray())
109 | it.flush()
110 | it.close()
111 | }
112 | }
113 | if (requestCode == SPBackup.readCode && resultCode == RESULT_OK) {
114 | val sb = StringBuilder()
115 | contentResolver.openInputStream(uri)?.use { steam ->
116 | BufferedReader(InputStreamReader(steam)).use { reader ->
117 | var line: String? = reader.readLine()
118 | while (line != null) {
119 | sb.append(line)
120 | line = reader.readLine()
121 | }
122 | }
123 | }
124 | if (spBackup.convertJsonToSP(sb.toString())) {
125 | Toast.makeText(this, getString(R.string.RestoreModuleSettingsSuccess), Toast.LENGTH_SHORT).show()
126 | thread {
127 | Thread.sleep(1000)
128 | exitProcess(0)
129 | }
130 | } else {
131 | Toast.makeText(this, getString(R.string.RestoreModuleSettingsFailed), Toast.LENGTH_SHORT).show()
132 | }
133 | }
134 | }
135 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/view/adapter/ItemAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.view.adapter
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.Context
5 | import android.util.TypedValue
6 | import android.view.ContextThemeWrapper
7 | import android.view.LayoutInflater
8 | import android.view.View
9 | import android.view.ViewGroup
10 | import android.widget.LinearLayout
11 | import android.widget.TextView
12 | import androidx.recyclerview.widget.RecyclerView
13 | import com.yuk.miuihome.R
14 | import com.yuk.miuihome.utils.ViewBuilder
15 | import com.yuk.miuihome.view.base.BaseView
16 | import com.yuk.miuihome.view.data.Item
17 |
18 | class ItemAdapter(private val itemList: List
- ) :
19 | RecyclerView.Adapter() {
20 |
21 | inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
22 | val settingsBaseLinearLayout: LinearLayout = view.findViewById(R.id.settings_linear_base)
23 | val settingsText: TextView = view.findViewById(R.id.settings_text)
24 | val settingsCustomView: LinearLayout = view.findViewById(R.id.settings_custom_view)
25 | }
26 |
27 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
28 | val view = LayoutInflater.from(parent.context).inflate(R.layout.item, parent, false)
29 | return ViewHolder(view)
30 | }
31 |
32 | override fun getItemViewType(position: Int): Int {
33 | return position
34 | }
35 |
36 | @SuppressLint("RtlHardcoded", "UseCompatLoadingForDrawables")
37 | override fun onBindViewHolder(holder: ViewHolder, position: Int) {
38 | val item = itemList[position]
39 | val customItems = item.customItems
40 | val testItems = item.list
41 | val context = holder.settingsText.context
42 |
43 | for (view: View in customItems) holder.settingsCustomView.addView(view)
44 | for (view: BaseView in testItems) {
45 | if (view.outside) {
46 | ViewBuilder.build(context, view)
47 | ?.let { holder.settingsBaseLinearLayout.addView(it) }
48 | } else {
49 | ViewBuilder.build(context, view)?.let { holder.settingsCustomView.addView(it) }
50 | }
51 | }
52 | }
53 |
54 | override fun getItemCount(): Int = itemList.size
55 |
56 | private fun getSystemColor(context: Context): Int {
57 | val typedValue = TypedValue()
58 | val contextThemeWrapper = ContextThemeWrapper(context, android.R.style.Theme_DeviceDefault)
59 | contextThemeWrapper.theme.resolveAttribute(android.R.attr.colorAccent, typedValue, true)
60 | return typedValue.data
61 | }
62 |
63 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/view/adapter/ListPopupWindowAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.view.adapter
2 |
3 | import android.content.Context
4 | import android.graphics.Typeface
5 | import android.graphics.drawable.GradientDrawable
6 | import android.graphics.drawable.StateListDrawable
7 | import android.util.TypedValue
8 | import android.view.Gravity
9 | import android.view.View
10 | import android.view.ViewGroup
11 | import android.widget.BaseAdapter
12 | import android.widget.ImageView
13 | import android.widget.LinearLayout
14 | import android.widget.TextView
15 | import com.yuk.miuihome.R
16 | import com.yuk.miuihome.utils.ktx.dp2px
17 |
18 | class ListPopupWindowAdapter(
19 | context: Context,
20 | array: ArrayList,
21 | private val currentValue: String?
22 | ) : BaseAdapter() {
23 | private val context: Context
24 | private val array: ArrayList
25 |
26 | private fun createRectangleDrawable(color: Int, radius: FloatArray): GradientDrawable {
27 | return try {
28 | GradientDrawable().apply {
29 | shape = GradientDrawable.RECTANGLE
30 | setColor(color)
31 | setStroke(0, 0)
32 | if (radius.size == 4) {
33 | cornerRadii = floatArrayOf(radius[0], radius[0], radius[1], radius[1], radius[2], radius[2], radius[3], radius[3])
34 | }
35 | }
36 | } catch (e: Exception) {
37 | GradientDrawable()
38 | }
39 | }
40 |
41 | private fun createStateListDrawable(pressedDrawable: GradientDrawable, normalDrawable: GradientDrawable): StateListDrawable {
42 | return StateListDrawable().apply {
43 | addState(intArrayOf(android.R.attr.state_focused), pressedDrawable)
44 | addState(intArrayOf(android.R.attr.state_pressed), pressedDrawable)
45 | addState(intArrayOf(-android.R.attr.state_focused), normalDrawable)
46 | }
47 | }
48 |
49 | fun getWidth(): Int {
50 | var maxWidth = 0
51 | for (t in array) {
52 | val textView = TextView(context).also { it.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT) }
53 | textView.text = t
54 | textView.measure(0, 0)
55 | maxWidth = if (maxWidth > textView.measuredWidth) maxWidth else textView.measuredWidth
56 | }
57 | return maxWidth
58 | }
59 |
60 | override fun getCount(): Int = array.size
61 |
62 | override fun getItem(position: Int): Any = array[position]
63 |
64 | override fun getItemId(position: Int): Long = position.toLong()
65 |
66 | override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
67 | return convertView
68 | ?: LinearLayout(context).apply {
69 | val thisText = array[position]
70 | orientation = LinearLayout.HORIZONTAL
71 | var radius = floatArrayOf(0f, 0f, 0f, 0f)
72 | val radiusFloat = dp2px(16f).toFloat()
73 | when (position) {
74 | 0 -> radius = floatArrayOf(radiusFloat, radiusFloat, 0f, 0f)
75 | array.size - 1 -> radius = floatArrayOf(0f, 0f, radiusFloat, radiusFloat)
76 | }
77 | val pressedDrawable = createRectangleDrawable(context.getColor(if (currentValue == thisText) R.color.popup_select_click else R.color.popup_background_click), radius)
78 | val normalDrawable = createRectangleDrawable(context.getColor(if (currentValue == thisText) R.color.popup_select else R.color.popup_background), radius)
79 | background = createStateListDrawable(pressedDrawable, normalDrawable)
80 | addView(TextView(context).apply {
81 | text = thisText
82 | isSingleLine = true
83 | setTextSize(TypedValue.COMPLEX_UNIT_SP,16f)
84 | typeface = Typeface.create(null, 500, false)
85 | setPadding(0, dp2px(18f), 0, dp2px(18f))
86 | if (currentValue == thisText) setTextColor(context.getColor(R.color.popup_select_text))
87 | }, LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1f).also { it.gravity = Gravity.START; it.marginStart = dp2px(25f); it.marginEnd = dp2px(25f) })
88 | addView(ImageView(context).apply {
89 | if (currentValue == thisText) background = context.getDrawable(R.drawable.ic_popup_select)
90 | }, LinearLayout.LayoutParams(dp2px(15f), dp2px(15f)).also { it.gravity = Gravity.CENTER_VERTICAL; it.marginEnd = dp2px(25f) })
91 | }
92 | }
93 |
94 | init {
95 | this.context = context
96 | this.array = array
97 | }
98 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/view/base/BaseView.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.view.base
2 |
3 | import android.content.Context
4 | import android.view.View
5 |
6 | abstract class BaseView : BaseProperties {
7 |
8 | var hasLoad = false
9 |
10 | abstract fun getType(): BaseView
11 |
12 | abstract fun create(context: Context): View
13 | }
14 |
15 | interface BaseProperties {
16 |
17 | val outside: Boolean
18 | get() = false
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/view/base/LineV.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.view.base
2 |
3 | import android.content.Context
4 | import android.view.View
5 | import android.widget.LinearLayout
6 | import com.yuk.miuihome.R
7 | import com.yuk.miuihome.utils.ktx.dp2px
8 |
9 | class LineV : BaseView() {
10 |
11 | override fun getType(): BaseView = this
12 |
13 | override fun create(context: Context): View {
14 | return View(context).also {
15 | val layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, dp2px(0.9f))
16 | layoutParams.setMargins(dp2px(25f), dp2px(16f), dp2px(25f), dp2px(16f))
17 | it.layoutParams = layoutParams
18 | it.setBackgroundColor(context.resources.getColor(R.color.line, null))
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/view/base/LinearContainerV.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.view.base
2 |
3 | import android.content.Context
4 | import android.view.View
5 | import android.widget.LinearLayout
6 | import com.yuk.miuihome.view.data.LayoutPair
7 |
8 | class LinearContainerV(private val orientation: Int, private val pairs: Array) : BaseView() {
9 | companion object {
10 | const val VERTICAL = LinearLayout.VERTICAL
11 | const val HORIZONTAL = LinearLayout.HORIZONTAL
12 | }
13 |
14 | override fun getType(): BaseView = this
15 |
16 | override fun create(context: Context): View {
17 | return LinearLayout(context).also {
18 | it.orientation = orientation
19 | for (pair in pairs) it.addView(pair.view, pair.layoutParams)
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/view/base/SubtitleV.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.view.base
2 |
3 | import android.content.Context
4 | import android.graphics.Typeface
5 | import android.view.View
6 | import com.yuk.miuihome.R
7 | import com.yuk.miuihome.utils.ktx.dp2px
8 | import com.yuk.miuihome.view.data.Padding
9 |
10 | class SubtitleV(
11 | val text: String? = null,
12 | val resId: Int? = null,
13 | private val onClickListener: View.OnClickListener? = null
14 | ) : BaseView() {
15 |
16 | override fun getType(): BaseView = this
17 |
18 | override fun create(context: Context): View {
19 | return TextV(text, resId, 13f, context.getColor(R.color.title), Padding(dp2px(25f), dp2px(13f), dp2px(25f), dp2px(13f)), Typeface.create(null, 500, false), onClickListener).create(context)
20 | }
21 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/view/base/TextV.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.view.base
2 |
3 | import android.content.Context
4 | import android.graphics.Typeface
5 | import android.util.TypedValue
6 | import android.view.View
7 | import android.widget.TextView
8 | import com.yuk.miuihome.R
9 | import com.yuk.miuihome.utils.ktx.dp2px
10 | import com.yuk.miuihome.view.data.Padding
11 |
12 | class TextV(
13 | var text: String? = null,
14 | var resId: Int? = null,
15 | val textSize: Float? = null,
16 | val textColor: Int? = null,
17 | private val padding: Padding? = null,
18 | private val typeface: Typeface? = null,
19 | val onClickListener: View.OnClickListener? = null
20 | ) : BaseView() {
21 |
22 | override fun getType(): BaseView = this
23 |
24 | override fun create(context: Context): View {
25 | return TextView(context).also { view ->
26 | text?.let { view.text = it }
27 | resId?.let { view.setText(it) }
28 | view.textAlignment = View.TEXT_ALIGNMENT_VIEW_START
29 | if (textSize == null)
30 | view.setTextSize(TypedValue.COMPLEX_UNIT_SP,18f)
31 | else
32 | view.setTextSize(TypedValue.COMPLEX_UNIT_SP,textSize)
33 | if (typeface == null)
34 | view.paint.typeface = Typeface.create(null, 500, false)
35 | else
36 | view.paint.typeface = typeface
37 | textColor?.let { view.setTextColor(it) }
38 | view.setPadding(dp2px(25f), dp2px(16f), dp2px(25f), dp2px(16f))
39 | padding?.let { view.setPadding(it.left, it.top, it.right, it.bottom) }
40 | onClickListener?.let { view.setOnClickListener(it); view.background = context.getDrawable(R.drawable.ic_click_check) }
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/view/base/TextWithArrowV.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.view.base
2 |
3 | import android.content.Context
4 | import android.view.Gravity
5 | import android.view.View
6 | import android.widget.ImageView
7 | import android.widget.LinearLayout
8 | import com.yuk.miuihome.R
9 | import com.yuk.miuihome.utils.ktx.dp2px
10 | import com.yuk.miuihome.view.data.LayoutPair
11 |
12 | class TextWithArrowV(
13 | private val textWithSummaryV: TextWithSummaryV,
14 | private val onClickListener: View.OnClickListener? = null
15 | ) : BaseView() {
16 |
17 | override fun getType(): BaseView = this
18 |
19 | override fun create(context: Context): View {
20 | return LinearContainerV(LinearContainerV.HORIZONTAL,
21 | arrayOf(
22 | LayoutPair(textWithSummaryV.create(context).also { it.setPadding(0, 0, 0, 0) }, LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)),
23 | LayoutPair(ImageView(context).also { view -> view.background = context.getDrawable(R.drawable.ic_right_arrow) }, LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { it.gravity = Gravity.CENTER_VERTICAL; it.marginEnd = dp2px(25f) }),
24 | )
25 | ).create(context).also { view -> onClickListener?.let { view.setOnClickListener(it); view.background = context.getDrawable(R.drawable.ic_click_check); view.setPadding(0, dp2px(16f), 0, dp2px(16f))} }
26 | }
27 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/view/base/TextWithSeekBarV.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.view.base
2 |
3 | import android.content.Context
4 | import android.graphics.Typeface
5 | import android.view.View
6 | import android.widget.LinearLayout
7 | import android.widget.SeekBar
8 | import android.widget.TextView
9 | import com.yuk.miuihome.R
10 | import com.yuk.miuihome.utils.OwnSP
11 | import com.yuk.miuihome.utils.ktx.dp2px
12 | import com.yuk.miuihome.view.data.LayoutPair
13 |
14 | class TextWithSeekBarV(
15 | private val textV: TextV,
16 | val key: String,
17 | private val min: Int,
18 | private val max: Int,
19 | val divide: Int = 1,
20 | private val defaultProgress: Int
21 | ) : BaseView() {
22 |
23 | override var outside = true
24 |
25 | override fun getType(): BaseView = this
26 |
27 | override fun create(context: Context): View {
28 | val minText = TextV(min.toString(), textSize = 12f, textColor = context.getColor(R.color.spinner), typeface = Typeface.create(null, 400, false)).create(context)
29 | val maxText = TextV(max.toString(), textSize = 12f, textColor = context.getColor(R.color.spinner), typeface = Typeface.create(null, 400, false)).create(context)
30 | val mutableText = TextV("", textSize = 12f, textColor = context.getColor(R.color.spinner), typeface = Typeface.create(null, 400, false)).create(context)
31 | val seekBar = SeekBar(context).also { view ->
32 | view.thumb = null
33 | view.maxHeight = dp2px(30f)
34 | view.minHeight = dp2px(30f)
35 | view.isIndeterminate = false
36 | view.progressDrawable = context.getDrawable(R.drawable.seekbar_progress_drawable)
37 | view.indeterminateDrawable = context.getDrawable(R.color.colorAccent)
38 | view.min = min
39 | view.max = max
40 | OwnSP.ownSP.getFloat(key, -2333f).let {
41 | if (it != -2333f) {
42 | view.progress = (it * divide).toInt()
43 | (mutableText as TextView).text = view.progress.toString()
44 | } else {
45 | view.progress = defaultProgress
46 | (mutableText as TextView).text = defaultProgress.toString()
47 | }
48 | }
49 | view.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
50 | override fun onProgressChanged(p0: SeekBar?, p1: Int, p2: Boolean) {
51 | OwnSP.ownSP.edit().run {
52 | (mutableText as TextView).text = p1.toString()
53 | putFloat(key, p1.toFloat() / divide)
54 | apply()
55 | }
56 | }
57 |
58 | override fun onStartTrackingTouch(p0: SeekBar?) {}
59 |
60 | override fun onStopTrackingTouch(p0: SeekBar?) {}
61 | })
62 | }
63 | return LinearContainerV(LinearContainerV.VERTICAL,
64 | arrayOf(
65 | LayoutPair(textV.create(context).also { it.setPadding(dp2px(25f), dp2px(16f), dp2px(25f), dp2px(8f)) }, LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)),
66 | LayoutPair(seekBar.also { it.setPadding(dp2px(25f), 0, dp2px(25f), 0) }, LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)),
67 | LayoutPair(
68 | LinearContainerV(LinearContainerV.HORIZONTAL,
69 | arrayOf(
70 | LayoutPair(minText.also { it.textAlignment = TextView.TEXT_ALIGNMENT_VIEW_START; it.setPadding(0, dp2px(8f), 0, dp2px(16f)) }, LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)),
71 | LayoutPair(mutableText.also { it.textAlignment = TextView.TEXT_ALIGNMENT_CENTER; it.setPadding(0, dp2px(8f), 0, dp2px(16f)) }, LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)),
72 | LayoutPair(maxText.also { it.textAlignment = TextView.TEXT_ALIGNMENT_VIEW_END; it.setPadding(0, dp2px(8f), 0, dp2px(16f)) }, LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f))
73 | )
74 | ).create(context).also { it.setPadding(dp2px(25f), 0, dp2px(25f), 0) }, LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
75 | )
76 | )
77 | ).create(context)
78 | }
79 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/view/base/TextWithSpinnerV.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.view.base
2 |
3 | import android.animation.ValueAnimator
4 | import android.annotation.SuppressLint
5 | import android.content.Context
6 | import android.os.Build
7 | import android.view.Gravity
8 | import android.view.HapticFeedbackConstants
9 | import android.view.MotionEvent
10 | import android.view.View
11 | import android.widget.ImageView
12 | import android.widget.LinearLayout
13 | import android.widget.ListPopupWindow
14 | import android.widget.TextView
15 | import com.yuk.miuihome.R
16 | import com.yuk.miuihome.utils.ktx.dp2px
17 | import com.yuk.miuihome.view.adapter.ListPopupWindowAdapter
18 | import com.yuk.miuihome.view.data.DataHelper
19 | import com.yuk.miuihome.view.data.LayoutPair
20 |
21 | class TextWithSpinnerV(
22 | private val textV: TextV,
23 | var select: String?,
24 | val array: ArrayList,
25 | private val callBacks: ((String) -> Unit)? = null
26 | ) : BaseView() {
27 |
28 | override var outside = true
29 |
30 | override fun getType(): BaseView = this
31 |
32 | private fun setBackgroundAlpha(bgAlpha: Float) {
33 | val lp = DataHelper.currentActivity.window.attributes
34 | lp.alpha = bgAlpha
35 | DataHelper.currentActivity.window.attributes = lp
36 | }
37 |
38 | @SuppressLint("ClickableViewAccessibility", "RtlHardcoded")
39 | override fun create(context: Context): View {
40 | val text = TextView(context)
41 | val popup = ListPopupWindow(context).apply {
42 | setBackgroundDrawable(context.getDrawable(R.drawable.rounded_corners_pop))
43 | setAdapter(ListPopupWindowAdapter(context, array, select.toString()))
44 | verticalOffset = dp2px(-100f)
45 | width = ListPopupWindowAdapter(context, array, select.toString()).getWidth() + dp2px(125f)
46 | isModal = true
47 | setOnItemClickListener { parent, _, position, _ ->
48 | val p0 = parent.getItemAtPosition(position).toString()
49 | text.text = p0
50 | setAdapter(ListPopupWindowAdapter(context, array, p0))
51 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) parent.performHapticFeedback(HapticFeedbackConstants.CONFIRM, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING)
52 | else parent.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING)
53 | callBacks?.let { it -> it(p0) }
54 | dismiss()
55 | }
56 | setOnDismissListener {
57 | val animator = ValueAnimator.ofFloat(0.7f, 1f).setDuration(300)
58 | animator.addUpdateListener { animation -> setBackgroundAlpha(animation.animatedValue as Float) }
59 | animator.start()
60 | }
61 | }
62 | val spinner = LinearContainerV(LinearContainerV.HORIZONTAL,
63 | arrayOf(
64 | LayoutPair(text.also { it.textAlignment = View.TEXT_ALIGNMENT_VIEW_START; it.setTextColor(context.getColor(R.color.spinner)); it.text = select; it.textSize = 16f }, LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1f).also { it.marginStart = dp2px(30f); it.marginEnd = dp2px(6f); it.gravity = Gravity.CENTER_VERTICAL + Gravity.END }),
65 | LayoutPair(ImageView(context).also { it.background = context.getDrawable(R.drawable.ic_up_down) }, LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { it.gravity = Gravity.CENTER_VERTICAL })
66 | )
67 | )
68 | return LinearContainerV(LinearContainerV.HORIZONTAL,
69 | arrayOf(
70 | LayoutPair(textV.create(context).also { it.setPadding(dp2px(25f), 0, dp2px(25f), 0) }, LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)),
71 | LayoutPair(spinner.create(context).also { it.setPadding(0, 0, 0, 0)}, LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { it.gravity = Gravity.CENTER_VERTICAL; it.marginEnd = dp2px(25f) })
72 | )
73 | ).create(context).also {
74 | it.setOnTouchListener { view, motionEvent ->
75 | when (motionEvent.action) {
76 | MotionEvent.ACTION_UP -> {
77 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) it.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING)
78 | else it.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING)
79 | val animator = ValueAnimator.ofFloat(1f, 0.7f).setDuration(300)
80 | animator.addUpdateListener { animation -> setBackgroundAlpha(animation.animatedValue as Float) }
81 | animator.start()
82 | val halfWidth = view.width / 2
83 | if (halfWidth >= motionEvent.x) {
84 | popup.apply {
85 | horizontalOffset = dp2px(20f)
86 | setDropDownGravity(Gravity.LEFT)
87 | anchorView = view
88 | show()
89 | }
90 | } else {
91 | popup.apply {
92 | horizontalOffset = dp2px(-20f)
93 | setDropDownGravity(Gravity.RIGHT)
94 | anchorView = view
95 | show()
96 | }
97 | }
98 | it.background = context.getDrawable(R.drawable.ic_main_bg)
99 | }
100 | MotionEvent.ACTION_DOWN -> {
101 | it.background = context.getDrawable(R.drawable.ic_main_down_bg)
102 | }
103 | MotionEvent.ACTION_MOVE -> {
104 | it.background = context.getDrawable(R.drawable.ic_main_down_bg)
105 | }
106 | MotionEvent.ACTION_CANCEL -> {
107 | it.background = context.getDrawable(R.drawable.ic_main_bg)
108 | }
109 | }
110 | return@setOnTouchListener true
111 | }
112 | it.setPadding(0, dp2px(16f), 0, dp2px(16f))
113 | }
114 | }
115 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/view/base/TextWithSummaryV.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.view.base
2 |
3 | import android.content.Context
4 | import android.graphics.Typeface
5 | import android.util.TypedValue
6 | import android.view.View
7 | import android.widget.LinearLayout
8 | import android.widget.TextView
9 | import com.yuk.miuihome.R
10 | import com.yuk.miuihome.utils.ktx.dp2px
11 | import com.yuk.miuihome.view.data.LayoutPair
12 |
13 | class TextWithSummaryV(
14 | private val textV: TextV = TextV(),
15 | private val title: String? = null,
16 | private val titleResId: Int? = null,
17 | private val summary: String? = null,
18 | private val summaryResId: Int? = null,
19 | ) : BaseView() {
20 |
21 | override fun getType(): BaseView = this
22 |
23 | override fun create(context: Context): View {
24 | return LinearContainerV(LinearContainerV.VERTICAL, arrayOf(
25 | LayoutPair(textV.also { view -> title.let { view.text = it }; titleResId?.let { view.resId = it } }.create(context).also { it.setPadding(dp2px(25f), 0, dp2px(25f), 0) }, LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)),
26 | LayoutPair(
27 | TextView(context).also { view ->
28 | summary?.let { view.text = it }
29 | summaryResId?.let { view.setText(it) }
30 | view.setTextColor(context.getColor(R.color.spinner))
31 | view.setTextSize(TypedValue.COMPLEX_UNIT_SP, 13f)
32 | view.paint.typeface = Typeface.create(null, 400, false)
33 | view.setPadding(dp2px(25f), 0, dp2px(25f), 0)
34 | if (summary == null && summaryResId == null) view.visibility = View.GONE },
35 | LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)
36 | )
37 | )).create(context).also { it.setPadding(dp2px(25f), dp2px(16f), dp2px(25f), dp2px(16f)) }
38 | }
39 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/view/base/TextWithSwitchV.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.view.base
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.Context
5 | import android.view.Gravity
6 | import android.view.MotionEvent
7 | import android.view.View
8 | import android.widget.CompoundButton
9 | import android.widget.LinearLayout
10 | import com.yuk.miuihome.R
11 | import com.yuk.miuihome.utils.OwnSP
12 | import com.yuk.miuihome.utils.ktx.dp2px
13 | import com.yuk.miuihome.view.CustomSwitch
14 | import com.yuk.miuihome.view.data.LayoutPair
15 |
16 | class TextWithSwitchV(
17 | private val textWithSummaryV: TextWithSummaryV,
18 | private val key: String,
19 | private var customOnCheckedChangeListener: CompoundButton.OnCheckedChangeListener? = null
20 | ) : BaseView() {
21 |
22 | override fun getType(): BaseView = this
23 |
24 | @SuppressLint("ClickableViewAccessibility")
25 | override fun create(context: Context): View {
26 | val switchV = CustomSwitch(context).also {
27 | it.background = null
28 | it.setThumbResource(R.drawable.switch_thumb)
29 | it.setTrackResource(R.drawable.switch_track)
30 | it.isChecked = OwnSP.ownSP.getBoolean(key, false)
31 | it.setOnCheckedChangeListener { compoundButton, b ->
32 | customOnCheckedChangeListener?.onCheckedChanged(compoundButton, b)
33 | OwnSP.ownSP.edit().run {
34 | putBoolean(key, b)
35 | apply()
36 | }
37 | }
38 | }
39 | return LinearContainerV(
40 | LinearContainerV.HORIZONTAL,
41 | arrayOf(
42 | LayoutPair(textWithSummaryV.create(context).also { it.setPadding(0, dp2px(16f), 0, dp2px(16f)) }, LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1f).also { it.gravity = Gravity.CENTER_VERTICAL }),
43 | LayoutPair(switchV.also { it.setPadding(0, dp2px(16f), 0, dp2px(16f)) }, LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { it.gravity = Gravity.CENTER_VERTICAL; it.setMargins(0, 0, 0, 0); it.marginEnd = dp2px(25f)})
44 | )
45 | ).create(context).also {
46 | it.setOnTouchListener { _, motionEvent ->
47 | when (motionEvent.action) {
48 | MotionEvent.ACTION_UP -> {
49 | it.background = context.getDrawable(R.drawable.ic_main_bg)
50 | switchV.also { switch ->
51 | OwnSP.ownSP.edit().run {
52 | if (OwnSP.ownSP.getBoolean(key, false)) putBoolean(key, false)
53 | else putBoolean(key, true)
54 | apply()
55 | }
56 | switch.isChecked = OwnSP.ownSP.getBoolean(key, false)
57 | }
58 | }
59 | MotionEvent.ACTION_DOWN -> {
60 | it.background = context.getDrawable(R.drawable.ic_main_down_bg)
61 | }
62 | MotionEvent.ACTION_MOVE -> {
63 | it.background = context.getDrawable(R.drawable.ic_main_down_bg)
64 | }
65 | MotionEvent.ACTION_CANCEL -> {
66 | it.background = context.getDrawable(R.drawable.ic_main_bg)
67 | }
68 | }
69 | return@setOnTouchListener true
70 | }
71 | }
72 | }
73 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/view/data/Item.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.view.data
2 |
3 | import android.view.View
4 | import com.yuk.miuihome.view.base.BaseView
5 |
6 | data class Item(
7 | val customItems: List = arrayListOf(),
8 | val list: List = arrayListOf()
9 | )
10 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/view/data/LayoutPair.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.view.data
2 |
3 | import android.view.View
4 | import android.view.ViewGroup
5 |
6 | data class LayoutPair(
7 | val view: View,
8 | val layoutParams: ViewGroup.LayoutParams
9 | )
10 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/yuk/miuihome/view/data/Padding.kt:
--------------------------------------------------------------------------------
1 | package com.yuk.miuihome.view.data
2 |
3 | data class Padding(
4 | val left: Int,
5 | val top: Int,
6 | val right: Int,
7 | val bottom: Int
8 | )
9 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/zhenxiang/blur/BackgroundBlurDrawableExtensions.kt:
--------------------------------------------------------------------------------
1 | package com.zhenxiang.blur
2 |
3 | import com.android.internal.graphics.drawable.BackgroundBlurDrawable
4 | import org.lsposed.hiddenapibypass.HiddenApiBypass
5 |
6 | fun BackgroundBlurDrawable.setColor(color: Int) {
7 | HiddenApiBypass.invoke(BackgroundBlurDrawable::class.java, this, "setColor", color)
8 | }
9 |
10 | fun BackgroundBlurDrawable.setBlurRadius(blurRadius: Int) {
11 | HiddenApiBypass.invoke(BackgroundBlurDrawable::class.java, this, "setBlurRadius", blurRadius)
12 | }
13 |
14 | fun BackgroundBlurDrawable.setCornerRadius(cornerRadiusTL: Float, cornerRadiusTR: Float, cornerRadiusBL: Float, cornerRadiusBR: Float) {
15 | HiddenApiBypass.invoke(BackgroundBlurDrawable::class.java, this, "setCornerRadius", cornerRadiusTL, cornerRadiusTR, cornerRadiusBL, cornerRadiusBR)
16 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/zhenxiang/blur/SystemBlurController.kt:
--------------------------------------------------------------------------------
1 | package com.zhenxiang.blur
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.Context
5 | import android.graphics.Color
6 | import android.graphics.drawable.ShapeDrawable
7 | import android.graphics.drawable.shapes.RoundRectShape
8 | import android.os.Build
9 | import android.view.View
10 | import android.view.WindowManager
11 | import com.android.internal.graphics.drawable.BackgroundBlurDrawable
12 | import com.zhenxiang.blur.model.CornersRadius
13 | import java.util.function.Consumer
14 |
15 | class SystemBlurController(
16 | private val view: View,
17 | backgroundColour: Int = Color.TRANSPARENT,
18 | blurRadius: Int = 100,
19 | cornerRadius: CornersRadius = CornersRadius.all(0f),
20 | ) : View.OnAttachStateChangeListener {
21 |
22 | private var windowManager: WindowManager? = null
23 | private val crossWindowBlurListener = Consumer{ blurEnabled = it }
24 | private var blurEnabled: Boolean = false
25 | set(value) {
26 | if (value != field) {
27 | field = value
28 | updateBackgroundColour()
29 | updateBlurRadius()
30 | }
31 | }
32 | var backgroundColour = backgroundColour
33 | set(value) {
34 | field = value
35 | updateBackgroundColour()
36 | }
37 | var blurRadius = blurRadius
38 | set(value) {
39 | field = value
40 | updateBlurRadius()
41 | }
42 | var cornerRadius = cornerRadius
43 | set(value) {
44 | field = value
45 | when (val bg = view.background) {
46 | is BackgroundBlurDrawable -> setCornerRadius(bg, value)
47 | is ShapeDrawable -> bg.shape = getShapeFromCorners(value)
48 | }
49 | }
50 |
51 | init {
52 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
53 | // On api 31 and above background init is done in onViewAttachedToWindow
54 | view.addOnAttachStateChangeListener(this)
55 | } else {
56 | // On pre api 31 init background here
57 | val shape = ShapeDrawable()
58 | shape.shape = getShapeFromCorners(cornerRadius)
59 | shape.paint.color = backgroundColour
60 | view.background = shape
61 | }
62 | }
63 |
64 | @SuppressLint("NewApi")
65 | override fun onViewAttachedToWindow(v: View) {
66 | windowManager = getWindowManager(view.context).apply {
67 | blurEnabled = isCrossWindowBlurEnabled
68 | addCrossWindowBlurEnabledListener(crossWindowBlurListener)
69 | }
70 | view.createBackgroundBlurDrawable()?.let {
71 | // Configure blur drawable with current values
72 | it.setColor(backgroundColour)
73 | it.setBlurRadius(blurRadius)
74 | setCornerRadius(it, cornerRadius)
75 | view.background = it
76 | }
77 | }
78 |
79 | @SuppressLint("NewApi")
80 | override fun onViewDetachedFromWindow(_v: View) {
81 | // Clear blur drawable
82 | if (view.background is BackgroundBlurDrawable) {
83 | view.background = null
84 | }
85 | windowManager?.removeCrossWindowBlurEnabledListener(crossWindowBlurListener)
86 | windowManager = null
87 | }
88 |
89 | private fun updateBackgroundColour() {
90 | val bg = view.background
91 | when (bg) {
92 | is BackgroundBlurDrawable -> bg.setColor(backgroundColour)
93 | is ShapeDrawable -> bg.paint.color = backgroundColour
94 | }
95 | bg?.invalidateSelf()
96 | }
97 |
98 | private fun updateBlurRadius() {
99 | val bg = view.background
100 | if (bg is BackgroundBlurDrawable) {
101 | bg.setBlurRadius(if (blurEnabled) blurRadius else 0)
102 | }
103 | }
104 |
105 | private fun setCornerRadius(blurDrawable: BackgroundBlurDrawable, corners: CornersRadius) {
106 | blurDrawable.setCornerRadius(corners.topLeft, corners.topRight, corners.bottomLeft, corners.bottomRight)
107 | }
108 |
109 | private fun getShapeFromCorners(corners: CornersRadius): RoundRectShape {
110 | return RoundRectShape(getCornersFloatArray(corners), null, null)
111 | }
112 |
113 | private fun getCornersFloatArray(corners: CornersRadius): FloatArray {
114 | return floatArrayOf(corners.topLeft, corners.topLeft, corners.topRight, corners.topRight, corners.bottomRight, corners.bottomRight, corners.bottomLeft, corners.bottomLeft)
115 | }
116 |
117 | private fun getWindowManager(context: Context): WindowManager {
118 | return context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
119 | }
120 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/zhenxiang/blur/ViewExtensions.kt:
--------------------------------------------------------------------------------
1 | package com.zhenxiang.blur
2 |
3 | import android.util.Log
4 | import android.view.View
5 | import android.view.ViewRootImpl
6 | import com.android.internal.graphics.drawable.BackgroundBlurDrawable
7 | import org.lsposed.hiddenapibypass.HiddenApiBypass
8 |
9 | fun View.createBackgroundBlurDrawable(): BackgroundBlurDrawable? {
10 |
11 | return try {
12 | val getViewRootImpl = HiddenApiBypass.invoke(View::class.java, this, "getViewRootImpl") as ViewRootImpl
13 | HiddenApiBypass.invoke(ViewRootImpl::class.java, getViewRootImpl, "createBackgroundBlurDrawable") as BackgroundBlurDrawable
14 | } catch (e: Exception) {
15 | Log.w(null, e)
16 | null
17 | }
18 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/zhenxiang/blur/WindowBlurFrameLayout.kt:
--------------------------------------------------------------------------------
1 | package com.zhenxiang.blur
2 |
3 | import android.content.Context
4 | import android.widget.FrameLayout
5 |
6 | class WindowBlurFrameLayout constructor(context: Context) : FrameLayout(context) {
7 | val blurController: SystemBlurController = SystemBlurController(this)
8 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/zhenxiang/blur/WindowBlurLinearLayout.kt:
--------------------------------------------------------------------------------
1 | package com.zhenxiang.blur
2 |
3 | import android.content.Context
4 | import android.widget.LinearLayout
5 |
6 | class WindowBlurLinearLayout constructor(context: Context) : LinearLayout(context) {
7 | val blurController: SystemBlurController = SystemBlurController(this)
8 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/com/zhenxiang/blur/model/CornerRadius.kt:
--------------------------------------------------------------------------------
1 | package com.zhenxiang.blur.model
2 |
3 | data class CornersRadius(
4 | val topLeft: Float,
5 | val topRight: Float,
6 | val bottomLeft: Float,
7 | val bottomRight: Float,
8 | ) {
9 |
10 | companion object {
11 | fun all(radius: Float): CornersRadius {
12 | return CornersRadius(radius, radius, radius, radius)
13 | }
14 |
15 | fun custom(
16 | topLeft: Float,
17 | topRight: Float,
18 | bottomLeft: Float,
19 | bottomRight: Float
20 | ): CornersRadius {
21 | return CornersRadius(topLeft, topRight, bottomLeft, bottomRight)
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button_left_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button_left_background_no_pressed.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button_left_background_pressed.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button_right_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button_right_background_no_pressed.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button_right_background_pressed.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/dialog_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/dialog_pad_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/edit_view_background.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_action_back.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_click_check.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
24 |
27 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_main_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_main_down_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_popup_select.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_right_arrow.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_up_down.xml:
--------------------------------------------------------------------------------
1 |
7 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/rounded_corners_pop.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/seekbar_progress_drawable.xml:
--------------------------------------------------------------------------------
1 |
2 | -
3 |
4 |
5 |
11 |
12 |
13 | -
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/switch_thumb.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/switch_track.xml:
--------------------------------------------------------------------------------
1 |
2 | -
3 |
4 |
5 |
6 |
7 |
8 | -
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
17 |
18 |
29 |
30 |
35 |
36 |
47 |
48 |
60 |
61 |
62 |
63 |
69 |
70 |
84 |
85 |
100 |
101 |
115 |
116 |
117 |
118 |
119 |
120 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_pad_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
26 |
27 |
32 |
33 |
44 |
45 |
57 |
58 |
59 |
60 |
66 |
67 |
81 |
82 |
97 |
98 |
112 |
113 |
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
22 |
23 |
24 |
25 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/settings_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
24 |
25 |
35 |
36 |
37 |
38 |
42 |
43 |
--------------------------------------------------------------------------------
/app/src/main/res/values-hi/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | एडवांस सेटिंग
4 | मिउई विजेट्स को क्लासिक विजेट में प्रदर्शित होने दें
5 | स्टेटस बार क्लॉक हमेशा दिखाएं
6 | जेस्चर एनीमेशन गति
7 | टास्क व्यू एप्लिकेशन आइकन और नामों के बीच की दूरी
8 | फोल्डर ब्लर इनेबल करें
9 | कैंसिल करें
10 | सारी सेटिंग्स रीसेट करें
11 | फ़ोल्डर के अंदर एप्लिकेशन खोलते समय फ़ोल्डर बंद करें
12 | पूरा ब्लर करें
13 | डिफ़ॉल्ट
14 | मिउई लॉन्चर के लिए हुक
15 | फ़ोल्डर सेटिंग्स
16 | रीसेंट स्क्रीन में स्टेटस बार छुपाएं
17 | रीसेंट में एप्लिकेशन आइकन छुपाएं
18 | रीसेंट में क्लीन ऑल बटन छुपाएं
19 | \"फ़्लोटिंग विंडो\" को रीसेंट से हटा दें
20 | विजेट लेबल छुपाएं
21 | हॉरिजॉन्टल रीसेंट के लिए थंबनेल साइज
22 | लॉन्चर अनंत स्क्रॉल
23 | जल तरंग इफ़ेक्ट डाउनलोड
24 | मॉड्यूल विशेषताएं
25 | मॉड्यूल सेटिंग्स
26 | नो ब्लर
27 | अन्य विशेषताएं
28 | ट्रू · हॉरिजॉन्टल रीसेंट
29 | लॉन्चर फिर से शुरू करें
30 | लॉन्चर फिर से एक सेकंड में शुरू होगा!
31 | राउंडेड कॉर्नर्स थंबनेल का आकार
32 | डॉक में एप्लीकेशन का नाम दिखाएं
33 | सरल एनिमेशन
34 | सरल ब्लर
35 | स्मूथ एनीमेशन
36 | थंबनेल लेबल टेक्स्ट का आकार
37 | रीसेंट ब्लर स्तर
38 | ब्लर परीक्षण
39 | प्रायोगिक विशेषताएं
40 | यह पता चला है कि आप पहली बार इस मॉड्यूल का उपयोग कर रहे हैं, मॉड्यूल डिफ़ॉल्ट मूल्य सेट करेगा, और फिर सिस्टम लॉन्चर को पुनरारंभ करें|\nयदि आपको और सेटिंग्स की आवश्यकता है, कृपया मिउई लांचर के पुनः आरंभ होने की प्रतीक्षा करें और \"होम स्क्रीन\" सेटिंग्स को दुबारा खोलें|
41 | ग्रिड प्रतिबंध को अनलॉक करें
42 | लंबवत रीसेंट के लिए थंबनेल आकार
43 | रीसेंट के वॉलपेपर को अँधेरा करने वाला फीचर बंद करें
44 | स्वागत हे!
45 | विजेट विशेषताएं
46 | क्लासिक विजेट को \"ऐप वॉल्ट\ ले जाने दें"
47 | हां
48 | आइकन परछाई तथा प्रतिबिंब दिखाएँ
49 | सभी ऐप्स को फ़्लोटिंग विंडोज़ का उपयोग करने दें
50 | लो-एंड डिवाइस पर नया विजेट स्टोर सक्षम करें
51 | अनुशंसित सर्वर अक्षम करें
52 | एवरीथिंग मोड के साथ लॉन्चर को ऑप्टिमाइज़ करें
53 | यह डॉक सेटिंग्स को उसके डिफ़ॉल्ट मूल्य पर पुनर्स्थापित करेगा और सिस्टम लॉन्चर को पुनरारंभ करेगा|
54 | पृष्ठ संकेतक निकालें
55 | \"आल\" को ऐप काटेगोरिएस से छुपाये
56 | फ़ोल्डर कॉलम गणना
57 | संपूर्ण फ़ोल्डर\'स चौड़ाई का इस्तेमाल करें
58 | आइकन लेबल फ़ॉन्ट आकार
59 | जब रीसेंट में कोई बैकग्राउंड न हो तो टेक्स्ट डिस्प्ले को अनुकूलित करें
60 |
61 |
--------------------------------------------------------------------------------
/app/src/main/res/values-in/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Fitur Special
4 | Izinkan agar Widget MIUI dimunculkan pada menu klasik
5 | Selalu tampilkan jam statusbar
6 | Kecepatan animasi gesture
7 | Kejauhan antara nama aplikasi dan ikon aplikasi di recent
8 | Aktifkan blur pada saat dalam folder
9 | Batalkan
10 | Reset ke pengaturan awal
11 | Tutup folder saat animasi aplikasi sedang berjalan
12 | Blur komplit
13 | Default
14 | Hook untuk Launcher MIUI
15 | Pengaturan folder
16 | Sembunyikan statusbar saat dalam menu terbaru
17 | Sembunyikan icon aplikasi saat dalam menu terbaru
18 | Sembunyikan tombol "clear all" dalam menu terbaru
19 | Sembunyikan \"Floating windows\" dalam menu terbaru
20 | Sembunyikan label widget
21 | Ukuran thumbnail pada saat menggunakan menu terbaru Horizontal
22 | Menggulir secara tak terbatas
23 | Efek download Air
24 | Fitur Modul
25 | Pengaturan module
26 | Tanpa Blur
27 | Fitur lainnya
28 | Menu terbaru Horizontal asli
29 | Restart Launcher
30 | Launcher akan restart pada 1 detik!
31 | Ukuran sudut bundar thumbnail
32 | Tampilkan nama aplikasi di dalam dock
33 | Animasi simpel
34 | Blur simpel
35 | Animasi lancar
36 | Ukuran text label pada thumbnail
37 | Blur menu terbaru
38 | Blur test
39 | Fitur experimental
40 | Telah dideteksi bahwa anda menggunakan modul ini pertama kalinya, Modul akan mengatur pengaturan kedefault, dan akan merestart launcher f.\nJika kamu perlu pengaturan lebih, Mohon tunggu untuk MIUI launcher agar selesai restart, dan bukalah pengaturan \"Home screen\" lagi
41 | Buka batasan dkuran grid
42 | Ukuran thumbnail untuk menu terbaru vertikal
43 | Matikan fitur menggelapkan wallpaper dalam menu terbaru
44 | Selamat datang!
45 | Fitur widget
46 | Bolehkan memindahkan widget ke \"App Vault\"
47 | Iya
48 | Munculkan bayangan dan refleksi
49 | Bolehkan semua aplikasi menggunakan floating window
50 | Aktifkan toko widget di HP low-end
51 | Matikan server rekomendasi
52 | Optimize launcher dengan mode "segalanya"
53 | Ini akan mereset pengaturan kedefault, dan merestar launcher.
54 | Hilangkan indikator halaman
55 | Sembunyikan \"All\" dalam kategori aplikasi
56 | Jumlah kolum folder
57 | Gunakan seluruh lebar folder
58 | Ukuran font label ikon
59 | Customizasi text saat tidak ada process dalam menu terbaru
60 |
61 |
--------------------------------------------------------------------------------
/app/src/main/res/values-night/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #333333
4 | #FFFFFF
5 | #000000
6 | #333333
7 | #353535
8 | #373737
9 | #0173DD
10 | #2688E3
11 | #2E2E2E
12 | #252525
13 | #333333
14 | #ccffffff
15 | #666666
16 | #666666
17 | #242424
18 | #454545
19 | #1F2F4C
20 | #404E67
21 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh-rCN/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 进阶设定
4 | 在安卓小部件中显示 MIUI 小部件
5 | 时钟常显
6 | 手势动画速度
7 | 后台应用图标与标题间距
8 | 文件夹展开背景模糊
9 | 取消
10 | 重置为默认设置
11 | 恢复备份成功,正在重启系统桌面
12 | 恢复备份失败
13 | 备份模块设置
14 | 恢复模块设置
15 | 这将清除所有模块设置并从文件中恢复模块设置,随后重启系统桌面
16 | 打开应用时关闭文件夹
17 | 完整模糊
18 | 默认值
19 | 推荐值
20 | 留空为恢复默认
21 | 留空为恢复默认,键入空格表示移除文本
22 | 当前
23 | 针对 MIUI 桌面的自定义扩展
24 | 文件夹相关
25 | 后台界面隐藏状态栏
26 | 隐藏后台应用图标
27 | 隐藏后台清理图标
28 | 移除后台\"小窗应用\"图标
29 | 隐藏桌面小部件标题
30 | 横向(平铺)后台卡片大小
31 | 桌面无限滚动
32 | 水波纹应用下载特效
33 | 模块相关
34 | 模块设置
35 | 无模糊
36 | 其他功能
37 | 真·横屏最近任务
38 | 重启桌面
39 | 确定要重启吗
40 | 桌面将在 1 秒后重启!
41 | 后台卡片圆角大小
42 | 显示底栏应用标题
43 | 简单动画
44 | 简单模糊
45 | 平滑动画
46 | 后台卡片文字大小
47 | 后台模糊级别
48 | 测试模糊
49 | 实验性功能
50 | 检测到你是第一次使用本模块,模块会进行默认值设定,并随后重启桌面。\n如需进一步设置,请待桌面重启后再次打开桌面设置。
51 | 解锁桌面布局限制
52 | 纵向(瀑布)后台卡片大小
53 | 取消后台壁纸压暗效果
54 | 欢迎
55 | 小部件相关
56 | 允许将安卓小部件移到负一屏
57 | 确定
58 | 显示应用阴影和倒影
59 | 允许所有应用使用小窗口
60 | 在低端机上启用 MIUI 小部件
61 | 禁用今日推荐
62 | 使用 Everything 模式编译桌面
63 | 这将还原模块默认值设定并重启桌面.
64 | 移除页面指示器
65 | 隐藏应用分组中的 \"全部\"
66 | 隐藏应用分页内的编辑按钮
67 | 文件夹排列数
68 | 利用整个文件夹的宽度
69 | 应用标题文字大小
70 | 后台无应用时显示的文本
71 | 双击锁屏
72 | 允许低端机使用动画图标
73 | 竖屏
74 | 横屏
75 | 重置横向(平铺)卡片大小配置参数
76 | 这将重置横向(平铺)卡片大小配置参数到默认值并重启桌面
77 | 解锁底栏图标数量限制
78 | 你启用了简单动画,这会禁用一些功能设置
79 | 废弃功能
80 | 模糊半径
81 | 基础模糊
82 | 应用标题颜色
83 | 支持十六进制颜色值,例如#FFFFFF为白,#000000为黑
84 | 关于模块
85 | 系统版本
86 | 桌面版本
87 | 模块版本
88 | 始终模糊桌面壁纸
89 | 开源仓库
90 | 点击打开 Github
91 | 图标与标题间距
92 | 解锁 Shortcut 数量限制
93 | 最大 Shortcut 数量
94 | 后台小窗应用卡片背景颜色
95 | 抽屉内水平图标个数
96 | 小米平板 Dock 模糊
97 | 底栏高度
98 | 底栏圆角
99 | 底栏距屏幕两侧
100 | 底栏距屏幕底部
101 | 图标距屏幕底部
102 | 底栏设置
103 | 启用底栏功能
104 | 启用底栏模糊
105 | 重置底栏配置参数
106 | 这将重置底栏配置参数到默认值并重启桌面.
107 | 页面指示器距图标
108 | 页面指示器距屏幕底部
109 | 应用返回桌面模糊过渡
110 | 应用返回桌面模糊过渡的速度
111 | 小文件夹模糊
112 | 启用该功能后,在编辑模式移动小文件夹图标将导致崩溃
113 | 小文件夹模糊圆角半径
114 | 小文件夹模糊大小
115 | 抽屉模糊
116 | 请将应用程序抽屉的背景透明度设置为100%以使用此功能。因为刷新机制的问题,模糊很容易变成纯黑屏
117 |
118 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh-rHK/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 進階設定
4 | 在安卓小部件中顯示 MIUI 小部件
5 | 時鐘常顯
6 | 手勢動畫速度
7 | 後台應用圖標與標題間距
8 | 文件夾打開背景模糊
9 | 取消
10 | 清除用戶配置
11 | 恢復備份成功,重啟系統桌面
12 | 恢复备份失败
13 | 備份模塊設置
14 | 恢復模塊設置
15 | 这将清除所有模块设置并从文件中恢复模块设置,随后重启系统桌面
16 | 打開應用時關閉文件夾
17 | 完整模糊
18 | 默認值
19 | 推薦值
20 | 留空為恢復默認
21 | 留空為恢復默認,鍵入空格表示移除文本
22 | 當前
23 | 針對 MIUI 桌面的自定義擴展
24 | 文件夾相關
25 | 後台界面隱藏狀態欄
26 | 隱藏後台應用圖標
27 | 隱藏後台清理圖標
28 | 移除後台\"小窗應用\"圖標
29 | 隱藏桌面小部件標題
30 | 橫向(瀑布)後台卡片大小
31 | 桌面無限滾動
32 | 水波紋應用下載特效
33 | 模塊相關
34 | 模塊設置
35 | 無模糊
36 | 其他功能
37 | 真·橫屏最近任務
38 | 重啟桌面
39 | 確定要重啟嗎
40 | 桌面將在 1 秒後重啟!
41 | 後台卡片圓角大小
42 | 顯示底欄應用標題
43 | 簡單動畫
44 | 簡單模糊
45 | 平滑動畫
46 | 後台卡片文字大小
47 | 後台模糊級別
48 | 測試模糊
49 | 實驗性功能
50 | 檢測到你是第一次使用本模塊,模塊會進行默認值設定,並隨後重啟桌面。如需進一步設置,請待桌面重啟後再次打開桌面設置。
51 | 解鎖桌面佈局限制
52 | 縱向(平鋪)後台卡片大小
53 | 取消後台壁紙壓暗效果
54 | 歡迎
55 | 小部件相關
56 | 允許將安卓小部件移到負一屏
57 | 確定
58 | 顯示應用陰影和倒影
59 | 允許所有應用使用小窗口
60 | 允許低端機添加 MIUI 小組件
61 | 禁用今日推薦
62 | 使用 Everything 模式編譯桌面
63 | 這將還原模塊默認值設定並重啟桌面。
64 | 移除頁面指示器
65 | 隱藏應用分組中的 \"全部\"
66 | 隱藏應用分頁內的編輯按鈕
67 | 文件夾排列數
68 | 利用整個文件夾的寬度
69 | 應用標題文字大小
70 | 後台無應用時的文本顯示
71 | 雙擊鎖屏
72 | 允許低端機使用動畫圖標
73 | 豎屏
74 | 橫屏
75 | 重置橫向卡片大小配置參數
76 | 這將重置橫向卡片大小配置參數到默認值並重啟桌面。
77 | 解鎖底欄圖標數量限制
78 | 你啟用了簡單動畫,這會禁用一些功能設置。
79 | 廢棄功能
80 | 模糊半徑
81 | 基礎模糊
82 | 應用標題顔色
83 | 支持十六進制顏色值,例如#FFFFFF為白,#000000為黑
84 | 關於模塊
85 | 系統版本
86 | 桌面版本
87 | 模塊版本
88 | 始終模糊桌面壁紙
89 | 開源倉庫
90 | 點擊打開 Github
91 | 圖標與標題間距
92 | 解鎖 Shortcut 數量限制
93 | 最大 Shortcut 數量
94 | Customize the thumbnail background color for small window apps
95 | Drawer mode icon count
96 | Pad Dock Blur
97 | 底欄高度
98 | 底欄圓角
99 | 底欄距離螢幕兩側
100 | 底欄距螢幕底部
101 | 圖標距螢幕底部
102 | 底欄設定
103 | 啟用底欄功能
104 | 啟用底欄模糊
105 | 重置底欄設定參數
106 | 這將重置底欄設定參數到預設值並重啟桌面。
107 | 頁面指示器距圖示
108 | 頁面寬度螢幕底部
109 | 應用程式返回模糊
110 | App Return Blur Speed
111 | Small folder blur
112 | Moving folders in edit mode will cause a crash when this feature is enabled
113 | Small folder blur corner
114 | Small folder blur side
115 | Enable All Apps Container View Blur
116 | Please set app drawer background transparency to 100% to use this feature.Also this is a very early test feature, because refresh issues blur very easily turned into a black screen
117 |
118 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh-rTW/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 進階設定
4 | 在 Android 小工具中顯示 MIUI 小工具
5 | 停用狀態列時鐘隱藏
6 | 手勢動畫速度
7 | 最近任務應用圖示與標題間距
8 | 啟用資料夾模糊
9 | 取消
10 | 重設為預設設定
11 | 還原備份成功,正在重啟系統桌面
12 | 還原備份失敗
13 | 備份模組設定
14 | 還原模組設定
15 | 這將清除所有模組設定並從檔案中恢復模組設定,隨後重啟系統桌面
16 | 開啟應用程式時關閉資料夾
17 | 完整模糊
18 | 預設值
19 | 建議值
20 | 留空以還原預設值
21 | 留空以還原預設值,輸入空白以移除文字
22 | 目前
23 | 針對 MIUI 桌面的自訂擴展
24 | 資料夾設定
25 | 最近任務畫面隱藏狀態列
26 | 最近任務畫面隱藏應用程式圖示
27 | 最近任務畫面隱藏「清除全部任務」按鈕
28 | 最近任務畫面隱藏「小窗應用程式」按鈕
29 | 隱藏小工具標籤
30 | 橫向最近任務畫面縮圖大小
31 | 啟用桌面無限捲動
32 | 啟用水波紋應用程式下載效果
33 | 模組功能
34 | 模組設定
35 | 無模糊
36 | 其他功能
37 | 真 • 橫向最近任務畫面
38 | 重啟桌面
39 | 確定要重啟系統桌面嗎?
40 | 桌面將在 1 秒內重啟!
41 | 最近任務畫面縮圖圓角大小
42 | 顯示 Dock 應用程式名稱
43 | 簡單動畫
44 | 簡單模糊
45 | 平滑動畫
46 | 縮圖標籤文字大小
47 | 最近任務畫面模糊層級
48 | 測試模糊
49 | 實驗性功能
50 | 偵測到你是第一次使用本模組,模組將設定為預設值,並隨後重啟桌面。\n如需進一步設定,請待桌面重啟後再次開啟「桌面設定」。
51 | 解鎖方格限制
52 | 直向最近任務畫面縮圖大小
53 | 關閉最近任務畫面桌布壓暗功能
54 | 歡迎使用
55 | 小工具功能
56 | 允許將 Android 小工具移至「負一屏」
57 | 確定
58 | 顯示圖示陰影和倒影
59 | 允許所有應用程式使用小視窗
60 | 為入門機啟用 MIUI 小工具
61 | 停用今日推薦
62 | 使用 Everything 模式最佳化桌面
63 | 這將還原模組預設設定並重啟桌面。
64 | 移除頁面指示器
65 | 隱藏應用程式分組中的「全部」
66 | 隱藏應用程式分類頁面內的「編輯」按鈕
67 | 資料夾欄數
68 | 利用整個資料夾的寬度
69 | 圖示標籤字型大小
70 | 自訂最近任務畫面無應用程式時的文字顯示
71 | 雙擊熄滅螢幕
72 | 為入門機啟用動畫圖示
73 | 直向螢幕
74 | 橫向螢幕
75 | 重設橫向最近任務卡片縮圖大小
76 | 這將重設橫向卡片大小設定參數為預設值並重啟桌面。
77 | 移除 Dock 圖示數量限制
78 | 你啟用了簡單動畫,這將隱藏一些設定。
79 | 棄用功能
80 | 模糊半徑
81 | 基本模糊
82 | 自訂應用程式標題色彩
83 | 支援十六進位色彩字串,例如 #FFFFFF 為白,#000000 為黑
84 | 關於模組
85 | MIUI 版本
86 | 桌面版本
87 | 模組版本
88 | 始終模糊桌面桌布
89 | GitHub
90 | 按一下以開啟 GitHub
91 | 圖示標題頂部邊界
92 | 解鎖捷徑數量限制
93 | 修改最大捷徑數量
94 | 自訂小窗應用程式的縮圖背景色彩
95 | 抽屜模式圖示數量
96 | 平板 Dock 模糊
97 | Dock 列高度
98 | Dock 列圓角
99 | Dock 列距螢幕兩側
100 | Dock 列距螢幕底部
101 | 圖示距螢幕底部
102 | Dock 設定
103 | 啟用 Dock 功能
104 | 啟用 Dock 模糊
105 | 重設 Dock 參數
106 | 這將重設 Dock 參數為預設值並重啟桌面。
107 | 頁面指示器與圖示間距
108 | 頁面指示器與距螢幕底部
109 | 應用程式返回模糊
110 | 應用程式返回模糊速度
111 | 小資料夾模糊
112 | 此功能啟用後,在編輯模式移動資料夾將會導致當機
113 | 小資料夾模糊圓角
114 | 小資料夾模糊側邊
115 | 啟用所有應用程式容器檢視模糊
116 | 請將應用程式導覽匣透明度設定為 100% 以使用此功能。這是一個測試版功能,因為重新整理問題的模糊很容易導致黑畫面。
117 |
118 |
--------------------------------------------------------------------------------
/app/src/main/res/values/array.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - com.miui.home
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #E6E6e6
4 | #000000
5 | #FFFFFF
6 | #1A000000
7 | #0C84FF
8 | #EFEFEF
9 | #DCDCDC
10 | #0C84FF
11 | #0D7AEC
12 | #EBEBEB
13 | #0374A7
14 | #FFFFFF
15 | #F0F0F0
16 | #FFFFFF
17 | #cc000000
18 | #999999
19 | #9399B3
20 | #FFFFFF
21 | #EBEBEB
22 | #E6F2FF
23 | #D4DFEB
24 | #1385FF
25 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
15 |
16 |
28 |
--------------------------------------------------------------------------------
/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.android.application") version "7.2.1" apply false
3 | id("com.android.library") version "7.2.1" apply false
4 | id("org.jetbrains.kotlin.android") version "1.8.0" apply false
5 | }
6 |
7 | tasks.register("clean").configure {
8 | delete(rootProject.buildDir)
9 | }
--------------------------------------------------------------------------------
/crowdin.yml:
--------------------------------------------------------------------------------
1 | files:
2 | - source: /app/src/main/res/values/strings.xml
3 | translation: /app/src/main/res/values-%two_letters_code%/strings.xml
4 | translate_content: 0
5 | translate_attributes: 0
6 | content_segmentation: 0
7 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | #android.enableJetifier=true
20 | android.enableR8.fullMode=true
21 | android.enableAppCompileTimeRClass=true
22 | android.nonTransitiveRClass=true
23 | org.gradle.caching=true
24 | org.gradle.parallel=true
25 | org.gradle.vfs.watch=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qqlittleice/MiuiHome/3da7a684ca28b3b0aea0cfd401d6eb8ea3ebf0f8/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Nov 27 00:00:00 CST 2021
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/hidden-api/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/hidden-api/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.android.library")
3 | id("kotlin-android")
4 | }
5 |
6 | android {
7 | compileSdk = 33
8 | namespace = "com.android.internal"
9 | defaultConfig {
10 | minSdk = 29
11 | targetSdk = 33
12 | }
13 | buildTypes {
14 | release {
15 | isMinifyEnabled = false
16 | setProguardFiles(listOf(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"))
17 | }
18 | }
19 | compileOptions {
20 | sourceCompatibility = JavaVersion.VERSION_11
21 | targetCompatibility = JavaVersion.VERSION_11
22 | }
23 | kotlinOptions {
24 | jvmTarget = JavaVersion.VERSION_11.majorVersion
25 | }
26 | }
27 |
28 | dependencies {
29 | }
--------------------------------------------------------------------------------
/hidden-api/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/hidden-api/src/main/java/android/view/ViewRootImpl.java:
--------------------------------------------------------------------------------
1 | package android.view;
2 |
3 | import com.android.internal.graphics.drawable.BackgroundBlurDrawable;
4 |
5 | public class ViewRootImpl {
6 |
7 | public BackgroundBlurDrawable createBackgroundBlurDrawable() {
8 | throw new RuntimeException("Stub!");
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/hidden-api/src/main/java/com/android/internal/graphics/drawable/BackgroundBlurDrawable.java:
--------------------------------------------------------------------------------
1 | package com.android.internal.graphics.drawable;
2 |
3 | import android.graphics.drawable.Drawable;
4 |
5 | public abstract class BackgroundBlurDrawable extends Drawable {
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | gradlePluginPortal()
6 | }
7 | }
8 |
9 | dependencyResolutionManagement {
10 | repositories {
11 | google()
12 | mavenCentral()
13 | maven("https://api.xposed.info")
14 | }
15 | }
16 |
17 | rootProject.name = "MiuiHome"
18 | include(":app", ":hidden-api")
--------------------------------------------------------------------------------