├── .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 | 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 | ![Launcher](https://github.com/qqlittleice/MiuiHome/blob/main/Pic/MiuiHome.png) 10 | 11 | 12 | [![Android CI](https://github.com/qqlittleice/MiuiHome/actions/workflows/android.yml/badge.svg)](https://github.com/qqlittleice/MiuiHome/actions/workflows/android.yml) 13 | [![Download](https://img.shields.io/github/downloads/Xposed-Modules-Repo/com.yuk.miuihome/total)](https://github.com/Xposed-Modules-Repo/com.yuk.miuihome/releases) 14 | [![Crowdin](https://badges.crowdin.net/miuihome_xposed/localized.svg)](https://crowdin.com/project/miuihome_xposed) 15 | [![Release](https://img.shields.io/github/v/release/Xposed-Modules-Repo/com.yuk.miuihome?label=release)](https://github.com/Xposed-Modules-Repo/com.yuk.miuihome/releases/latest) 16 | [![Chat](https://img.shields.io/badge/Telegram-Chat-blue.svg?logo=telegram)](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 | ![Screenshot](https://github.com/qqlittleice/MiuiHome/blob/main/Pic/Screenshot_ZH.png) 53 | 54 | ## 许可证 55 | 56 | [GNU General Public License v3.0](LICENSE) 57 | 58 | ## Star 数量统计 59 | 60 | [![Stargazers over time](https://starchart.cc/qqlittleice/MiuiHome.svg)](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 | ![Launcher](https://github.com/qqlittleice/MiuiHome/blob/main/Pic/MiuiHome.png) 10 | 11 | 12 | [![Android CI](https://github.com/qqlittleice/MiuiHome/actions/workflows/android.yml/badge.svg)](https://github.com/qqlittleice/MiuiHome/actions/workflows/android.yml) 13 | [![Download](https://img.shields.io/github/downloads/Xposed-Modules-Repo/com.yuk.miuihome/total)](https://github.com/Xposed-Modules-Repo/com.yuk.miuihome/releases) 14 | [![Crowdin](https://badges.crowdin.net/miuihome_xposed/localized.svg)](https://crowdin.com/project/miuihome_xposed) 15 | [![Release](https://img.shields.io/github/v/release/Xposed-Modules-Repo/com.yuk.miuihome?label=release)](https://github.com/Xposed-Modules-Repo/com.yuk.miuihome/releases/latest) 16 | [![Chat](https://img.shields.io/badge/Telegram-Chat-blue.svg?logo=telegram)](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 | ![Screenshot](https://github.com/qqlittleice/MiuiHome/blob/main/Pic/Screenshot_EN.png) 53 | 54 | ## License 55 | 56 | [GNU General Public License v3.0](LICENSE) 57 | 58 | ## Stargazers over time 59 | 60 | [![Stargazers over time](https://starchart.cc/qqlittleice/MiuiHome.svg)](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 |