├── .gitignore ├── LICENSE ├── README.md ├── build.gradle.kts ├── images ├── 1.jpg └── 2.jpg ├── proguard-rules.pro └── src └── main ├── AndroidManifest.xml ├── kotlin └── cn │ └── fkj233 │ └── ui │ ├── activity │ ├── MIUIActivity.kt │ ├── MIUIHookActivity.kt │ ├── Utils.kt │ ├── annotation │ │ ├── BMMainPage.kt │ │ ├── BMMenuPage.kt │ │ └── BMPage.kt │ ├── data │ │ ├── AsyncInit.kt │ │ ├── BasePage.kt │ │ ├── DataBinding.kt │ │ ├── InitView.kt │ │ ├── LayoutPair.kt │ │ ├── MIUIPopupData.kt │ │ ├── Padding.kt │ │ └── SafeSharedPreferences.kt │ ├── fragment │ │ └── MIUIFragment.kt │ └── view │ │ ├── BaseView.kt │ │ ├── CustomViewV.kt │ │ ├── ImageTextV.kt │ │ ├── LineV.kt │ │ ├── LinearContainerV.kt │ │ ├── MIUIEditText.kt │ │ ├── MIUIPopup.kt │ │ ├── PageV.kt │ │ ├── RadioViewV.kt │ │ ├── RoundCornerImageView.kt │ │ ├── SeekBarV.kt │ │ ├── SeekBarWithTextV.kt │ │ ├── SpinnerV.kt │ │ ├── SwitchV.kt │ │ ├── TextSummaryV.kt │ │ ├── TextSummaryWithArrowV.kt │ │ ├── TextSummaryWithSeekBarV.kt │ │ ├── TextSummaryWithSpinnerV.kt │ │ ├── TextSummaryWithSwitchV.kt │ │ ├── TextV.kt │ │ ├── TextWithArrowV.kt │ │ ├── TextWithSeekBarV.kt │ │ ├── TextWithSpinnerV.kt │ │ ├── TextWithSwitchV.kt │ │ └── TitleTextV.kt │ ├── dialog │ ├── MIUIDialog.kt │ └── NewDialog.kt │ └── switch │ └── MIUISwitch.kt └── res ├── animator ├── dialog_enter.xml ├── dialog_exit.xml ├── slide_left_in.xml ├── slide_left_out.xml ├── slide_right_in.xml └── slide_right_out.xml ├── drawable ├── abc_ic_ab_back_material.xml ├── abc_ic_menu_overflow_material.xml ├── editview_background.xml ├── ic_click_check.xml ├── ic_loading.webp ├── ic_main_bg.xml ├── ic_main_down_bg.xml ├── ic_popup_select.xml ├── ic_right_arrow.xml ├── ic_up_down.xml ├── l_button_background.xml ├── l_button_background_disable.xml ├── l_button_background_no_pressed.xml ├── l_button_background_pressed.xml ├── loading_background.xml ├── miui_rounded_corners_pop.xml ├── r_button_background.xml ├── r_button_background_disable.xml ├── r_button_background_no_pressed.xml ├── r_button_background_pressed.xml ├── seekbar_progress_drawable.xml ├── switch_thumb.xml └── switch_track.xml ├── values-night ├── colors.xml └── styles.xml └── values ├── colors.xml └── styles.xml /.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BlockMIUI 2 | 3 | [Demo](https://github.com/577fkj/BlockMIUIDemo) 4 | 5 | ![](images/1.jpg) 6 | 7 | ![](images/2.jpg) 8 | 9 | # LICENSE 10 | ### 许可证要求: 11 | 1. 您可以在您的项目使用此项目。 12 | 2. 但是有对本项目源码做出修改,您需要提供修改后的源代码! 13 | 3. 非开源项目需要在您的项目里注明使用了BlockMIUI。 14 | 15 | ### License requirements: 16 | 1. You can use this project in your project. 17 | 2. If the source code of this project modified. You need to provide the modified source code! 18 | 3. Non open source projects you need to indicate in the project that BlockMIUI is used. 19 | -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.android.library") 3 | id("kotlin-android") 4 | } 5 | 6 | android { 7 | compileSdk = 35 8 | namespace = "cn.fkj233.ui" 9 | defaultConfig.minSdk = 26 10 | 11 | buildTypes { 12 | release { 13 | isMinifyEnabled = false 14 | setProguardFiles(listOf(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")) 15 | } 16 | } 17 | kotlin.jvmToolchain(21) 18 | } 19 | 20 | dependencies { 21 | implementation("androidx.annotation:annotation:1.8.2") 22 | } 23 | -------------------------------------------------------------------------------- /images/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Block-Network/blockmiui/33a54b10d1a049d7e1237cb909b0f5d58fcd6b22/images/1.jpg -------------------------------------------------------------------------------- /images/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Block-Network/blockmiui/33a54b10d1a049d7e1237cb909b0f5d58fcd6b22/images/2.jpg -------------------------------------------------------------------------------- /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 | -keep class cn.fkj233.ui.activity.data.** { *; } -------------------------------------------------------------------------------- /src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/MIUIActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | @file:Suppress("DEPRECATION") 24 | 25 | package cn.fkj233.ui.activity 26 | 27 | import android.annotation.SuppressLint 28 | import android.app.Activity 29 | import android.app.FragmentManager 30 | import android.content.Context 31 | import android.content.SharedPreferences 32 | import android.graphics.Typeface 33 | import android.os.Bundle 34 | import android.util.TypedValue 35 | import android.view.Gravity 36 | import android.view.View 37 | import android.widget.FrameLayout 38 | import android.widget.ImageView 39 | import android.widget.LinearLayout 40 | import android.widget.TextView 41 | import androidx.annotation.Keep 42 | import cn.fkj233.ui.R 43 | import cn.fkj233.ui.activity.annotation.BMMainPage 44 | import cn.fkj233.ui.activity.annotation.BMMenuPage 45 | import cn.fkj233.ui.activity.annotation.BMPage 46 | import cn.fkj233.ui.activity.data.AsyncInit 47 | import cn.fkj233.ui.activity.data.BasePage 48 | import cn.fkj233.ui.activity.data.InitView 49 | import cn.fkj233.ui.activity.data.SafeSharedPreferences 50 | import cn.fkj233.ui.activity.fragment.MIUIFragment 51 | import cn.fkj233.ui.activity.view.BaseView 52 | 53 | /** 54 | * @version: V1.0 55 | * @author: 577fkj 56 | * @className: MIUIActivity 57 | * @packageName: MIUIActivity 58 | * @description: BaseActivity / 基本Activity 59 | * @data: 2022-02-05 18:30 60 | **/ 61 | @Keep 62 | open class MIUIActivity : Activity() { 63 | private var callbacks: (() -> Unit)? = null 64 | 65 | private var thisName: ArrayList = arrayListOf() 66 | 67 | private lateinit var viewData: InitView 68 | 69 | private val dataList: HashMap = hashMapOf() 70 | 71 | private lateinit var initViewData: InitView.() -> Unit 72 | 73 | companion object { 74 | var safeSP: SafeSharedPreferences = SafeSharedPreferences() 75 | 76 | @SuppressLint("StaticFieldLeak") 77 | lateinit var context: Context 78 | 79 | @SuppressLint("StaticFieldLeak") 80 | lateinit var activity: MIUIActivity 81 | } 82 | 83 | private val backButton by lazy { 84 | ImageView(activity).apply { 85 | layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { 86 | it.gravity = Gravity.CENTER_VERTICAL 87 | if (isRtl(context)) it.setMargins(dp2px(activity, 5f), 0, 0, 0) 88 | else it.setMargins(0, 0, dp2px(activity, 5f), 0) 89 | } 90 | background = getDrawable(R.drawable.abc_ic_ab_back_material) 91 | visibility = View.GONE 92 | setOnClickListener { 93 | this@MIUIActivity.onBackPressed() 94 | } 95 | } 96 | } 97 | 98 | private val menuButton by lazy { 99 | ImageView(activity).apply { 100 | layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT) 101 | .also { it.gravity = Gravity.CENTER_VERTICAL } 102 | background = getDrawable(R.drawable.abc_ic_menu_overflow_material) 103 | visibility = View.GONE 104 | if (isRtl(context)) setPadding(dp2px(activity, 25f), 0, 0, 0) 105 | else setPadding(0, 0, dp2px(activity, 25f), 0) 106 | setOnClickListener { 107 | showFragment(if (this@MIUIActivity::initViewData.isInitialized) "Menu" else "__menu__") 108 | } 109 | } 110 | } 111 | 112 | private val titleView by lazy { 113 | TextView(activity).apply { 114 | layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1f).also { 115 | it.gravity = Gravity.CENTER_VERTICAL 116 | } 117 | gravity = if (isRtl(context)) Gravity.RIGHT else Gravity.LEFT 118 | setTextColor(getColor(R.color.whiteText)) 119 | setTextSize(TypedValue.COMPLEX_UNIT_SP, 25f) 120 | paint.typeface = Typeface.defaultFromStyle(Typeface.BOLD) 121 | } 122 | } 123 | 124 | private var frameLayoutId: Int = -1 125 | private val frameLayout by lazy { 126 | val mFrameLayout = FrameLayout(activity).apply { 127 | layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT) 128 | } 129 | frameLayoutId = View.generateViewId() 130 | mFrameLayout.id = frameLayoutId 131 | mFrameLayout 132 | } 133 | 134 | /** 135 | * 是否继续加载 / Continue loading 136 | */ 137 | @Suppress("MemberVisibilityCanBePrivate") 138 | var isLoad = true 139 | 140 | /** 141 | * 退出时是否保留后台 / Retaining the background 142 | */ 143 | @Suppress("MemberVisibilityCanBePrivate") 144 | var isExit = false 145 | 146 | override fun onCreate(savedInstanceState: Bundle?) { 147 | super.onCreate(savedInstanceState) 148 | context = this 149 | activity = this 150 | register() 151 | actionBar?.hide() 152 | setContentView(LinearLayout(activity).apply { 153 | layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT) 154 | background = getDrawable(R.color.foreground) 155 | orientation = LinearLayout.VERTICAL 156 | addView(LinearLayout(activity).apply { 157 | layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT) 158 | setPadding(dp2px(activity, 25f), dp2px(activity, 20f), dp2px(activity, 25f), dp2px(activity, 15f)) 159 | orientation = LinearLayout.HORIZONTAL 160 | addView(backButton) 161 | addView(titleView) 162 | addView(menuButton) 163 | }) 164 | addView(frameLayout) 165 | }) 166 | if (savedInstanceState != null) { 167 | if (this::initViewData.isInitialized) { 168 | viewData = InitView(dataList).apply(initViewData) 169 | setMenuShow(viewData.isMenu) 170 | val list = savedInstanceState.getStringArrayList("this")!! 171 | fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE) 172 | for (name: String in list) { 173 | showFragment(name) 174 | } 175 | if (list.size == 1) { 176 | setBackupShow(viewData.mainShowBack) 177 | } 178 | return 179 | } 180 | val list = savedInstanceState.getStringArrayList("this")!! 181 | fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE) 182 | initAllPage() 183 | if (pageInfo.containsKey("__menu__")) setMenuShow(list.size == 1) 184 | for (name: String in list) { 185 | showFragment(name) 186 | } 187 | } else { 188 | if (isLoad) { 189 | if (this::initViewData.isInitialized) { 190 | viewData = InitView(dataList).apply(initViewData) 191 | setBackupShow(!viewData.mainShowBack) 192 | setMenuShow(viewData.isMenu) 193 | showFragment("Main") 194 | return 195 | } 196 | initAllPage() 197 | showFragment("__main__") 198 | } 199 | } 200 | val showFragmentName = intent.getStringExtra("showFragment").toString() 201 | if (showFragmentName != "null" && showFragmentName.isNotEmpty()) { 202 | if (pageInfo.containsKey(showFragmentName)) { 203 | showFragment(showFragmentName) 204 | return 205 | } 206 | } 207 | } 208 | 209 | private val pageInfo: HashMap = hashMapOf() 210 | private val pageList: HashMap, String> = HashMap() 211 | 212 | fun registerPage(basePage: Class, title: String? = null) { 213 | if (title == null) { 214 | pageList[basePage] = basePage.simpleName 215 | } else { 216 | pageList[basePage] = title 217 | } 218 | } 219 | 220 | open fun register() {} 221 | 222 | fun initAllPage() { 223 | pageList.forEach { (basePage, _) -> 224 | val mainPage = basePage.newInstance() 225 | mainPage.activity = this 226 | if (basePage.getAnnotation(BMMainPage::class.java) != null) { 227 | pageInfo["__main__"] = mainPage 228 | } else if (basePage.getAnnotation(BMMenuPage::class.java) != null) { 229 | menuButton.visibility = View.VISIBLE 230 | pageInfo["__menu__"] = mainPage 231 | } else if (basePage.getAnnotation(BMPage::class.java) != null) { 232 | pageInfo[basePage.simpleName] = mainPage 233 | } else { 234 | throw Exception("Page must be annotated with BMMainPage or BMMenuPage or BMPage") 235 | } 236 | } 237 | } 238 | 239 | fun initView(iView: InitView.() -> Unit) { 240 | initViewData = iView 241 | } 242 | 243 | override fun setTitle(title: CharSequence?) { 244 | titleView.text = title 245 | } 246 | 247 | /** 248 | * 设置 SharedPreferences / Set SharedPreferences 249 | * @param: SharedPreferences 250 | */ 251 | fun setSP(sharedPreferences: SharedPreferences) { 252 | safeSP.mSP = sharedPreferences 253 | } 254 | 255 | /** 256 | * 获取 SharedPreferences / Get SharedPreferences 257 | * @return: SharedPreferences 258 | */ 259 | fun getSP(): SharedPreferences? { 260 | return safeSP.mSP 261 | } 262 | 263 | /** 264 | * 显示 Fragment / Show fragment 265 | * @param: key 注册的key / Register key 266 | */ 267 | fun showFragment(key: String) { 268 | if (this::initViewData.isInitialized) { 269 | title = dataList[key]?.title 270 | thisName.add(key) 271 | val frame = MIUIFragment(key) 272 | if (key != "Main" && fragmentManager.backStackEntryCount != 0) { 273 | fragmentManager.beginTransaction().let { 274 | if (key != "Menu") { 275 | if (isRtl(activity)) it.setCustomAnimations( 276 | R.animator.slide_left_in, 277 | R.animator.slide_right_out, 278 | R.animator.slide_right_in, 279 | R.animator.slide_left_out 280 | ) 281 | else it.setCustomAnimations(R.animator.slide_right_in, R.animator.slide_left_out, R.animator.slide_left_in, R.animator.slide_right_out) 282 | } else { 283 | if (isRtl(activity)) it.setCustomAnimations( 284 | R.animator.slide_right_in, 285 | R.animator.slide_left_out, 286 | R.animator.slide_left_in, 287 | R.animator.slide_right_out 288 | ) 289 | else it.setCustomAnimations(R.animator.slide_left_in, R.animator.slide_right_out, R.animator.slide_right_in, R.animator.slide_left_out) 290 | } 291 | }.replace(frameLayoutId, frame).addToBackStack(key).commit() 292 | backButton.visibility = View.VISIBLE 293 | setMenuShow(dataList[key]?.hideMenu == false) 294 | } else { 295 | setBackupShow(viewData.mainShowBack) 296 | fragmentManager.beginTransaction().replace(frameLayoutId, frame).addToBackStack(key).commit() 297 | } 298 | return 299 | } 300 | if (!pageInfo.containsKey(key)) { 301 | throw Exception("No page found") 302 | } 303 | val thisPage = pageInfo[key]!! 304 | title = getPageTitle(thisPage::class.java) 305 | thisName.add(key) 306 | val frame = MIUIFragment(key) 307 | if (key != "__main__" && fragmentManager.backStackEntryCount != 0) { 308 | fragmentManager.beginTransaction().let { 309 | if (key != "__menu__") { 310 | if (isRtl(activity)) it.setCustomAnimations( 311 | R.animator.slide_left_in, 312 | R.animator.slide_right_out, 313 | R.animator.slide_right_in, 314 | R.animator.slide_left_out 315 | ) 316 | else it.setCustomAnimations(R.animator.slide_right_in, R.animator.slide_left_out, R.animator.slide_left_in, R.animator.slide_right_out) 317 | } else { 318 | if (isRtl(activity)) it.setCustomAnimations( 319 | R.animator.slide_right_in, 320 | R.animator.slide_left_out, 321 | R.animator.slide_left_in, 322 | R.animator.slide_right_out 323 | ) 324 | else it.setCustomAnimations(R.animator.slide_left_in, R.animator.slide_right_out, R.animator.slide_right_in, R.animator.slide_left_out) 325 | } 326 | }.replace(frameLayoutId, frame).addToBackStack(key).commit() 327 | setBackupShow(true) 328 | if (key !in arrayOf("__main__", "__menu__")) setMenuShow(!getPageHideMenu(thisPage)) 329 | if (key == "__menu__") setMenuShow(false) 330 | } else { 331 | setMenuShow(pageInfo.containsKey("__menu__")) 332 | setBackupShow(pageInfo["__main__"]!!.javaClass.getAnnotation(BMMainPage::class.java)!!.showBack) 333 | fragmentManager.beginTransaction().replace(frameLayoutId, frame).addToBackStack(key).commit() 334 | } 335 | } 336 | 337 | fun setMenuShow(show: Boolean) { 338 | if (this::initViewData.isInitialized) { 339 | if (!dataList.containsKey("Menu")) return 340 | if (show) menuButton.visibility = View.VISIBLE 341 | else menuButton.visibility = View.GONE 342 | return 343 | } 344 | if (pageInfo.containsKey("__menu__")) { 345 | if (show) { 346 | menuButton.visibility = View.VISIBLE 347 | } else { 348 | menuButton.visibility = View.GONE 349 | } 350 | } 351 | } 352 | 353 | fun setBackupShow(show: Boolean) { 354 | if (show) backButton.visibility = View.VISIBLE else backButton.visibility = View.GONE 355 | } 356 | 357 | private fun getPageHideMenu(basePage: BasePage): Boolean { 358 | return basePage.javaClass.getAnnotation(BMPage::class.java)?.hideMenu == true 359 | } 360 | 361 | private fun getPageTitle(basePage: Class): String { 362 | return pageList[basePage].toString() 363 | } 364 | 365 | fun getTopPage(): String { 366 | return thisName[thisName.lastSize()] 367 | } 368 | 369 | fun getThisItems(key: String): List { 370 | if (this::initViewData.isInitialized) { 371 | return dataList[key]?.itemList ?: arrayListOf() 372 | } 373 | val currentPage = pageInfo[key]!! 374 | if (currentPage.itemList.size == 0) { 375 | currentPage.onCreate() 376 | } 377 | return currentPage.itemList 378 | } 379 | 380 | fun getThisAsync(key: String): AsyncInit? { 381 | if (this::initViewData.isInitialized) { 382 | return dataList[key]?.async 383 | } 384 | val currentPage = pageInfo[key]!! 385 | if (currentPage.itemList.size == 0) { 386 | currentPage.onCreate() 387 | } 388 | return object : AsyncInit { 389 | override val skipLoadItem: Boolean 390 | get() = currentPage.skipLoadItem 391 | 392 | override fun onInit(fragment: MIUIFragment) { 393 | currentPage.asyncInit(fragment) 394 | } 395 | } 396 | } 397 | 398 | fun getAllCallBacks(): (() -> Unit)? { 399 | return callbacks 400 | } 401 | 402 | /** 403 | * 设置全局返回调用 / Set global return call methods 404 | * @param: Unit 405 | */ 406 | fun setAllCallBacks(callbacks: () -> Unit) { 407 | this.callbacks = callbacks 408 | } 409 | 410 | @Deprecated("Deprecated in Java") 411 | override fun onBackPressed() { 412 | if (fragmentManager.backStackEntryCount <= 1) { 413 | if (isExit) { 414 | finishAndRemoveTask() 415 | } else { 416 | finish() 417 | } 418 | } else { 419 | thisName.removeAt(thisName.lastSize()) 420 | val name = fragmentManager.getBackStackEntryAt(fragmentManager.backStackEntryCount - 2).name 421 | when (name) { 422 | "Main" -> { 423 | if (!viewData.mainShowBack) backButton.visibility = View.GONE 424 | if (viewData.isMenu) menuButton.visibility = View.VISIBLE 425 | } 426 | 427 | "__main__" -> { 428 | if (!pageInfo[name]!!.javaClass.getAnnotation(BMMainPage::class.java)!!.showBack) backButton.visibility = View.GONE 429 | setMenuShow(pageInfo.containsKey("__menu__")) 430 | } 431 | 432 | else -> { 433 | if (this::initViewData.isInitialized) { 434 | setMenuShow(dataList[name]?.hideMenu == false) 435 | } else { 436 | setMenuShow(!getPageHideMenu(pageInfo[name]!!)) 437 | } 438 | } 439 | } 440 | title = if (this::initViewData.isInitialized) { 441 | dataList[name]?.title 442 | } else { 443 | getPageTitle(pageInfo[name]!!::class.java) 444 | } 445 | fragmentManager.popBackStack() 446 | } 447 | } 448 | 449 | private fun ArrayList<*>.lastSize(): Int = this.size - 1 450 | 451 | override fun onSaveInstanceState(outState: Bundle) { 452 | super.onSaveInstanceState(outState) 453 | outState.putStringArrayList("this", thisName) 454 | } 455 | 456 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/MIUIHookActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity 24 | 25 | import android.content.Context 26 | import android.os.Bundle 27 | 28 | class MIUIHookActivity(private val moduleClassLoader: ClassLoader, private val hookAppClassLoader: ClassLoader) : MIUIActivity() { 29 | class FixedClassLoader(private val mModuleClassLoader: ClassLoader, private val mHostClassLoader: ClassLoader) : ClassLoader( 30 | mBootstrap 31 | ) { 32 | 33 | companion object { 34 | private val mBootstrap: ClassLoader = Context::class.java.classLoader!! 35 | } 36 | 37 | override fun loadClass(name: String, resolve: Boolean): Class<*> { 38 | runCatching { 39 | return mBootstrap.loadClass(name) 40 | } 41 | 42 | return try { 43 | mModuleClassLoader.loadClass(name) 44 | } catch (e: Exception) { 45 | mHostClassLoader.loadClass(name) 46 | } 47 | } 48 | 49 | } 50 | 51 | override fun getClassLoader(): ClassLoader { 52 | return FixedClassLoader(moduleClassLoader, hookAppClassLoader) 53 | } 54 | 55 | override fun onRestoreInstanceState(savedInstanceState: Bundle) { 56 | val windowState = savedInstanceState.getBundle("android:viewHierarchyState") 57 | windowState?.let { 58 | it.classLoader = MIUIHookActivity::class.java.classLoader 59 | } 60 | super.onRestoreInstanceState(savedInstanceState) 61 | } 62 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/Utils.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | @file:Suppress("DEPRECATION") 24 | 25 | package cn.fkj233.ui.activity 26 | 27 | import android.content.Context 28 | import android.text.TextUtils 29 | import android.util.TypedValue 30 | import android.view.Display 31 | import android.view.View 32 | import android.view.WindowManager 33 | 34 | fun dp2px(context: Context, dpValue: Float): Int = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, context.resources.displayMetrics).toInt() 35 | 36 | fun getDisplay(context: Context): Display { 37 | return (context.applicationContext.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay 38 | } 39 | 40 | fun isRtl(context: Context): Boolean { 41 | return TextUtils.getLayoutDirectionFromLocale(context.resources.configuration.locale) == View.LAYOUT_DIRECTION_RTL 42 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/annotation/BMMainPage.kt: -------------------------------------------------------------------------------- 1 | package cn.fkj233.ui.activity.annotation 2 | 3 | import androidx.annotation.Keep 4 | 5 | @Keep 6 | annotation class BMMainPage( 7 | val title: String = "", 8 | val titleId: Int = 0, 9 | val showBack: Boolean = false 10 | ) 11 | -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/annotation/BMMenuPage.kt: -------------------------------------------------------------------------------- 1 | package cn.fkj233.ui.activity.annotation 2 | 3 | import androidx.annotation.Keep 4 | 5 | @Keep 6 | annotation class BMMenuPage( 7 | val title: String = "", 8 | val titleId: Int = 0, 9 | ) 10 | -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/annotation/BMPage.kt: -------------------------------------------------------------------------------- 1 | package cn.fkj233.ui.activity.annotation 2 | 3 | import androidx.annotation.Keep 4 | 5 | @Keep 6 | annotation class BMPage( 7 | val hideMenu: Boolean = true 8 | ) 9 | -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/data/AsyncInit.kt: -------------------------------------------------------------------------------- 1 | package cn.fkj233.ui.activity.data 2 | 3 | import cn.fkj233.ui.activity.fragment.MIUIFragment 4 | 5 | interface AsyncInit { 6 | /** 7 | * Skip auto load view / 跳过自动加载控件 8 | */ 9 | val skipLoadItem: Boolean 10 | 11 | /** 12 | * Asynchronous operation start / 异步操作开始 13 | * Operation UI, please use { fragment.handler.post } 14 | */ 15 | fun onInit(fragment: MIUIFragment) 16 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/data/BasePage.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("FunctionName") 2 | 3 | package cn.fkj233.ui.activity.data 4 | 5 | import android.graphics.Typeface 6 | import android.graphics.drawable.Drawable 7 | import android.view.View 8 | import android.widget.TextView 9 | import cn.fkj233.ui.activity.MIUIActivity 10 | import cn.fkj233.ui.activity.fragment.MIUIFragment 11 | import cn.fkj233.ui.activity.view.* 12 | 13 | abstract class BasePage { 14 | val itemList: ArrayList = arrayListOf() 15 | var bindingData = arrayListOf() 16 | var skipLoadItem: Boolean = false 17 | lateinit var activity: MIUIActivity 18 | 19 | abstract fun onCreate() 20 | 21 | open fun asyncInit(fragment: MIUIFragment) {} 22 | 23 | fun showPage(page: Class) { 24 | activity.showFragment(page.simpleName) 25 | } 26 | 27 | fun setTitle(title: String) { 28 | activity.title = title 29 | } 30 | 31 | open fun getTitle(): String = "" 32 | 33 | fun getString(id: Int): String = activity.getString(id) 34 | fun getDrawable(id: Int): Drawable = activity.getDrawable(id)!! 35 | fun getColor(id: Int): Int = activity.getColor(id) 36 | 37 | 38 | fun GetDataBinding(defValue: () -> Any, recvCallbacks: (View, Int, Any) -> Unit): DataBinding.BindingData { 39 | return DataBinding.get(bindingData, defValue, recvCallbacks) 40 | } 41 | 42 | fun ImageWithText(head: Drawable, name: String, tips: String? = null, round: Float = 30f, onClickListener: (() -> Unit)? = null, dataBindingRecv: DataBinding.Binding.Recv? = null) { 43 | itemList.add(ImageTextV(head, name, tips, round, onClickListener, dataBindingRecv)) 44 | } 45 | 46 | fun Page(pageHead: Drawable, pageName: String? = null, pageNameId: Int? = null, round: Float = 0f, onClickListener: (() -> Unit)? = null, dataBindingRecv: DataBinding.Binding.Recv? = null) { 47 | itemList.add(PageV(pageHead, pageName, pageNameId, round, onClickListener, dataBindingRecv)) 48 | } 49 | 50 | fun Line(dataBindingRecv: DataBinding.Binding.Recv? = null,) { 51 | itemList.add(LineV(dataBindingRecv)) 52 | } 53 | 54 | fun SeekBar(key: String, min: Int, max: Int, defaultProgress: Int, dataSend: DataBinding.Binding.Send? = null, dataBindingRecv: DataBinding.Binding.Recv? = null, callBacks: ((Int, TextView) -> Unit)? = null) { 55 | itemList.add(SeekBarV(key, min, max, defaultProgress, dataSend, dataBindingRecv, callBacks)) 56 | } 57 | 58 | fun SeekBarWithText(key: String = "", min: Int, max: Int, defaultProgress: Int = 0, dataBindingRecv: DataBinding.Binding.Recv? = null, dataBindingSend: DataBinding.Binding.Send? = null, callBacks: ((Int, TextView) -> Unit)? = null) { 59 | itemList.add(SeekBarWithTextV(key, min, max, defaultProgress, dataBindingRecv, dataBindingSend, callBacks)) 60 | } 61 | 62 | fun Text(text: String? = null, textId: Int? = null, textSize: Float? = null, colorInt: Int? = null, colorId: Int? = null, padding: Padding? = null, dataBindingRecv: DataBinding.Binding.Recv? = null, typeface: Typeface? = null, onClickListener: (() -> Unit)? = null) { 63 | itemList.add(TextV(text, textId, textSize, colorInt, colorId, padding, dataBindingRecv, typeface, onClickListener)) 64 | } 65 | 66 | fun TextWithSwitch(textV: TextV, switchV: SwitchV, dataBindingRecv: DataBinding.Binding.Recv? = null) { 67 | itemList.add(TextWithSwitchV(textV, switchV, dataBindingRecv)) 68 | } 69 | 70 | fun TextSw(text: String? = null, textId: Int? = null, key: String, defValue: Boolean = false, onClickListener: ((Boolean) -> Unit)? = null, dataBindingRecv: DataBinding.Binding.Recv? = null) { 71 | itemList.add(TextWithSwitchV(TextV(text, textId), SwitchV(key, defValue, onClickListener = onClickListener), dataBindingRecv)) 72 | } 73 | 74 | fun TextWithSpinner(textV: TextV, spinnerV: SpinnerV, dataBindingRecv: DataBinding.Binding.Recv? = null) { 75 | itemList.add(TextWithSpinnerV(textV, spinnerV, dataBindingRecv)) 76 | } 77 | 78 | fun TextSp(text: String? = null, textId: Int? = null, currentValue: String, data: SpinnerV.SpinnerData.() -> Unit, dataBindingRecv: DataBinding.Binding.Recv? = null) { 79 | itemList.add(TextWithSpinnerV(TextV(text, textId), SpinnerV(currentValue, data = data), dataBindingRecv)) 80 | } 81 | 82 | fun TextWithArrow(textV: TextV, dataBindingRecv: DataBinding.Binding.Recv? = null) { 83 | itemList.add(TextWithArrowV(textV, dataBindingRecv)) 84 | } 85 | 86 | fun TextA(text: String? = null, textId: Int? = null, onClickListener: (() -> Unit)? = null, dataBindingRecv: DataBinding.Binding.Recv? = null) { 87 | itemList.add(TextWithArrowV(TextV(text, textId, onClickListener = onClickListener), dataBindingRecv)) 88 | } 89 | 90 | fun TextWithSeekBar(textV: TextV, seekBarWithTextV: SeekBarWithTextV, dataBindingRecv: DataBinding.Binding.Recv? = null) { 91 | itemList.add(TextWithSeekBarV(textV, seekBarWithTextV, dataBindingRecv)) 92 | } 93 | 94 | fun TextSummary(text: String? = null, textId: Int? = null, tips: String? = null, colorInt: Int? = null, colorId: Int? = null, tipsId: Int? = null, dataBindingRecv: DataBinding.Binding.Recv? = null, onClickListener: (() -> Unit)? = null) { 95 | itemList.add(TextSummaryV(text, textId, tips, colorInt, colorId, tipsId, dataBindingRecv, onClickListener)) 96 | } 97 | 98 | fun TextS(text: String? = null, textId: Int? = null, tips: String? = null, colorInt: Int? = null, colorId: Int? = null, tipsId: Int? = null, dataBindingRecv: DataBinding.Binding.Recv? = null, onClickListener: (() -> Unit)? = null) { 99 | itemList.add(TextSummaryV(text, textId, tips, colorInt, colorId, tipsId, dataBindingRecv, onClickListener)) 100 | } 101 | 102 | fun TextSummaryWithSwitch(textSummaryV: TextSummaryV, switchV: SwitchV, dataBindingRecv: DataBinding.Binding.Recv? = null) { 103 | itemList.add(TextSummaryWithSwitchV(textSummaryV, switchV, dataBindingRecv)) 104 | } 105 | 106 | fun TextSSw(text: String? = null, textId: Int? = null, tips: String? = null, tipsId: Int? = null, key: String, defValue: Boolean = false, onClickListener: ((Boolean) -> Unit)? = null, dataBindingRecv: DataBinding.Binding.Recv? = null) { 107 | itemList.add(TextSummaryWithSwitchV(TextSummaryV(text, textId, tips, tipsId = tipsId), SwitchV(key, defValue, onClickListener = onClickListener), dataBindingRecv)) 108 | } 109 | 110 | fun TextSummaryWithSpinner(textSummaryV: TextSummaryV, spinnerV: SpinnerV, dataBindingRecv: DataBinding.Binding.Recv? = null) { 111 | itemList.add(TextSummaryWithSpinnerV(textSummaryV, spinnerV, dataBindingRecv)) 112 | } 113 | 114 | fun TextSSp(text: String? = null, textId: Int? = null, tips: String? = null, tipsId: Int? = null, currentValue: String, data: SpinnerV.SpinnerData.() -> Unit, dataBindingRecv: DataBinding.Binding.Recv? = null) { 115 | itemList.add(TextSummaryWithSpinnerV(TextSummaryV(text, textId, tips, tipsId), SpinnerV(currentValue, data = data), dataBindingRecv)) 116 | } 117 | 118 | fun TextSummaryWithArrow(textSummaryV: TextSummaryV, dataBindingRecv: DataBinding.Binding.Recv? = null) { 119 | itemList.add(TextSummaryWithArrowV(textSummaryV, dataBindingRecv)) 120 | } 121 | 122 | fun TextSA(text: String? = null, textId: Int? = null, tips: String? = null, tipsId: Int? = null, onClickListener: (() -> Unit)? = null, dataBindingRecv: DataBinding.Binding.Recv? = null) { 123 | itemList.add(TextSummaryWithArrowV(TextSummaryV(text = text, textId = textId, tips = tips, tipsId = tipsId, onClickListener = onClickListener), dataBindingRecv)) 124 | } 125 | 126 | fun TextSummaryWithSeekBar(textSummaryV: TextSummaryV, seekBarWithTextV: SeekBarWithTextV, dataBindingRecv: DataBinding.Binding.Recv? = null) { 127 | itemList.add(TextSummaryWithSeekBarV(textSummaryV, seekBarWithTextV, dataBindingRecv)) 128 | } 129 | 130 | fun TitleText(text: String? = null, textId: Int? = null, colorInt: Int? = null, colorId: Int? = null, dataBindingRecv: DataBinding.Binding.Recv? = null, onClickListener: (() -> Unit)? = null) { 131 | itemList.add(TitleTextV(text, textId, colorInt, colorId, dataBindingRecv, onClickListener)) 132 | } 133 | 134 | fun CustomView(view: View, dataBindingRecv: DataBinding.Binding.Recv? = null) { 135 | itemList.add(CustomViewV(view, dataBindingRecv)) 136 | } 137 | 138 | fun RadioView(key: String, dataBindingRecv: DataBinding.Binding.Recv? = null, data: RadioViewV.RadioData.() -> Unit) { 139 | itemList.add(RadioViewV(key, dataBindingRecv, data)) 140 | } 141 | 142 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/data/DataBinding.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.data 24 | 25 | import android.view.View 26 | 27 | object DataBinding { 28 | fun get(bindingData: ArrayList, defValue: () -> Any, recvCallbacks: (View, Int, Any) -> Unit): BindingData { 29 | val binding = Binding(defValue, recvCallbacks) 30 | return BindingData(binding, binding.getSend(), recvCallbacks, { i -> 31 | binding.getRecv(i) 32 | }, { data -> 33 | binding.getSend().send(data) 34 | }).also { bindingData.add(it) } 35 | } 36 | 37 | data class BindingData( 38 | val binding: Binding, 39 | val bindingSend: Binding.Send, 40 | val recvCallbacks: (View, Int, Any) -> Unit, 41 | val getRecv: (Int) -> Binding.Recv, 42 | val send: (Any) -> Unit 43 | ) 44 | 45 | class Binding(private val defValue: () -> Any, val recvCallbacks: (View, Int, Any) -> Unit) { 46 | var data: ArrayList = arrayListOf() 47 | 48 | inner class Send { 49 | fun send(any: Any) { 50 | for (recv in data) { 51 | recv.recv(any) 52 | } 53 | } 54 | } 55 | 56 | fun add(recv: Recv) { 57 | data.add(recv) 58 | } 59 | 60 | fun getSend(): Send { 61 | return Send() 62 | } 63 | 64 | /** 65 | * Get data reception / 获取数据接收 66 | */ 67 | fun getRecv(flags: Int): Recv { 68 | return Recv(flags, defValue).also { add(it) } 69 | } 70 | 71 | /** 72 | * Please do not use it directly. / 请不要直接使用. 73 | *

74 | * Please use {@link cn.fkj233.ui.activity.data.DataBinding.Binding#getRecv(int)} 75 | */ 76 | inner class Recv(private val flags: Int, private val defValue: () -> Any) { 77 | private lateinit var mView: View 78 | 79 | fun setView(view: View) { 80 | mView = view 81 | recv(defValue()) 82 | } 83 | 84 | fun recv(any: Any) { 85 | recvCallbacks(mView, flags, any) 86 | } 87 | } 88 | } 89 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/data/InitView.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("FunctionName") 2 | 3 | package cn.fkj233.ui.activity.data 4 | 5 | import android.graphics.Typeface 6 | import android.graphics.drawable.Drawable 7 | import android.view.View 8 | import android.widget.TextView 9 | import cn.fkj233.ui.activity.view.* 10 | 11 | @Deprecated("Use BMMainPage/BMMenuPage/BMPage instead") 12 | class InitView(private val datalist: HashMap) { 13 | var isMenu = false 14 | var mainShowBack = false 15 | 16 | inner class ItemData(val title: String, val hideMenu: Boolean) { 17 | val itemList: ArrayList = arrayListOf() 18 | var bindingData = arrayListOf() 19 | var async: AsyncInit? = null 20 | 21 | fun GetDataBinding(defValue: () -> Any, recvCallbacks: (View, Int, Any) -> Unit): DataBinding.BindingData { 22 | return DataBinding.get(bindingData, defValue, recvCallbacks) 23 | } 24 | 25 | fun Author(authorHead: Drawable, authorName: String, authorTips: String? = null, round: Float = 30f, onClickListener: (() -> Unit)? = null, dataBindingRecv: DataBinding.Binding.Recv? = null) { 26 | itemList.add(ImageTextV(authorHead, authorName, authorTips, round, onClickListener, dataBindingRecv)) 27 | } 28 | 29 | fun Page(pageHead: Drawable, pageName: String?, pageNameId: Int?, round: Float = 0f, onClickListener: (() -> Unit)? = null, dataBindingRecv: DataBinding.Binding.Recv? = null) { 30 | itemList.add(PageV(pageHead, pageName, pageNameId, round, onClickListener, dataBindingRecv)) 31 | } 32 | 33 | fun Line() { 34 | itemList.add(LineV()) 35 | } 36 | 37 | fun SeekBar(key: String, min: Int, max: Int, defaultProgress: Int, dataSend: DataBinding.Binding.Send? = null, dataBindingRecv: DataBinding.Binding.Recv? = null, callBacks: ((Int, TextView) -> Unit)? = null) { 38 | itemList.add(SeekBarV(key, min, max, defaultProgress, dataSend, dataBindingRecv, callBacks)) 39 | } 40 | 41 | fun TextSummaryWithSpinner(textV: TextSummaryV, spinnerV: SpinnerV, dataBindingRecv: DataBinding.Binding.Recv? = null) { 42 | itemList.add(TextSummaryWithSpinnerV(textV, spinnerV, dataBindingRecv)) 43 | } 44 | 45 | fun Text(text: String? = null, textId: Int? = null, textSize: Float? = null, colorInt: Int? = null, colorId: Int? = null, padding: Padding? = null, dataBindingRecv: DataBinding.Binding.Recv? = null, typeface: Typeface? = null, onClickListener: (() -> Unit)? = null) { 46 | itemList.add(TextV(text, textId, textSize, colorInt, colorId, padding, dataBindingRecv, typeface, onClickListener)) 47 | } 48 | 49 | fun SeekBarWithText(key: String = "", min: Int, max: Int, defaultProgress: Int = 0, dataBindingRecv: DataBinding.Binding.Recv? = null, dataBindingSend: DataBinding.Binding.Send? = null, callBacks: ((Int, TextView) -> Unit)? = null) { 50 | itemList.add(SeekBarWithTextV(key, min, max, defaultProgress, dataBindingRecv, dataBindingSend, callBacks)) 51 | } 52 | 53 | fun TextSummaryArrow(textSummaryV: TextSummaryV, dataBindingRecv: DataBinding.Binding.Recv? = null) { 54 | itemList.add(TextSummaryWithArrowV(textSummaryV, dataBindingRecv)) 55 | } 56 | 57 | fun TextA(text: String? = null, textId: Int? = null, onClickListener: (() -> Unit)? = null, dataBindingRecv: DataBinding.Binding.Recv? = null) { 58 | itemList.add(TextSummaryWithArrowV(TextSummaryV(text, textId, onClickListener = onClickListener), dataBindingRecv)) 59 | } 60 | 61 | fun TextSummaryWithSwitch(textSummaryV: TextSummaryV, switchV: SwitchV, dataBindingRecv: DataBinding.Binding.Recv? = null) { 62 | itemList.add(TextSummaryWithSwitchV(textSummaryV, switchV, dataBindingRecv)) 63 | } 64 | 65 | fun TitleText(text: String? = null, textId: Int? = null,colorInt: Int? = null, colorId: Int? = null, dataBindingRecv: DataBinding.Binding.Recv? = null, onClickListener: (() -> Unit)? = null) { 66 | itemList.add(TitleTextV(text, textId,colorInt, colorId,dataBindingRecv, onClickListener)) 67 | } 68 | 69 | fun TextWithSwitch(textV: TextV, switchV: SwitchV, dataBindingRecv: DataBinding.Binding.Recv? = null) { 70 | itemList.add(TextWithSwitchV(textV, switchV, dataBindingRecv)) 71 | } 72 | 73 | fun TextS(text: String? = null, textId: Int? = null, key: String, defValue: Boolean=false, onClickListener: ((Boolean) -> Unit)? = null, dataBindingRecv: DataBinding.Binding.Recv? = null) { 74 | itemList.add(TextWithSwitchV(TextV(text, textId), SwitchV(key, defValue, onClickListener = onClickListener), dataBindingRecv)) 75 | } 76 | 77 | fun TextWithSpinner(textV: TextV, spinnerV: SpinnerV, dataBindingRecv: DataBinding.Binding.Recv? = null) { 78 | itemList.add(TextWithSpinnerV(textV, spinnerV, dataBindingRecv)) 79 | } 80 | 81 | fun CustomView(view: View, dataBindingRecv: DataBinding.Binding.Recv? = null) { 82 | itemList.add(CustomViewV(view, dataBindingRecv)) 83 | } 84 | 85 | fun RadioView(key: String, dataBindingRecv: DataBinding.Binding.Recv? = null, data: RadioViewV.RadioData.() -> Unit) { 86 | itemList.add(RadioViewV(key, dataBindingRecv, data)) 87 | } 88 | 89 | fun TextSummary(text: String? = null, textId: Int? = null, tips: String? = null, colorInt: Int? = null, colorId: Int? = null, tipsId: Int? = null, dataBindingRecv: DataBinding.Binding.Recv? = null, onClickListener: (() -> Unit)? = null) { 90 | itemList.add(TextSummaryV(text, textId, tips, colorInt, colorId, tipsId, dataBindingRecv, onClickListener)) 91 | } 92 | } 93 | 94 | fun registerMain(title: String, showBack: Boolean, itemData: ItemData.() -> Unit) { 95 | datalist["Main"] = ItemData(title, false).apply(itemData) 96 | mainShowBack = showBack 97 | } 98 | 99 | fun registerMenu(title: String, itemData: ItemData.() -> Unit) { 100 | datalist["Menu"] = ItemData(title, true).apply(itemData) 101 | isMenu = true 102 | } 103 | 104 | fun register(key: String, title: String, hideMenu: Boolean, itemData: ItemData.() -> Unit) { 105 | if (key in arrayOf("Main", "Menu")) throw Throwable("[$key] This is reserved and cannot be used!") 106 | datalist[key] = ItemData(title, hideMenu).apply(itemData) 107 | } 108 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/data/LayoutPair.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.data 24 | 25 | import android.view.View 26 | import android.view.ViewGroup 27 | 28 | data class LayoutPair(val view: View, val layoutParams: ViewGroup.LayoutParams) -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/data/MIUIPopupData.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.data 24 | 25 | open class MIUIPopupData(private val name: String, private val dataBindingSend: DataBinding.Binding.Send?, private val callBacks: () -> Unit) { 26 | fun getName(): String = name 27 | 28 | fun getCallBacks(): () -> Unit = callBacks 29 | 30 | fun getDataBindingSend(): DataBinding.Binding.Send? = dataBindingSend 31 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/data/Padding.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.data 24 | 25 | data class Padding( 26 | val left: Int, 27 | val top: Int, 28 | val right: Int, 29 | val bottom: Int 30 | ) -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/data/SafeSharedPreferences.kt: -------------------------------------------------------------------------------- 1 | package cn.fkj233.ui.activity.data 2 | 3 | import android.content.SharedPreferences 4 | 5 | class SafeSharedPreferences { 6 | var mSP: SharedPreferences? = null 7 | 8 | fun containsKey(key: String, defValue: Boolean = false): Boolean { 9 | return if (mSP == null) { 10 | defValue 11 | } else { 12 | mSP!!.all.containsKey(key) 13 | } 14 | } 15 | 16 | fun putAny(key: String, any: Any) { 17 | if (mSP == null) return 18 | mSP!!.edit().apply { 19 | when (any) { 20 | is Boolean -> putBoolean(key, any) 21 | is String -> putString(key, any) 22 | is Int -> putInt(key, any) 23 | is Float -> putFloat(key, any) 24 | is Long -> putLong(key, any) 25 | } 26 | apply() 27 | } 28 | } 29 | 30 | fun getBoolean(key: String, defValue: Boolean): Boolean { 31 | return if (mSP == null) { 32 | defValue 33 | } else { 34 | mSP!!.getBoolean(key, defValue) 35 | } 36 | } 37 | 38 | fun getInt(key: String, defValue: Int): Int { 39 | return if (mSP == null) { 40 | defValue 41 | } else { 42 | mSP!!.getInt(key, defValue) 43 | } 44 | } 45 | 46 | fun getFloat(key: String, defValue: Float): Float { 47 | return if (mSP == null) { 48 | defValue 49 | } else { 50 | mSP!!.getFloat(key, defValue) 51 | } 52 | } 53 | 54 | fun getLong(key: String, defValue: Long): Long { 55 | return if (mSP == null) { 56 | defValue 57 | } else { 58 | mSP!!.getLong(key, defValue) 59 | } 60 | } 61 | 62 | fun getString(key: String, defValue: String): String { 63 | return if (mSP == null) { 64 | defValue 65 | } else { 66 | mSP!!.getString(key, defValue) ?: defValue 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/fragment/MIUIFragment.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | @file:Suppress("DEPRECATION", "DuplicatedCode") 24 | 25 | package cn.fkj233.ui.activity.fragment 26 | 27 | import android.annotation.SuppressLint 28 | import android.app.Dialog 29 | import android.app.Fragment 30 | import android.os.Bundle 31 | import android.os.Handler 32 | import android.os.Looper 33 | import android.view.LayoutInflater 34 | import android.view.View 35 | import android.view.ViewGroup 36 | import android.view.animation.AnimationSet 37 | import android.view.animation.LinearInterpolator 38 | import android.view.animation.RotateAnimation 39 | import android.widget.ImageView 40 | import android.widget.LinearLayout 41 | import android.widget.RelativeLayout 42 | import android.widget.ScrollView 43 | import androidx.annotation.Keep 44 | import cn.fkj233.ui.R 45 | import cn.fkj233.ui.activity.MIUIActivity 46 | import cn.fkj233.ui.activity.data.AsyncInit 47 | import cn.fkj233.ui.activity.dp2px 48 | import cn.fkj233.ui.activity.view.BaseView 49 | 50 | @Suppress("MemberVisibilityCanBePrivate") 51 | @SuppressLint("ValidFragment") 52 | @Keep 53 | class MIUIFragment() : Fragment() { 54 | private var key = "" 55 | private lateinit var scrollView: ScrollView 56 | private lateinit var itemView: LinearLayout 57 | val callBacks: (() -> Unit)? by lazy { MIUIActivity.activity.getAllCallBacks() } 58 | private val async: AsyncInit? by lazy { MIUIActivity.activity.getThisAsync(key.ifEmpty { MIUIActivity.activity.getTopPage() }) } 59 | private var dialog: Dialog? = null 60 | val handler: Handler by lazy { Handler(Looper.getMainLooper()) } 61 | 62 | constructor(keys: String) : this() { 63 | key = keys 64 | } 65 | 66 | @Deprecated("Deprecated in Java") 67 | override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View { 68 | scrollView = ScrollView(context).apply { 69 | isVerticalScrollBarEnabled = false 70 | layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT) 71 | isFillViewport = true 72 | addView(LinearLayout(context).apply { // 总布局 73 | layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) 74 | orientation = LinearLayout.VERTICAL 75 | background = context.getDrawable(R.color.foreground) 76 | itemView = this 77 | if (async?.skipLoadItem != true) initData() 78 | }) 79 | } 80 | async?.let { Thread { it.onInit(this) }.start() } 81 | return scrollView 82 | } 83 | 84 | /** 85 | * 如果 skipLoadItem 为 true 则需要手动调用 / If skipLoadItem is true, it needs to be called manually 86 | */ 87 | @Suppress("MemberVisibilityCanBePrivate") 88 | fun initData() { 89 | for (item: BaseView in MIUIActivity.activity.getThisItems(key.ifEmpty { MIUIActivity.activity.getTopPage() })) { 90 | addItem(item) 91 | } 92 | } 93 | 94 | /** 95 | * Show loading dialog / 显示加载 Dialog 96 | */ 97 | fun showLoading() { 98 | handler.post { 99 | dialog = Dialog(MIUIActivity.context, R.style.Translucent_NoTitle).apply { 100 | setCancelable(false) 101 | setContentView(LinearLayout(context).apply { 102 | layoutParams = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT) 103 | addView(ImageView(context).apply { 104 | layoutParams = LinearLayout.LayoutParams(dp2px(context, 60f), dp2px(context, 60f)) 105 | .also { it.setMargins(dp2px(context, 20f), dp2px(context, 20f), dp2px(context, 20f), dp2px(context, 20f)) } 106 | background = context.getDrawable(R.drawable.ic_loading) 107 | startAnimation(AnimationSet(true).apply { 108 | interpolator = LinearInterpolator() 109 | addAnimation(RotateAnimation(0f, +359f, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f).apply { 110 | repeatCount = -1 111 | startOffset = 0 112 | duration = 1000 113 | }) 114 | }) 115 | }) 116 | }) 117 | } 118 | dialog?.show() 119 | } 120 | } 121 | 122 | /** 123 | * Close loading dialog / 关闭加载 Dialog 124 | */ 125 | fun closeLoading() { 126 | handler.post { dialog?.dismiss() } 127 | } 128 | 129 | /** 130 | * Add view / 添加控件 131 | */ 132 | @SuppressLint("ClickableViewAccessibility") 133 | fun addItem(item: BaseView) { 134 | handler.post { 135 | itemView.addView(LinearLayout(MIUIActivity.context).apply { // 控件布局 136 | layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) 137 | background = context.getDrawable(R.drawable.ic_click_check) 138 | setPadding(dp2px(context, 30f), 0, dp2px(context, 30f), 0) 139 | item.onDraw(this@MIUIFragment, this, item.create(context, callBacks)) 140 | }) 141 | } 142 | } 143 | 144 | /** 145 | * Clear all view / 清除所有控件 146 | */ 147 | fun clearAll() { 148 | handler.post { 149 | itemView.removeAllViews() 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/BaseView.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.view 24 | 25 | import android.content.Context 26 | import android.view.View 27 | import android.widget.LinearLayout 28 | import cn.fkj233.ui.activity.fragment.MIUIFragment 29 | 30 | interface BaseView { 31 | 32 | fun getType(): BaseView 33 | 34 | fun create(context: Context, callBacks: (() -> Unit)?): View 35 | 36 | fun onDraw(thiz: MIUIFragment, group: LinearLayout, view: View) { 37 | group.addView(view) 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/CustomViewV.kt: -------------------------------------------------------------------------------- 1 | package cn.fkj233.ui.activity.view 2 | 3 | import android.content.Context 4 | import android.view.View 5 | import android.view.ViewGroup 6 | import cn.fkj233.ui.activity.data.DataBinding 7 | 8 | class CustomViewV(val view: View, private val dataBindingRecv: DataBinding.Binding.Recv? = null): BaseView { 9 | 10 | override fun getType(): BaseView = this 11 | 12 | override fun create(context: Context, callBacks: (() -> Unit)?): View { 13 | dataBindingRecv?.setView(view) 14 | view.parent?.let { (it as ViewGroup).removeView(view) } 15 | return view 16 | } 17 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/ImageTextV.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.view 24 | 25 | import android.content.Context 26 | import android.graphics.Typeface 27 | import android.graphics.drawable.Drawable 28 | import android.os.Build 29 | import android.util.TypedValue 30 | import android.view.Gravity 31 | import android.view.View 32 | import android.widget.ImageView 33 | import android.widget.LinearLayout 34 | import android.widget.TextView 35 | import cn.fkj233.ui.R 36 | import cn.fkj233.ui.activity.data.DataBinding 37 | import cn.fkj233.ui.activity.data.LayoutPair 38 | import cn.fkj233.ui.activity.dp2px 39 | import cn.fkj233.ui.activity.fragment.MIUIFragment 40 | import cn.fkj233.ui.activity.isRtl 41 | 42 | class ImageTextV(private val authorHead: Drawable, private val authorName: String, private val authorTips: String? = null, private val round: Float = 30f, private val onClick: (() -> Unit)? = null, private val dataBindingRecv: DataBinding.Binding.Recv? = null): BaseView { 43 | 44 | override fun getType(): BaseView { 45 | return this 46 | } 47 | 48 | override fun create(context: Context, callBacks: (() -> Unit)?): View { 49 | return LinearContainerV(LinearContainerV.HORIZONTAL, arrayOf( 50 | LayoutPair( 51 | RoundCornerImageView(context, dp2px(context, round), dp2px(context, round)).also { 52 | it.setPadding(0, dp2px(context, 10f), 0, dp2px(context, 10f)) 53 | it.background = authorHead 54 | }, 55 | LinearLayout.LayoutParams( 56 | dp2px(context, 60f), 57 | dp2px(context, 60f) 58 | ) 59 | ), 60 | LayoutPair( 61 | LinearContainerV( 62 | LinearContainerV.VERTICAL, arrayOf( 63 | LayoutPair( 64 | TextView(context).also { 65 | if (isRtl(context)) 66 | it.setPadding(0, dp2px(context, if (authorTips == null) 17f else 5f), dp2px(context, 15f), 0) 67 | else 68 | it.setPadding(dp2px(context, 15f), dp2px(context, if (authorTips == null) 17f else 5f), 0, 0) 69 | it.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f) 70 | it.setTextColor(context.getColor(R.color.whiteText)) 71 | it.text = authorName 72 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 73 | it.paint.typeface = Typeface.create(null, 500,false) 74 | } else { 75 | it.paint.typeface = Typeface.defaultFromStyle(Typeface.BOLD) 76 | } 77 | }, 78 | LinearLayout.LayoutParams( 79 | LinearLayout.LayoutParams.MATCH_PARENT, 80 | LinearLayout.LayoutParams.MATCH_PARENT 81 | ) 82 | ), 83 | LayoutPair( 84 | TextView(context).also { 85 | if (isRtl(context)) 86 | it.setPadding(0, 0, dp2px(context, 16f), 0) 87 | else 88 | it.setPadding(dp2px(context, 16f), 0, 0, 0) 89 | it.setTextSize(TypedValue.COMPLEX_UNIT_SP, 13f) 90 | it.setTextColor(context.getColor(R.color.author_tips)) 91 | if (authorTips == null) { 92 | it.visibility = View.GONE 93 | } else { 94 | it.text = authorTips 95 | } 96 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 97 | it.paint.typeface = Typeface.create(null, 400,false) 98 | } else { 99 | it.paint.typeface = Typeface.defaultFromStyle(Typeface.BOLD) 100 | } 101 | }, 102 | LinearLayout.LayoutParams( 103 | LinearLayout.LayoutParams.MATCH_PARENT, 104 | LinearLayout.LayoutParams.MATCH_PARENT 105 | ) 106 | ) 107 | )).create(context, callBacks), 108 | LinearLayout.LayoutParams( 109 | 0, 110 | LinearLayout.LayoutParams.WRAP_CONTENT, 111 | 1f 112 | ) 113 | ), 114 | LayoutPair( 115 | ImageView(context).also { 116 | it.background = context.getDrawable(R.drawable.ic_right_arrow) 117 | }, 118 | LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { 119 | it.gravity = Gravity.CENTER_VERTICAL 120 | if (isRtl(context)) it.setMargins(0, 0, dp2px(context, 5f), 0) 121 | } 122 | ) 123 | ), layoutParams = LinearLayout.LayoutParams( 124 | LinearLayout.LayoutParams.MATCH_PARENT, 125 | LinearLayout.LayoutParams.WRAP_CONTENT 126 | ).also { 127 | it.setMargins(0, dp2px(context, 10f), 0, dp2px(context, 10f)) 128 | }).create(context, callBacks).also { 129 | dataBindingRecv?.setView(it) 130 | } 131 | } 132 | 133 | override fun onDraw(thiz: MIUIFragment, group: LinearLayout, view: View) { 134 | thiz.apply { 135 | group.apply { 136 | addView(view) 137 | onClick?.let { unit -> 138 | setOnClickListener { 139 | unit() 140 | callBacks?.let { it1 -> it1() } 141 | } 142 | } 143 | } 144 | } 145 | } 146 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/LineV.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.view 24 | 25 | import android.content.Context 26 | import android.view.View 27 | import android.widget.LinearLayout 28 | import cn.fkj233.ui.R 29 | import cn.fkj233.ui.activity.data.DataBinding 30 | import cn.fkj233.ui.activity.dp2px 31 | 32 | class LineV(private val dataBindingRecv: DataBinding.Binding.Recv? = null): BaseView { 33 | 34 | override fun getType(): BaseView { 35 | return this 36 | } 37 | 38 | override fun create(context: Context, callBacks: (() -> Unit)?): View { 39 | return View(context).also { 40 | val layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, dp2px(context, 0.9f)) 41 | layoutParams.setMargins(0, dp2px(context, 23.5f), 0, dp2px(context, 23.5f)) 42 | it.layoutParams = layoutParams 43 | it.setBackgroundColor(context.resources.getColor(R.color.line, null)) 44 | dataBindingRecv?.setView(it) 45 | } 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/LinearContainerV.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.view 24 | 25 | import android.content.Context 26 | import android.view.View 27 | import android.view.ViewGroup 28 | import android.widget.LinearLayout 29 | import cn.fkj233.ui.activity.data.DataBinding 30 | import cn.fkj233.ui.activity.data.LayoutPair 31 | 32 | class LinearContainerV(private val orientation: Int, private val pairs: Array, val descendantFocusability: Int? = null, private val dataBindingRecv: DataBinding.Binding.Recv? = null, private val click: ((View) -> Unit)? = null, val layoutParams: ViewGroup.LayoutParams? = null): BaseView { 33 | companion object { 34 | const val VERTICAL = LinearLayout.VERTICAL 35 | const val HORIZONTAL = LinearLayout.HORIZONTAL 36 | const val FOCUS_BLOCK_DESCENDANTS = ViewGroup.FOCUS_BLOCK_DESCENDANTS 37 | } 38 | 39 | override fun getType(): BaseView { 40 | return this 41 | } 42 | 43 | override fun create(context: Context, callBacks: (() -> Unit)?): View { 44 | return LinearLayout(context).also { 45 | it.orientation = orientation 46 | layoutParams?.let { it1 -> it.layoutParams = it1 } 47 | descendantFocusability?.let { it1 -> it.descendantFocusability = it1 } 48 | click?.let { it1 -> it.setOnClickListener { it2 -> it1(it2) } } 49 | for (pair in pairs) { 50 | it.addView(pair.view, pair.layoutParams) 51 | } 52 | dataBindingRecv?.setView(it) 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/MIUIEditText.kt: -------------------------------------------------------------------------------- 1 | package cn.fkj233.ui.activity.view 2 | 3 | import android.content.Context 4 | import android.util.TypedValue 5 | import android.view.Gravity 6 | import android.view.View 7 | import android.widget.EditText 8 | import android.widget.LinearLayout 9 | import cn.fkj233.ui.R 10 | import cn.fkj233.ui.activity.dp2px 11 | 12 | class MIUIEditText(context: Context) : EditText(context) { 13 | init { 14 | this.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { 15 | it.setMargins(dp2px(context, 25f), dp2px(context, 10f), dp2px(context, 25f), 0) 16 | } 17 | this.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20f) 18 | this.setTextColor(context.getColor(R.color.whiteText)) 19 | this.gravity = Gravity.CENTER_VERTICAL 20 | this.setPadding(dp2px(context, 20f), dp2px(context, 15f), dp2px(context, 20f), dp2px(context, 15f)) 21 | this.background = context.getDrawable(R.drawable.editview_background) 22 | this.isSingleLine = true 23 | this.setHintTextColor(context.getColor(R.color.hintText)) 24 | this.visibility = View.GONE 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/MIUIPopup.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.view 24 | 25 | import android.content.Context 26 | import android.graphics.Typeface 27 | import android.graphics.drawable.GradientDrawable 28 | import android.graphics.drawable.StateListDrawable 29 | import android.text.TextUtils 30 | import android.util.TypedValue 31 | import android.view.Gravity 32 | import android.view.View 33 | import android.view.ViewGroup 34 | import android.widget.* 35 | import cn.fkj233.ui.R 36 | import cn.fkj233.ui.activity.data.MIUIPopupData 37 | import cn.fkj233.ui.activity.dp2px 38 | import cn.fkj233.ui.activity.isRtl 39 | 40 | 41 | class MIUIPopup(private val context: Context, view: View, private val currentValue: String, private val dropDownWidth: Float, private val dataBacks: (String) -> Unit, private val arrayList: ArrayList): ListPopupWindow(context) { 42 | 43 | /** 44 | * 创建背景颜色 45 | * 46 | * @param color 填充色 47 | * @param strokeColor 线条颜色 48 | * @param strokeWidth 线条宽度 单位px 49 | * @param radius 角度 px,长度为4,分别表示左上,右上,右下,左下的角度 50 | */ 51 | fun createRectangleDrawable(color: Int, strokeColor: Int = 0, strokeWidth: Int, radius: FloatArray?): GradientDrawable { 52 | return try { 53 | GradientDrawable().apply { 54 | shape = GradientDrawable.RECTANGLE 55 | setColor(color) 56 | if (strokeColor != 0) setStroke(strokeWidth, strokeColor) 57 | if (radius != null && radius.size == 4) { 58 | cornerRadii = floatArrayOf( 59 | radius[0], radius[0], radius[1], 60 | radius[1], radius[2], radius[2], 61 | radius[3], radius[3] 62 | ) 63 | } 64 | } 65 | } catch (e: Exception) { 66 | GradientDrawable() 67 | } 68 | } 69 | 70 | /** 71 | * 创建点击颜色 72 | * 73 | * @param pressedDrawable 点击颜色 74 | * @param normalDrawable 正常颜色 75 | */ 76 | fun createStateListDrawable(pressedDrawable: GradientDrawable, normalDrawable: GradientDrawable): StateListDrawable { 77 | return StateListDrawable().apply { 78 | addState(intArrayOf(android.R.attr.state_focused), pressedDrawable) 79 | addState(intArrayOf(android.R.attr.state_pressed), pressedDrawable) 80 | addState(intArrayOf(-android.R.attr.state_focused), normalDrawable) 81 | } 82 | } 83 | 84 | 85 | init { 86 | setBackgroundDrawable(context.getDrawable(R.drawable.miui_rounded_corners_pop)) 87 | width = dp2px(context, dropDownWidth) 88 | height = ViewGroup.LayoutParams.WRAP_CONTENT 89 | isModal = true 90 | anchorView = view 91 | 92 | setAdapter(object: BaseAdapter() { 93 | override fun getCount(): Int = arrayList.size 94 | 95 | override fun getItem(p0: Int): Any = arrayList[p0] 96 | 97 | override fun getItemId(p0: Int): Long = p0.toLong() 98 | 99 | override fun getView(p0: Int, p1: View?, p2: ViewGroup?): View { 100 | val thisText = arrayList[p0].getName() 101 | val dataBinding = arrayList[p0].getDataBindingSend() 102 | return (p1 as? LinearLayout ?: LinearLayout(context)).apply { 103 | var radius = floatArrayOf(0f, 0f, 0f, 0f) 104 | val radiusFloat = dp2px(context, 20f).toFloat() 105 | if (arrayList.size == 1) 106 | radius = floatArrayOf(radiusFloat, radiusFloat, radiusFloat, radiusFloat) 107 | else when (p0) { 108 | 0 -> { 109 | radius = floatArrayOf(radiusFloat, radiusFloat, 0f, 0f) 110 | } 111 | arrayList.size - 1 -> { 112 | radius = floatArrayOf(0f, 0f, radiusFloat, radiusFloat) 113 | } 114 | } 115 | val pressedDrawable = createRectangleDrawable(context.getColor(if (currentValue == thisText) R.color.popup_select_click else R.color.popup_background_click), 0, 0, radius) 116 | val normalDrawable = createRectangleDrawable(context.getColor(if (currentValue == thisText) R.color.popup_select else R.color.popup_background), 0, 0, radius) 117 | background = createStateListDrawable(pressedDrawable, normalDrawable) 118 | removeAllViews() 119 | addView((object : TextView(context) { 120 | init { 121 | isFocusable = true 122 | } 123 | 124 | override fun isFocused(): Boolean { 125 | return true 126 | } 127 | 128 | }).apply { 129 | layoutParams = LinearLayout.LayoutParams(dp2px(context, dropDownWidth - 35), LinearLayout.LayoutParams.WRAP_CONTENT) 130 | descendantFocusability = LinearContainerV.FOCUS_BLOCK_DESCENDANTS 131 | setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f) 132 | if (isRtl(context)) 133 | setPadding(dp2px(context, 10f), dp2px(context, 25f), dp2px(context, 25f), dp2px(context, 25f)) 134 | else 135 | setPadding(dp2px(context, 25f), dp2px(context, 25f), dp2px(context, 10f), dp2px(context, 25f)) 136 | width = dp2px(context, 105f) 137 | isSingleLine = true 138 | text = thisText 139 | ellipsize = TextUtils.TruncateAt.MARQUEE 140 | paint.typeface = Typeface.defaultFromStyle(Typeface.BOLD) 141 | if (currentValue == thisText) setTextColor(context.getColor(R.color.popup_select_text)) else setTextColor(context.getColor(R.color.whiteText)) 142 | }) 143 | addView(ImageView(context).apply { 144 | layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { 145 | it.gravity = Gravity.CENTER_VERTICAL 146 | if (isRtl(context)) 147 | it.setMargins(dp2px(context, 20f), 0, 0, 0) 148 | else 149 | it.setMargins(0, 0, dp2px(context, 20f), 0) 150 | } 151 | background = context.getDrawable(R.drawable.ic_popup_select) 152 | if (currentValue != thisText) visibility = View.GONE 153 | }) 154 | setOnClickListener { 155 | (it as ViewGroup).apply { 156 | for (i in 0 until childCount) { 157 | val mView = getChildAt(i) 158 | if (mView is TextView) { 159 | dataBacks(mView.text.toString()) 160 | dataBinding?.send(mView.text.toString()) 161 | break 162 | } 163 | } 164 | } 165 | arrayList[p0].getCallBacks()() 166 | dismiss() 167 | } 168 | } 169 | } 170 | }) 171 | } 172 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/PageV.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.view 24 | 25 | import android.content.Context 26 | import android.graphics.Typeface 27 | import android.graphics.drawable.Drawable 28 | import android.os.Build 29 | import android.util.TypedValue 30 | import android.view.Gravity 31 | import android.view.View 32 | import android.widget.ImageView 33 | import android.widget.LinearLayout 34 | import android.widget.TextView 35 | import cn.fkj233.ui.R 36 | import cn.fkj233.ui.activity.data.DataBinding 37 | import cn.fkj233.ui.activity.data.LayoutPair 38 | import cn.fkj233.ui.activity.dp2px 39 | import cn.fkj233.ui.activity.fragment.MIUIFragment 40 | import cn.fkj233.ui.activity.isRtl 41 | 42 | class PageV( 43 | private val pageHead: Drawable, 44 | private val pageName: String?, 45 | private val pageNameId: Int?, 46 | private val round: Float = 0f, 47 | private val onClick: (() -> Unit)? = null, 48 | private val dataBindingRecv: DataBinding.Binding.Recv? = null 49 | ) : BaseView { 50 | 51 | override fun getType(): BaseView { 52 | return this 53 | } 54 | 55 | override fun create(context: Context, callBacks: (() -> Unit)?): View { 56 | return LinearContainerV(LinearContainerV.HORIZONTAL, arrayOf( 57 | LayoutPair( 58 | RoundCornerImageView(context, dp2px(context, round), dp2px(context, round)).also { 59 | it.background = pageHead 60 | }, 61 | LinearLayout.LayoutParams( 62 | dp2px(context, 30f), 63 | dp2px(context, 30f) 64 | ) 65 | ), 66 | LayoutPair( 67 | TextView(context).also { 68 | if (isRtl(context)) 69 | it.setPadding(0, 0, dp2px(context, 16f), 0) 70 | else 71 | it.setPadding(dp2px(context, 16f), 0, 0, 0) 72 | it.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f) 73 | it.setTextColor(context.getColor(R.color.whiteText)) 74 | pageName?.let { it1 -> it.text = it1 } 75 | pageNameId?.let { it1 -> it.setText(it1) } 76 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 77 | it.paint.typeface = Typeface.create(null, 500, false) 78 | } else { 79 | it.paint.typeface = Typeface.defaultFromStyle(Typeface.BOLD) 80 | } 81 | }, 82 | LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f).also { it.gravity = Gravity.CENTER_VERTICAL } 83 | ), 84 | LayoutPair( 85 | ImageView(context).also { it.background = context.getDrawable(R.drawable.ic_right_arrow) }, 86 | LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { it.gravity = Gravity.CENTER_VERTICAL }) 87 | ), layoutParams = LinearLayout.LayoutParams( 88 | LinearLayout.LayoutParams.MATCH_PARENT, 89 | LinearLayout.LayoutParams.WRAP_CONTENT 90 | ).also { 91 | it.setMargins(0, dp2px(context, 14.8f), 0, dp2px(context, 14.8f)) 92 | }).create(context, callBacks).also { 93 | dataBindingRecv?.setView(it) 94 | } 95 | } 96 | 97 | override fun onDraw(thiz: MIUIFragment, group: LinearLayout, view: View) { 98 | thiz.apply { 99 | group.apply { 100 | addView(view) 101 | onClick?.let { unit -> 102 | setOnClickListener { 103 | unit() 104 | callBacks?.let { it1 -> it1() } 105 | } 106 | } 107 | } 108 | } 109 | } 110 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/RadioViewV.kt: -------------------------------------------------------------------------------- 1 | package cn.fkj233.ui.activity.view 2 | 3 | import android.content.Context 4 | import android.graphics.Typeface 5 | import android.os.Build 6 | import android.util.TypedValue 7 | import android.view.View 8 | import android.widget.LinearLayout 9 | import android.widget.RadioButton 10 | import android.widget.RadioGroup 11 | import cn.fkj233.ui.R 12 | import cn.fkj233.ui.activity.MIUIActivity 13 | import cn.fkj233.ui.activity.data.DataBinding 14 | import cn.fkj233.ui.activity.dp2px 15 | import cn.fkj233.ui.activity.fragment.MIUIFragment 16 | import cn.fkj233.ui.activity.isRtl 17 | 18 | class RadioViewV(private val key: String, val dataBindingRecv: DataBinding.Binding.Recv? = null, val data: RadioData.() -> Unit) : BaseView { 19 | data class RadioDataValue(val value: String, val name: String, val dataBindingRecv: DataBinding.Binding.Recv?, val dataBindingSend: DataBinding.Binding.Send?, val callBacks: ((View, Any) -> Unit)?) 20 | 21 | class RadioData { 22 | val data: ArrayList = arrayListOf() 23 | 24 | fun add(value: String, name: String, dataBindingRecv: DataBinding.Binding.Recv? = null, dataBindingSend: DataBinding.Binding.Send? = null, callBacks: ((View, Any) -> Unit)? = null) { 25 | data.add(RadioDataValue(value, name, dataBindingRecv, dataBindingSend, callBacks)) 26 | } 27 | } 28 | 29 | override fun getType(): BaseView = this 30 | 31 | override fun create(context: Context, callBacks: (() -> Unit)?): View { 32 | val data = RadioData().apply(data) 33 | val viewId: HashMap = hashMapOf() 34 | return RadioGroup(context).apply { 35 | layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT) 36 | orientation = LinearLayout.VERTICAL 37 | for (radioData in data.data) { 38 | addView(RadioButton(context).apply { 39 | id = View.generateViewId() 40 | viewId[radioData.value] = id 41 | layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT) 42 | text = radioData.name 43 | setTextColor(context.getColor(R.color.whiteText)) 44 | setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f) 45 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 46 | paint.typeface = Typeface.create(null, 500, false) 47 | } else { 48 | paint.typeface = Typeface.defaultFromStyle(Typeface.BOLD) 49 | } 50 | if (isRtl(context)) 51 | setPadding(dp2px(context, 35f), dp2px(context, 20f), dp2px(context, 30f), dp2px(context, 20f)) 52 | else 53 | setPadding(dp2px(context, 30f), dp2px(context, 20f), dp2px(context, 35f), dp2px(context, 20f)) 54 | buttonDrawable = null 55 | background = context.getDrawable(R.drawable.ic_click_check) 56 | val drawable = context.getDrawable(android.R.drawable.btn_radio).also { it?.setBounds(0,0,60,60) } 57 | if (isRtl(context)) 58 | setCompoundDrawables(drawable, null, null, null) 59 | else 60 | setCompoundDrawables(null, null, drawable, null) 61 | setOnClickListener { view -> 62 | radioData.callBacks?.let { it(view, radioData.value) } 63 | radioData.dataBindingSend?.send(radioData.value) 64 | MIUIActivity.safeSP.putAny(key, radioData.value) 65 | } 66 | radioData.dataBindingRecv?.setView(this) 67 | }) 68 | } 69 | viewId[MIUIActivity.safeSP.getString(key, "")]?.let { check(it) } 70 | dataBindingRecv?.setView(this) 71 | } 72 | } 73 | 74 | override fun onDraw(thiz: MIUIFragment, group: LinearLayout, view: View) { 75 | thiz.apply { 76 | group.apply { 77 | setPadding(0, 0, 0, 0) 78 | addView(view) 79 | } 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/RoundCornerImageView.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.view 24 | 25 | import android.annotation.SuppressLint 26 | import android.content.Context 27 | import android.graphics.* 28 | import android.widget.ImageView 29 | 30 | @SuppressLint("ViewConstructor") 31 | class RoundCornerImageView(context: Context, private val roundWidth: Int = 5, private val roundHeight: Int = 5) : ImageView(context) { 32 | private var paint: Paint? = null 33 | private var paint2: Paint? = null 34 | 35 | init { 36 | paint = Paint() 37 | paint!!.color = Color.WHITE 38 | paint!!.isAntiAlias = true 39 | paint!!.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OUT) 40 | paint2 = Paint() 41 | paint2!!.xfermode = null 42 | } 43 | 44 | override fun draw(canvas: Canvas) { 45 | val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) 46 | val canvas2 = Canvas(bitmap) 47 | super.draw(canvas2) 48 | drawLiftUp(canvas2) 49 | drawRightUp(canvas2) 50 | drawLiftDown(canvas2) 51 | drawRightDown(canvas2) 52 | canvas.drawBitmap(bitmap, 0f, 0f, paint2) 53 | bitmap.recycle() 54 | } 55 | 56 | private fun drawLiftUp(canvas: Canvas) { 57 | canvas.drawPath(Path().apply { 58 | moveTo(0f, roundHeight.toFloat()) 59 | lineTo(0f, 0f) 60 | lineTo(roundWidth.toFloat(), 0f) 61 | arcTo( 62 | RectF( 63 | 0f, 64 | 0f, 65 | (roundWidth * 2).toFloat(), 66 | (roundHeight * 2).toFloat() 67 | ), -90f, -90f 68 | ) 69 | close() 70 | }, paint!!) 71 | } 72 | 73 | private fun drawLiftDown(canvas: Canvas) { 74 | canvas.drawPath(Path().apply { 75 | moveTo(0f, (height - roundHeight).toFloat()) 76 | lineTo(0f, height.toFloat()) 77 | lineTo(roundWidth.toFloat(), height.toFloat()) 78 | arcTo( 79 | RectF( 80 | 0f, 81 | (height - roundHeight * 2).toFloat(), 82 | (0 + roundWidth * 2).toFloat(), 83 | height.toFloat() 84 | ), 90f, 90f 85 | ) 86 | close() 87 | }, paint!!) 88 | } 89 | 90 | private fun drawRightDown(canvas: Canvas) { 91 | canvas.drawPath(Path().apply { 92 | moveTo((width - roundWidth).toFloat(), height.toFloat()) 93 | lineTo(width.toFloat(), height.toFloat()) 94 | lineTo(width.toFloat(), (height - roundHeight).toFloat()) 95 | arcTo( 96 | RectF( 97 | (width - roundWidth * 2).toFloat(), 98 | (height - roundHeight * 2).toFloat(), 99 | width.toFloat(), 100 | height.toFloat() 101 | ), 0f, 90f 102 | ) 103 | close() 104 | }, paint!!) 105 | } 106 | 107 | private fun drawRightUp(canvas: Canvas) { 108 | canvas.drawPath(Path().apply { 109 | moveTo(width.toFloat(), roundHeight.toFloat()) 110 | lineTo(width.toFloat(), 0f) 111 | lineTo((width - roundWidth).toFloat(), 0f) 112 | arcTo( 113 | RectF( 114 | (width - roundWidth * 2).toFloat(), 115 | 0f, 116 | width.toFloat(), 117 | (0 + roundHeight * 2).toFloat() 118 | ), -90f, 90f 119 | ) 120 | close() 121 | }, paint!!) 122 | } 123 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/SeekBarV.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.view 24 | 25 | import android.content.Context 26 | import android.os.Build 27 | import android.view.View 28 | import android.view.ViewGroup 29 | import android.widget.LinearLayout 30 | import android.widget.SeekBar 31 | import android.widget.TextView 32 | import cn.fkj233.ui.R 33 | import cn.fkj233.ui.activity.MIUIActivity 34 | import cn.fkj233.ui.activity.data.DataBinding 35 | import cn.fkj233.ui.activity.dp2px 36 | import cn.fkj233.ui.activity.fragment.MIUIFragment 37 | 38 | class SeekBarV( 39 | val key: String = "", 40 | private val min: Int, 41 | val max: Int, 42 | private val defaultProgress: Int, 43 | private val dataSend: DataBinding.Binding.Send? = null, 44 | private val dataBindingRecv: DataBinding.Binding.Recv? = null, 45 | val callBacks: ((Int, TextView) -> Unit)? = null 46 | ) : BaseView { 47 | 48 | override fun getType(): BaseView = this 49 | 50 | override fun create(context: Context, callBacks: (() -> Unit)?): View { 51 | return SeekBar(context).also { view -> 52 | view.thumb = null 53 | view.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) 54 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { 55 | view.maxHeight = dp2px(context, 35f) 56 | view.minHeight = dp2px(context, 35f) 57 | } 58 | view.isIndeterminate = false 59 | view.progressDrawable = context.getDrawable(R.drawable.seekbar_progress_drawable) 60 | view.indeterminateDrawable = context.getDrawable(R.color.colorAccent) 61 | view.min = min 62 | view.max = max 63 | if (MIUIActivity.safeSP.containsKey(key)) { 64 | MIUIActivity.safeSP.getInt(key, defaultProgress).let { 65 | view.progress = it 66 | } 67 | } else { 68 | view.progress = defaultProgress 69 | MIUIActivity.safeSP.putAny(key, defaultProgress) 70 | } 71 | view.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { 72 | override fun onProgressChanged(p0: SeekBar?, p1: Int, p2: Boolean) { 73 | callBacks?.let { it() } 74 | dataSend?.send(p1) 75 | MIUIActivity.safeSP.putAny(key, p1) 76 | } 77 | 78 | override fun onStartTrackingTouch(p0: SeekBar?) {} 79 | override fun onStopTrackingTouch(p0: SeekBar?) {} 80 | }) 81 | dataBindingRecv?.setView(view) 82 | } 83 | } 84 | 85 | override fun onDraw(thiz: MIUIFragment, group: LinearLayout, view: View) { 86 | thiz.apply { 87 | group.apply { 88 | addView(LinearLayout(context).apply { 89 | setPadding(dp2px(context, 12f), 0, dp2px(context, 12f), 0) 90 | addView(view, LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)) 91 | }) 92 | } 93 | } 94 | } 95 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/SeekBarWithTextV.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.view 24 | 25 | import android.annotation.TargetApi 26 | import android.content.Context 27 | import android.graphics.Typeface 28 | import android.os.Build 29 | import android.view.View 30 | import android.view.ViewGroup 31 | import android.widget.LinearLayout 32 | import android.widget.SeekBar 33 | import android.widget.TextView 34 | import cn.fkj233.ui.R 35 | import cn.fkj233.ui.activity.MIUIActivity 36 | import cn.fkj233.ui.activity.data.DataBinding 37 | import cn.fkj233.ui.activity.data.LayoutPair 38 | import cn.fkj233.ui.activity.dp2px 39 | import cn.fkj233.ui.activity.fragment.MIUIFragment 40 | 41 | class SeekBarWithTextV(val key: String = "", private val min: Int, private val max: Int, private val defaultProgress: Int = 0, private val dataBindingRecv: DataBinding.Binding.Recv? = null, private val dataBindingSend: DataBinding.Binding.Send? = null, val callBacks: ((Int, TextView) -> Unit)? = null) : BaseView { 42 | 43 | override fun getType(): BaseView = this 44 | 45 | @TargetApi(Build.VERSION_CODES.P) 46 | override fun create(context: Context, callBack: (() -> Unit)?): View { 47 | val minText = TextV(min.toString(), textSize = 13f, colorId = R.color.author_tips, typeface = Typeface.create(null, 400, false)).create(context, null) 48 | val maxText = TextV(max.toString(), textSize = 13f, colorId = R.color.author_tips, typeface = Typeface.create(null, 400, false)).create(context, null) 49 | val mutableText = TextV("", textSize = 13f, colorId = R.color.author_tips, typeface = Typeface.create(null, 400, false)).create(context, null) 50 | val seekBar = SeekBar(context).also { view -> 51 | view.thumb = null 52 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { 53 | view.maxHeight = dp2px(context, 31f) 54 | view.minHeight = dp2px(context, 31f) 55 | } 56 | view.isIndeterminate = false 57 | view.progressDrawable = context.getDrawable(R.drawable.seekbar_progress_drawable) 58 | view.indeterminateDrawable = context.getDrawable(R.color.colorAccent) 59 | view.min = min 60 | view.max = max 61 | view.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) 62 | if (MIUIActivity.safeSP.containsKey(key)) { 63 | MIUIActivity.safeSP.getInt(key, defaultProgress).let { 64 | view.progress = it 65 | (mutableText as TextView).text = it.toString() 66 | } 67 | } else { 68 | view.progress = defaultProgress 69 | (mutableText as TextView).text = defaultProgress.toString() 70 | MIUIActivity.safeSP.putAny(key, defaultProgress) 71 | } 72 | view.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { 73 | override fun onProgressChanged(p0: SeekBar?, p1: Int, p2: Boolean) { 74 | dataBindingSend?.send(p1) 75 | (mutableText as TextView).text = p1.toString() 76 | MIUIActivity.safeSP.putAny(key, p1) 77 | callBacks?.let { it(p1, mutableText) } 78 | } 79 | 80 | override fun onStartTrackingTouch(p0: SeekBar?) {} 81 | override fun onStopTrackingTouch(p0: SeekBar?) {} 82 | }) 83 | } 84 | return LinearContainerV(LinearContainerV.VERTICAL, arrayOf(LayoutPair(seekBar.also { it.setPadding(0, 0, 0, 0) }, LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)), LayoutPair(LinearContainerV(LinearContainerV.HORIZONTAL, arrayOf(LayoutPair(minText.also { it.setPadding(0, dp2px(context, 5f), 0, dp2px(context, 17.75f)) }, LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)), LayoutPair(mutableText.also { it.textAlignment = TextView.TEXT_ALIGNMENT_CENTER; it.setPadding(0, dp2px(context, 5f), 0, dp2px(context, 17.75f)) }, LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)), LayoutPair(maxText.also { it.textAlignment = TextView.TEXT_ALIGNMENT_VIEW_END; it.setPadding(0, dp2px(context, 5f), 0, dp2px(context, 17.75f)) }, LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)))).create(context, callBack).also { it.setPadding(0, 0, 0, 0) }, LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)))).create(context, null).also { 85 | dataBindingRecv?.setView(it) 86 | } 87 | } 88 | 89 | override fun onDraw(thiz: MIUIFragment, group: LinearLayout, view: View) { 90 | thiz.apply { 91 | group.apply { 92 | addView(view, LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)) 93 | } 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/SpinnerV.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.view 24 | 25 | import android.content.Context 26 | import android.graphics.Typeface 27 | import android.os.Build 28 | import android.util.TypedValue 29 | import android.view.Gravity 30 | import android.view.View 31 | import android.view.ViewGroup 32 | import android.widget.ImageView 33 | import android.widget.LinearLayout 34 | import android.widget.TextView 35 | import cn.fkj233.ui.R 36 | import cn.fkj233.ui.activity.data.DataBinding 37 | import cn.fkj233.ui.activity.data.LayoutPair 38 | import cn.fkj233.ui.activity.data.MIUIPopupData 39 | import cn.fkj233.ui.activity.dp2px 40 | import cn.fkj233.ui.activity.isRtl 41 | 42 | /** 43 | * Spinner / 下拉框 44 | * @param currentValue current select value / 当前选中的值 (name) 45 | * @param dropDownWidth Spinner width / 下拉框宽度 46 | * @param dataBindingSend Data binding send / 数据绑定发送 (name) 47 | * @param dataBindingRecv Data binding recv / 数据绑定接收 48 | * @param data Spinner data / 下拉框数据 49 | */ 50 | class SpinnerV(var currentValue: String, val dropDownWidth: Float = 150F, val dataBindingSend: DataBinding.Binding.Send? = null, private val dataBindingRecv: DataBinding.Binding.Recv? = null, val data: SpinnerData.() -> Unit): BaseView { 51 | 52 | class SpinnerData { 53 | val arrayList: ArrayList = arrayListOf() 54 | 55 | fun add(name: String, dataBindingSend: DataBinding.Binding.Send? = null, callBacks: () -> Unit) { 56 | arrayList.add(MIUIPopupData(name, dataBindingSend, callBacks)) 57 | } 58 | } 59 | 60 | private lateinit var context: Context 61 | 62 | lateinit var select: TextView 63 | 64 | override fun getType(): BaseView = this 65 | 66 | override fun create(context: Context, callBacks: (() -> Unit)?): View { 67 | this.context = context 68 | return LinearContainerV( 69 | LinearContainerV.HORIZONTAL, 70 | arrayOf( 71 | LayoutPair( 72 | TextView(context).also { 73 | it.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12f) 74 | it.gravity = if (isRtl(context)) Gravity.LEFT else Gravity.RIGHT 75 | it.text = currentValue 76 | it.setTextColor(context.getColor(R.color.spinner)) 77 | select = it 78 | it.width = dp2px(context, dropDownWidth) 79 | if (isRtl(context)) 80 | it.setPadding(dp2px(context, 5f), 0, dp2px(context, 30f), 0) 81 | else 82 | it.setPadding(dp2px(context, 30f), 0, dp2px(context, 5f), 0) 83 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 84 | it.paint.typeface = Typeface.create(null, 400, false) 85 | } else { 86 | it.paint.typeface = Typeface.defaultFromStyle(Typeface.BOLD) 87 | } 88 | it.setTextSize(TypedValue.COMPLEX_UNIT_SP, 15f) 89 | }, 90 | LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1f) 91 | ), 92 | LayoutPair( 93 | ImageView(context).also { 94 | it.background = context.getDrawable(R.drawable.ic_up_down) 95 | }, 96 | LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { it.gravity = Gravity.CENTER_VERTICAL } 97 | ) 98 | ), 99 | descendantFocusability = ViewGroup.FOCUS_BLOCK_DESCENDANTS, 100 | layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1f).also { it.gravity = Gravity.CENTER_VERTICAL } 101 | ).create(context, callBacks).also { 102 | dataBindingRecv?.setView(it) 103 | } 104 | } 105 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/SwitchV.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.view 24 | 25 | 26 | import android.content.Context 27 | import android.view.View 28 | import cn.fkj233.ui.activity.MIUIActivity 29 | import cn.fkj233.ui.activity.data.DataBinding 30 | import cn.fkj233.ui.switch.MIUISwitch 31 | 32 | class SwitchV(private val key: String, private val defValue: Boolean = false, private val dataBindingRecv: DataBinding.Binding.Recv? = null, private val dataBindingSend: DataBinding.Binding.Send? = null, private val onClickListener: ((Boolean) -> Unit)? = null): BaseView { 33 | 34 | lateinit var switch: MIUISwitch 35 | 36 | override fun getType(): BaseView = this 37 | 38 | override fun create(context: Context, callBacks: (() -> Unit)?): View { 39 | return MIUISwitch(context).also { 40 | switch = it 41 | dataBindingRecv?.setView(it) 42 | if (!MIUIActivity.safeSP.containsKey(key)) { 43 | MIUIActivity.safeSP.putAny(key, defValue) 44 | } 45 | it.isChecked = MIUIActivity.safeSP.getBoolean(key, defValue) 46 | it.setOnCheckedChangeListener { _, b -> 47 | dataBindingSend?.let { send -> 48 | send.send(b) 49 | } 50 | callBacks?.let { it1 -> it1() } 51 | onClickListener?.let { it(b) } 52 | MIUIActivity.safeSP.putAny(key, b) 53 | } 54 | } 55 | } 56 | 57 | fun click() { 58 | switch.isChecked = !switch.isChecked 59 | dataBindingSend?.let { send -> 60 | send.send(switch.isChecked) 61 | } 62 | onClickListener?.let { it(switch.isChecked) } 63 | MIUIActivity.safeSP.putAny(key, switch.isChecked) 64 | } 65 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/TextSummaryV.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.view 24 | 25 | import android.content.Context 26 | import android.graphics.Typeface 27 | import android.os.Build 28 | import android.util.TypedValue 29 | import android.view.Gravity 30 | import android.view.View 31 | import android.widget.LinearLayout 32 | import android.widget.TextView 33 | import cn.fkj233.ui.R 34 | import cn.fkj233.ui.activity.data.DataBinding 35 | import cn.fkj233.ui.activity.data.LayoutPair 36 | import cn.fkj233.ui.activity.dp2px 37 | import cn.fkj233.ui.activity.fragment.MIUIFragment 38 | import cn.fkj233.ui.activity.isRtl 39 | 40 | class TextSummaryV(private val text: String? = null, private val textId: Int? = null, private val tips: String? = null, private val colorInt: Int? = null, private val colorId: Int? = null, private val tipsId: Int? = null, private val dataBindingRecv: DataBinding.Binding.Recv? = null, val onClickListener: (() -> Unit)? = null): BaseView { 41 | 42 | private var notShowMargins = false 43 | 44 | override fun getType(): BaseView { 45 | return this 46 | } 47 | 48 | fun notShowMargins(boolean: Boolean) { 49 | notShowMargins = boolean 50 | } 51 | 52 | override fun create(context: Context, callBacks: (() -> Unit)?): View { 53 | return LinearContainerV(LinearContainerV.VERTICAL, arrayOf( 54 | LayoutPair( 55 | TextView(context).also { view -> 56 | view.setTextSize(TypedValue.COMPLEX_UNIT_SP, if (text == null && textId == null) 15f else 18.25f) 57 | view.gravity = if (isRtl(context)) Gravity.RIGHT else Gravity.LEFT 58 | colorInt?.let { view.setTextColor(colorInt) } 59 | colorId?.let { view.setTextColor(context.getColor(colorId)) } 60 | if (colorId == null && colorInt == null) { 61 | view.setTextColor(context.getColor(R.color.whiteText)) 62 | } 63 | text?.let { it1 -> view.text = it1 } 64 | textId?.let { it1 -> view.setText(it1) } 65 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 66 | view.paint.typeface = Typeface.create(null, 500,false) 67 | } else { 68 | view.paint.typeface = Typeface.defaultFromStyle(Typeface.BOLD) 69 | } 70 | }, 71 | LinearLayout.LayoutParams( 72 | LinearLayout.LayoutParams.MATCH_PARENT, 73 | LinearLayout.LayoutParams.MATCH_PARENT 74 | ) 75 | ), 76 | LayoutPair( 77 | TextView(context).also { 78 | it.gravity = if (isRtl(context)) Gravity.RIGHT else Gravity.LEFT 79 | it.setTextSize(TypedValue.COMPLEX_UNIT_SP, 13.75f) 80 | it.setTextColor(context.getColor(R.color.author_tips)) 81 | if (tips == null && tipsId == null) { 82 | it.visibility = View.GONE 83 | } else { 84 | tips?.let { it1 -> it.text = it1 } 85 | tipsId?.let { it1 -> it.setText(it1) } 86 | } 87 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 88 | it.paint.typeface = Typeface.create(null, 350,false) 89 | } else { 90 | it.paint.typeface = Typeface.defaultFromStyle(Typeface.BOLD) 91 | } 92 | }, 93 | LinearLayout.LayoutParams( 94 | LinearLayout.LayoutParams.MATCH_PARENT, 95 | LinearLayout.LayoutParams.MATCH_PARENT 96 | ) 97 | ) 98 | ), layoutParams = LinearLayout.LayoutParams( 99 | LinearLayout.LayoutParams.MATCH_PARENT, 100 | LinearLayout.LayoutParams.WRAP_CONTENT 101 | ).also { 102 | if (!notShowMargins) it.setMargins(0, dp2px(context, 15f),0, dp2px(context, 15f)) 103 | }).create(context, callBacks).also { 104 | dataBindingRecv?.setView(it) 105 | } 106 | } 107 | 108 | override fun onDraw(thiz: MIUIFragment, group: LinearLayout, view: View) { 109 | thiz.apply { 110 | group.apply { 111 | addView(view) 112 | onClickListener?.let { unit -> 113 | setOnClickListener { 114 | unit() 115 | callBacks?.let { it1 -> it1() } 116 | } 117 | } 118 | } 119 | } 120 | } 121 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/TextSummaryWithArrowV.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.view 24 | 25 | import android.content.Context 26 | import android.view.Gravity 27 | import android.view.View 28 | import android.widget.ImageView 29 | import android.widget.LinearLayout 30 | import cn.fkj233.ui.R 31 | import cn.fkj233.ui.activity.data.DataBinding 32 | import cn.fkj233.ui.activity.data.LayoutPair 33 | import cn.fkj233.ui.activity.dp2px 34 | import cn.fkj233.ui.activity.fragment.MIUIFragment 35 | 36 | class TextSummaryWithArrowV(private val textSummaryV: TextSummaryV, private val dataBindingRecv: DataBinding.Binding.Recv? = null): BaseView { 37 | 38 | override fun getType(): BaseView { 39 | return this 40 | } 41 | 42 | override fun create(context: Context, callBacks: (() -> Unit)?): View { 43 | textSummaryV.notShowMargins(true) 44 | return LinearContainerV(LinearContainerV.HORIZONTAL, arrayOf( 45 | LayoutPair(textSummaryV.create(context, callBacks), LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)), 46 | LayoutPair(ImageView(context).also { it.background = context.getDrawable(R.drawable.ic_right_arrow) }, LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { it.gravity = Gravity.CENTER_VERTICAL }) 47 | ), layoutParams = LinearLayout.LayoutParams( 48 | LinearLayout.LayoutParams.MATCH_PARENT, 49 | LinearLayout.LayoutParams.WRAP_CONTENT 50 | ).also { 51 | it.setMargins(0, dp2px(context, 17.75f),0, dp2px(context, 17.75f)) 52 | }).create(context, callBacks).also { 53 | dataBindingRecv?.setView(it) 54 | } 55 | } 56 | 57 | override fun onDraw(thiz: MIUIFragment, group: LinearLayout, view: View) { 58 | thiz.apply { 59 | group.apply { 60 | addView(view) 61 | textSummaryV.onClickListener?.let { unit -> 62 | setOnClickListener { 63 | unit() 64 | callBacks?.let { it1 -> it1() } 65 | } 66 | } 67 | } 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/TextSummaryWithSeekBarV.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.view 24 | 25 | import android.content.Context 26 | import android.view.View 27 | import android.widget.LinearLayout 28 | import cn.fkj233.ui.activity.data.DataBinding 29 | import cn.fkj233.ui.activity.data.LayoutPair 30 | import cn.fkj233.ui.activity.dp2px 31 | 32 | class TextSummaryWithSeekBarV(private val textSummaryV: TextSummaryV, private val seekBarWithTextV: SeekBarWithTextV, private val dataBindingRecv: DataBinding.Binding.Recv? = null) : BaseView { 33 | 34 | override fun getType(): BaseView = this 35 | 36 | override fun create(context: Context, callBacks: (() -> Unit)?): View { 37 | textSummaryV.notShowMargins(true) 38 | return LinearContainerV( 39 | LinearContainerV.VERTICAL, arrayOf( 40 | LayoutPair(textSummaryV.create(context, callBacks), LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { it.setMargins(0, dp2px(context, 17.75f), 0, dp2px(context, 5f)) }), 41 | LayoutPair(seekBarWithTextV.create(context, callBacks), LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)) 42 | ), layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT) 43 | ).create(context, callBacks).also { 44 | dataBindingRecv?.setView(it) 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/TextSummaryWithSpinnerV.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.view 24 | 25 | import android.annotation.SuppressLint 26 | import android.content.Context 27 | import android.view.Gravity 28 | import android.view.MotionEvent 29 | import android.view.View 30 | import android.widget.LinearLayout 31 | import cn.fkj233.ui.activity.data.DataBinding 32 | import cn.fkj233.ui.activity.data.LayoutPair 33 | import cn.fkj233.ui.activity.dp2px 34 | import cn.fkj233.ui.activity.fragment.MIUIFragment 35 | 36 | class TextSummaryWithSpinnerV(private val textSummaryV: TextSummaryV, private val spinnerV: SpinnerV, private val dataBindingRecv: DataBinding.Binding.Recv? = null): BaseView { 37 | 38 | override fun getType(): BaseView = this 39 | 40 | override fun create(context: Context, callBacks: (() -> Unit)?): View { 41 | return LinearContainerV( 42 | LinearContainerV.HORIZONTAL, 43 | arrayOf( 44 | LayoutPair(textSummaryV.create(context, callBacks), LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)), 45 | LayoutPair(spinnerV.create(context, callBacks), LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { it.gravity = Gravity.CENTER_VERTICAL }) 46 | ), 47 | descendantFocusability = LinearContainerV.FOCUS_BLOCK_DESCENDANTS, 48 | layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT).also { 49 | it.setMargins(0, dp2px(context, 17.75f),0, dp2px(context, 17.75f)) 50 | } 51 | ).create(context, callBacks).also { 52 | dataBindingRecv?.setView(it) 53 | } 54 | } 55 | 56 | @SuppressLint("ClickableViewAccessibility") 57 | override fun onDraw(thiz: MIUIFragment, group: LinearLayout, view: View) { 58 | thiz.apply { 59 | group.apply { 60 | addView(view) 61 | setOnClickListener {} 62 | setOnTouchListener { view, motionEvent -> 63 | if (motionEvent.action == MotionEvent.ACTION_UP) { 64 | val popup = MIUIPopup(context, view, spinnerV.currentValue, spinnerV.dropDownWidth, { 65 | spinnerV.select.text = it 66 | spinnerV.currentValue = it 67 | callBacks?.let { it1 -> it1() } 68 | spinnerV.dataBindingSend?.send(it) 69 | }, SpinnerV.SpinnerData().apply(spinnerV.data).arrayList) 70 | if (view.width / 2 >= motionEvent.x) { 71 | popup.apply { 72 | horizontalOffset = dp2px(context, 24F) 73 | setDropDownGravity(Gravity.LEFT) 74 | } 75 | } else { 76 | popup.apply { 77 | horizontalOffset = -dp2px(context, 24F) 78 | setDropDownGravity(Gravity.RIGHT) 79 | } 80 | } 81 | popup.show() 82 | } 83 | false 84 | } 85 | } 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/TextSummaryWithSwitchV.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.view 24 | 25 | import android.annotation.SuppressLint 26 | import android.content.Context 27 | import android.view.Gravity 28 | import android.view.MotionEvent 29 | import android.view.View 30 | import android.widget.LinearLayout 31 | import cn.fkj233.ui.R 32 | import cn.fkj233.ui.activity.data.DataBinding 33 | import cn.fkj233.ui.activity.data.LayoutPair 34 | import cn.fkj233.ui.activity.dp2px 35 | import cn.fkj233.ui.activity.fragment.MIUIFragment 36 | 37 | class TextSummaryWithSwitchV(private val textSummaryV: TextSummaryV, private val switchV: SwitchV, private val dataBindingRecv: DataBinding.Binding.Recv? = null): BaseView { 38 | 39 | override fun getType(): BaseView = this 40 | 41 | override fun create(context: Context, callBacks: (() -> Unit)?): View { 42 | textSummaryV.notShowMargins(true) 43 | return LinearContainerV( 44 | LinearContainerV.HORIZONTAL, 45 | arrayOf( 46 | LayoutPair(textSummaryV.create(context, callBacks), LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)), 47 | LayoutPair(switchV.create(context, callBacks), LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { it.gravity = Gravity.CENTER_VERTICAL }) 48 | ), 49 | layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT).also { 50 | it.setMargins(0, dp2px(context, 17.75f),0, dp2px(context, 17.75f)) 51 | } 52 | ).create(context, callBacks).also { 53 | dataBindingRecv?.setView(it) 54 | } 55 | } 56 | 57 | @SuppressLint("ClickableViewAccessibility") 58 | override fun onDraw(thiz: MIUIFragment, group: LinearLayout, view: View) { 59 | thiz.apply { 60 | group.apply { 61 | addView(view) // 带文本的开关 62 | setOnTouchListener { _, motionEvent -> 63 | when (motionEvent.action) { 64 | MotionEvent.ACTION_DOWN -> if (switchV.switch.isEnabled) background = context.getDrawable(R.drawable.ic_main_down_bg) 65 | MotionEvent.ACTION_UP -> { 66 | val touchX: Float = motionEvent.x 67 | val touchY: Float = motionEvent.y 68 | val maxX = width.toFloat() 69 | val maxY = height.toFloat() 70 | if (touchX < 0 || touchX > maxX || touchY < 0 || touchY > maxY) { 71 | isPressed = false 72 | return@setOnTouchListener false 73 | } 74 | if (switchV.switch.isEnabled) { 75 | switchV.click() 76 | callBacks?.let { it1 -> it1() } 77 | background = context.getDrawable(R.drawable.ic_main_bg) 78 | } 79 | } 80 | else -> background = context.getDrawable(R.drawable.ic_main_bg) 81 | } 82 | true 83 | } 84 | } 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/TextV.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.view 24 | 25 | 26 | import android.content.Context 27 | import android.graphics.Typeface 28 | import android.os.Build 29 | import android.util.TypedValue 30 | import android.view.Gravity 31 | import android.view.View 32 | import android.widget.LinearLayout 33 | import android.widget.TextView 34 | import cn.fkj233.ui.R 35 | import cn.fkj233.ui.activity.data.DataBinding 36 | import cn.fkj233.ui.activity.data.Padding 37 | import cn.fkj233.ui.activity.dp2px 38 | import cn.fkj233.ui.activity.fragment.MIUIFragment 39 | import cn.fkj233.ui.activity.isRtl 40 | 41 | class TextV(val text: String? = null, private val textId: Int? = null, val textSize: Float? = null, private val colorInt: Int? = null, private val colorId: Int? = null, private val padding: Padding? = null, private val dataBindingRecv: DataBinding.Binding.Recv? = null, private val typeface: Typeface? = null, val onClickListener: (() -> Unit)? = null): BaseView { 42 | 43 | private var notShowMargins = false 44 | 45 | override fun getType(): BaseView = this 46 | 47 | fun notShowMargins(boolean: Boolean) { 48 | notShowMargins = boolean 49 | } 50 | 51 | override fun create(context: Context, callBacks: (() -> Unit)?): View { 52 | return TextView(context).also { view -> 53 | view.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1f) 54 | text?.let { view.text = it } 55 | view.gravity = if (isRtl(context)) Gravity.RIGHT else Gravity.LEFT 56 | textId?.let { view.setText(it) } 57 | if (textSize == null) 58 | view.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f) 59 | else 60 | view.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize) 61 | colorInt?.let { view.setTextColor(colorInt) } 62 | colorId?.let { view.setTextColor(context.getColor(colorId)) } 63 | if (colorId == null && colorInt == null) { 64 | view.setTextColor(context.getColor(R.color.whiteText)) 65 | } 66 | if (typeface == null) { 67 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 68 | view.paint.typeface = Typeface.create(null, 500, false) 69 | } else { 70 | view.paint.typeface = Typeface.defaultFromStyle(Typeface.BOLD) 71 | } 72 | } else { 73 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 74 | view.paint.typeface = typeface 75 | } else { 76 | view.paint.typeface = Typeface.defaultFromStyle(Typeface.BOLD) 77 | } 78 | } 79 | if (!notShowMargins) { 80 | if (isRtl(context)) view.setPadding(dp2px(context, 5f), dp2px(context, 20f), 0, dp2px(context, 20f)) 81 | else view.setPadding(0, dp2px(context, 20f), dp2px(context, 5f), dp2px(context, 20f)) 82 | } 83 | padding?.let { 84 | if (isRtl(context)) 85 | view.setPadding(it.right, it.top, it.left, it.bottom) 86 | else 87 | view.setPadding(it.left, it.top, it.right, it.bottom) 88 | } 89 | dataBindingRecv?.setView(view) 90 | } 91 | } 92 | 93 | override fun onDraw(thiz: MIUIFragment, group: LinearLayout, view: View) { 94 | thiz.apply { 95 | group.apply { 96 | addView(view) 97 | onClickListener?.let { unit -> 98 | setOnClickListener { 99 | unit() 100 | callBacks?.let { it1 -> it1() } 101 | } 102 | } 103 | } 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/TextWithArrowV.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.view 24 | 25 | import android.content.Context 26 | import android.view.Gravity 27 | import android.view.View 28 | import android.widget.ImageView 29 | import android.widget.LinearLayout 30 | import cn.fkj233.ui.R 31 | import cn.fkj233.ui.activity.data.DataBinding 32 | import cn.fkj233.ui.activity.data.LayoutPair 33 | import cn.fkj233.ui.activity.dp2px 34 | import cn.fkj233.ui.activity.fragment.MIUIFragment 35 | 36 | class TextWithArrowV(private val textV: TextV, private val dataBindingRecv: DataBinding.Binding.Recv? = null) : BaseView { 37 | 38 | override fun getType(): BaseView { 39 | return this 40 | } 41 | 42 | override fun create(context: Context, callBacks: (() -> Unit)?): View { 43 | textV.notShowMargins(true) 44 | return LinearContainerV(LinearContainerV.HORIZONTAL, arrayOf( 45 | LayoutPair(textV.create(context, callBacks), LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)), 46 | LayoutPair( 47 | ImageView(context).also { it.background = context.getDrawable(R.drawable.ic_right_arrow) }, 48 | LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { it.gravity = Gravity.CENTER_VERTICAL }) 49 | ), layoutParams = LinearLayout.LayoutParams( 50 | LinearLayout.LayoutParams.MATCH_PARENT, 51 | LinearLayout.LayoutParams.WRAP_CONTENT 52 | ).also { 53 | it.setMargins(0, dp2px(context, 17.75f),0, dp2px(context, 17.75f)) 54 | }).create(context, callBacks).also { 55 | dataBindingRecv?.setView(it) 56 | } 57 | } 58 | 59 | override fun onDraw(thiz: MIUIFragment, group: LinearLayout, view: View) { 60 | thiz.apply { 61 | group.apply { 62 | addView(view) 63 | textV.onClickListener?.let { unit -> 64 | setOnClickListener { 65 | unit() 66 | callBacks?.let { it1 -> it1() } 67 | } 68 | } 69 | } 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/TextWithSeekBarV.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.view 24 | 25 | import android.content.Context 26 | import android.view.View 27 | import android.widget.LinearLayout 28 | import cn.fkj233.ui.activity.data.DataBinding 29 | import cn.fkj233.ui.activity.data.LayoutPair 30 | import cn.fkj233.ui.activity.dp2px 31 | 32 | class TextWithSeekBarV(private val textV: TextV, private val seekBarWithTextV: SeekBarWithTextV, private val dataBindingRecv: DataBinding.Binding.Recv? = null) : BaseView { 33 | 34 | override fun getType(): BaseView = this 35 | 36 | override fun create(context: Context, callBacks: (() -> Unit)?): View { 37 | textV.notShowMargins(true) 38 | return LinearContainerV( 39 | LinearContainerV.VERTICAL, arrayOf( 40 | LayoutPair(textV.create(context, callBacks), LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { it.setMargins(0, dp2px(context, 17.75f), 0, dp2px(context, 5f)) }), 41 | LayoutPair(seekBarWithTextV.create(context, callBacks), LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)) 42 | ), layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT) 43 | ).create(context, callBacks).also { 44 | dataBindingRecv?.setView(it) 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/TextWithSpinnerV.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.view 24 | 25 | import android.annotation.SuppressLint 26 | import android.content.Context 27 | import android.view.Gravity 28 | import android.view.MotionEvent 29 | import android.view.View 30 | import android.widget.LinearLayout 31 | import cn.fkj233.ui.activity.data.DataBinding 32 | import cn.fkj233.ui.activity.data.LayoutPair 33 | import cn.fkj233.ui.activity.dp2px 34 | import cn.fkj233.ui.activity.fragment.MIUIFragment 35 | 36 | class TextWithSpinnerV(private val textV: TextV, private val spinnerV: SpinnerV, private val dataBindingRecv: DataBinding.Binding.Recv? = null): BaseView { 37 | 38 | override fun getType(): BaseView = this 39 | 40 | override fun create(context: Context, callBacks: (() -> Unit)?): View { 41 | return LinearContainerV( 42 | LinearContainerV.HORIZONTAL, 43 | arrayOf( 44 | LayoutPair(textV.create(context, callBacks), LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)), 45 | LayoutPair(spinnerV.create(context, callBacks), LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { it.gravity = Gravity.CENTER_VERTICAL }) 46 | ), 47 | descendantFocusability = LinearContainerV.FOCUS_BLOCK_DESCENDANTS, 48 | layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT) 49 | ).create(context, callBacks).also { 50 | dataBindingRecv?.setView(it) 51 | } 52 | } 53 | 54 | @SuppressLint("ClickableViewAccessibility") 55 | override fun onDraw(thiz: MIUIFragment, group: LinearLayout, view: View) { 56 | thiz.apply { 57 | group.apply { 58 | addView(view) 59 | setOnClickListener {} 60 | setOnTouchListener { view, motionEvent -> 61 | if (motionEvent.action == MotionEvent.ACTION_UP) { 62 | val popup = MIUIPopup(context, view, spinnerV.currentValue, spinnerV.dropDownWidth, { 63 | spinnerV.select.text = it 64 | spinnerV.currentValue = it 65 | callBacks?.let { it1 -> it1() } 66 | spinnerV.dataBindingSend?.send(it) 67 | }, SpinnerV.SpinnerData().apply(spinnerV.data).arrayList) 68 | if (view.width / 2 >= motionEvent.x) { 69 | popup.apply { 70 | horizontalOffset = dp2px(context, 24F) 71 | setDropDownGravity(Gravity.LEFT) 72 | } 73 | } else { 74 | popup.apply { 75 | horizontalOffset = - dp2px(context, 24F) 76 | setDropDownGravity(Gravity.RIGHT) 77 | } 78 | } 79 | popup.show() 80 | } 81 | false 82 | } 83 | } 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/TextWithSwitchV.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.view 24 | 25 | import android.annotation.SuppressLint 26 | import android.content.Context 27 | import android.view.Gravity 28 | import android.view.MotionEvent 29 | import android.view.View 30 | import android.widget.LinearLayout 31 | import cn.fkj233.ui.R 32 | import cn.fkj233.ui.activity.data.DataBinding 33 | import cn.fkj233.ui.activity.data.LayoutPair 34 | import cn.fkj233.ui.activity.dp2px 35 | import cn.fkj233.ui.activity.fragment.MIUIFragment 36 | 37 | class TextWithSwitchV(private val textV: TextV, private val switchV: SwitchV, private val dataBindingRecv: DataBinding.Binding.Recv? = null) : BaseView { 38 | 39 | override fun getType(): BaseView = this 40 | 41 | override fun create(context: Context, callBacks: (() -> Unit)?): View { 42 | textV.notShowMargins(true) 43 | return LinearContainerV( 44 | LinearContainerV.HORIZONTAL, 45 | arrayOf( 46 | LayoutPair( 47 | textV.create(context, callBacks), 48 | LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1f) 49 | .also { it.gravity = Gravity.CENTER_VERTICAL } 50 | ), 51 | LayoutPair( 52 | switchV.create(context, callBacks), 53 | LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT) 54 | .also { it.gravity = Gravity.CENTER_VERTICAL }) 55 | ), layoutParams = LinearLayout.LayoutParams( 56 | LinearLayout.LayoutParams.MATCH_PARENT, 57 | LinearLayout.LayoutParams.WRAP_CONTENT 58 | ).also { 59 | it.setMargins(0, dp2px(context, 15.75f), 0, dp2px(context, 15.75f)) 60 | }) 61 | .create(context, callBacks).also { 62 | dataBindingRecv?.setView(it) 63 | } 64 | } 65 | 66 | @SuppressLint("ClickableViewAccessibility") 67 | override fun onDraw(thiz: MIUIFragment, group: LinearLayout, view: View) { 68 | thiz.apply { 69 | group.apply { 70 | addView(view) // 带文本的开关 71 | setOnTouchListener { _, motionEvent -> 72 | when (motionEvent.action) { 73 | MotionEvent.ACTION_DOWN -> if (switchV.switch.isEnabled) background = context.getDrawable(R.drawable.ic_main_down_bg) 74 | MotionEvent.ACTION_UP -> { 75 | val touchX: Float = motionEvent.x 76 | val touchY: Float = motionEvent.y 77 | val maxX = width.toFloat() 78 | val maxY = height.toFloat() 79 | if (touchX < 0 || touchX > maxX || touchY < 0 || touchY > maxY) { 80 | isPressed = false 81 | return@setOnTouchListener false 82 | } 83 | if (switchV.switch.isEnabled) { 84 | switchV.click() 85 | callBacks?.let { it1 -> it1() } 86 | background = context.getDrawable(R.drawable.ic_main_bg) 87 | } 88 | } 89 | 90 | else -> background = context.getDrawable(R.drawable.ic_main_bg) 91 | } 92 | true 93 | } 94 | } 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/activity/view/TitleTextV.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.activity.view 24 | 25 | import android.content.Context 26 | import android.graphics.Color 27 | import android.graphics.Typeface 28 | import android.os.Build 29 | import android.util.TypedValue 30 | import android.view.Gravity 31 | import android.view.View 32 | import android.widget.LinearLayout 33 | import android.widget.TextView 34 | import cn.fkj233.ui.activity.data.DataBinding 35 | import cn.fkj233.ui.activity.dp2px 36 | import cn.fkj233.ui.activity.isRtl 37 | 38 | class TitleTextV(val text: String? = null, private val textId: Int? = null, private val colorInt: Int? = null, private val colorId: Int? = null, private val dataBindingRecv: DataBinding.Binding.Recv? = null, private val onClickListener: (() -> Unit)? = null) : BaseView { 39 | 40 | override fun getType(): BaseView { 41 | return this 42 | } 43 | 44 | override fun create(context: Context, callBacks: (() -> Unit)?): View { 45 | 46 | return TextView(context).also { view -> 47 | view.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1f) 48 | text?.let { view.text = it } 49 | view.gravity = if (isRtl(context)) Gravity.RIGHT else Gravity.LEFT 50 | textId?.let { view.setText(it) } 51 | view.setTextSize(TypedValue.COMPLEX_UNIT_SP, 13f) 52 | view.setTextColor(Color.parseColor("#9399b3")) 53 | colorInt?.let { view.setTextColor(colorInt) } 54 | colorId?.let { view.setTextColor(context.getColor(colorId)) } 55 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 56 | view.paint.typeface = Typeface.create(null, 400, false) 57 | } else { 58 | view.paint.typeface = Typeface.defaultFromStyle(Typeface.BOLD) 59 | } 60 | 61 | view.setPadding(0, dp2px(context, 9.75f), dp2px(context, 5f), dp2px(context, 9.75f)) 62 | onClickListener?.let { view.setOnClickListener { it() } } 63 | dataBindingRecv?.setView(view) 64 | } 65 | 66 | } 67 | 68 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/dialog/MIUIDialog.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | package cn.fkj233.ui.dialog 24 | 25 | import android.annotation.SuppressLint 26 | import android.app.Dialog 27 | import android.content.Context 28 | import android.graphics.Typeface 29 | import android.graphics.drawable.GradientDrawable 30 | import android.os.Build 31 | import android.text.Editable 32 | import android.text.TextWatcher 33 | import android.util.DisplayMetrics 34 | import android.util.TypedValue 35 | import android.view.Gravity 36 | import android.view.View 37 | import android.view.WindowManager 38 | import android.widget.Button 39 | import android.widget.EditText 40 | import android.widget.LinearLayout 41 | import android.widget.RelativeLayout 42 | import android.widget.TextView 43 | import cn.fkj233.ui.R 44 | import cn.fkj233.ui.activity.dp2px 45 | import cn.fkj233.ui.activity.isRtl 46 | import cn.fkj233.ui.activity.view.MIUIEditText 47 | import kotlin.math.roundToInt 48 | 49 | @SuppressLint("ClickableViewAccessibility") 50 | class MIUIDialog(context: Context, private val newStyle: Boolean = true, val build: MIUIDialog.() -> Unit) : Dialog(context, R.style.CustomDialog) { 51 | 52 | private var finallyCallBacks: ((View) -> Unit)? = null 53 | 54 | private val title by lazy { 55 | TextView(context).also { textView -> 56 | textView.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { 57 | it.setMargins(0, dp2px(context, 20f), 0, dp2px(context, 20f)) 58 | } 59 | textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 19f) 60 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 61 | textView.paint.typeface = Typeface.create(null, 500, false) 62 | } 63 | textView.setTextColor(context.getColor(R.color.whiteText)) 64 | textView.gravity = Gravity.CENTER 65 | textView.setPadding(0, dp2px(context, 10f), 0, 0) 66 | } 67 | } 68 | 69 | private val message by lazy { 70 | TextView(context).also { textView -> 71 | textView.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { 72 | it.setMargins(dp2px(context, 20f), 0, dp2px(context, 20f), dp2px(context, 5f)) 73 | } 74 | textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 17f) 75 | textView.setTextColor(context.getColor(R.color.whiteText)) 76 | textView.gravity = Gravity.CENTER 77 | textView.visibility = View.GONE 78 | textView.setPadding(dp2px(context, 10f), 0, dp2px(context, 10f), 0) 79 | } 80 | } 81 | 82 | private val editText by lazy { MIUIEditText(context) } 83 | 84 | private val rButton by lazy { 85 | Button(context).also { buttonView -> 86 | buttonView.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, dp2px(context, 48f), 1f).also { 87 | it.setMargins(dp2px(context, 25f), 0, dp2px(context, 25f), 0) 88 | it.gravity = Gravity.CENTER 89 | } 90 | buttonView.typeface = Typeface.defaultFromStyle(Typeface.BOLD) 91 | buttonView.setTextColor(context.getColor(R.color.RButtonText)) 92 | buttonView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 17.5f) 93 | buttonView.stateListAnimator = null 94 | buttonView.background = context.getDrawable(R.drawable.r_button_background) 95 | buttonView.visibility = View.GONE 96 | } 97 | } 98 | 99 | private val lButton by lazy { 100 | Button(context).also { buttonView -> 101 | buttonView.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, dp2px(context, 48f), 1f).also { 102 | it.setMargins(dp2px(context, 25f), 0, dp2px(context, 25f), 0) 103 | it.gravity = Gravity.CENTER 104 | } 105 | buttonView.typeface = Typeface.defaultFromStyle(Typeface.BOLD) 106 | buttonView.setTextColor(context.getColor(R.color.LButtonText)) 107 | buttonView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 17.5f) 108 | buttonView.stateListAnimator = null 109 | buttonView.visibility = View.GONE 110 | buttonView.background = context.getDrawable(R.drawable.l_button_background) 111 | } 112 | } 113 | 114 | private val view by lazy { 115 | LinearLayout(context).also { linearLayout -> 116 | linearLayout.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT) 117 | linearLayout.orientation = LinearLayout.VERTICAL 118 | linearLayout.addView(message) 119 | linearLayout.addView(editText) 120 | } 121 | } 122 | 123 | private val root = RelativeLayout(context).also { viewRoot -> 124 | viewRoot.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT) 125 | viewRoot.addView(LinearLayout(context).also { viewLinearLayout -> 126 | viewLinearLayout.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT) 127 | viewLinearLayout.orientation = LinearLayout.VERTICAL 128 | viewLinearLayout.addView(title) 129 | viewLinearLayout.addView(view) 130 | viewLinearLayout.addView(LinearLayout(context).also { linearLayout -> 131 | linearLayout.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { 132 | it.gravity = Gravity.CENTER_HORIZONTAL 133 | } 134 | linearLayout.setPadding(0, dp2px(context, 16f), 0, dp2px(context, 24f)) 135 | linearLayout.addView(lButton) 136 | linearLayout.addView(rButton) 137 | }) 138 | }) 139 | } 140 | 141 | init { 142 | window?.setGravity(Gravity.BOTTOM) 143 | setContentView(root) 144 | window?.setBackgroundDrawable(GradientDrawable().apply { 145 | if (newStyle) { 146 | cornerRadius = dp2px(context, 32f).toFloat() 147 | } else { 148 | val dp32 = dp2px(context, 32f).toFloat() 149 | cornerRadii = floatArrayOf(dp32, dp32, dp32, dp32, 0f, 0f, 0f, 0f) 150 | } 151 | setColor(context.getColor(R.color.dialog_background)) 152 | }) 153 | } 154 | 155 | fun addView(mView: View) { 156 | view.addView(mView) 157 | } 158 | 159 | override fun setTitle(title: CharSequence?) { 160 | this.title.text = title 161 | } 162 | 163 | override fun setTitle(titleId: Int) { 164 | this.title.setText(titleId) 165 | } 166 | 167 | fun setLButton(text: CharSequence?, enable: Boolean = true) { 168 | setLButton(text, enable, null) 169 | } 170 | 171 | fun setLButton(text: CharSequence?, enable: Boolean = true, callBacks: ((View) -> Unit)?) { 172 | lButton.apply { 173 | this.isEnabled = enable 174 | visibility = View.VISIBLE 175 | setText(text) 176 | setOnClickListener { 177 | callBacks?.invoke(it) 178 | finallyCallBacks?.invoke(it) 179 | } 180 | } 181 | } 182 | 183 | fun setLButton(textId: Int, enable: Boolean = true) { 184 | setLButton(textId, enable, null) 185 | } 186 | 187 | fun setLButton(textId: Int, enable: Boolean = true, callBacks: ((View) -> Unit)?) { 188 | lButton.apply { 189 | this.isEnabled = enable 190 | visibility = View.VISIBLE 191 | setText(textId) 192 | setOnClickListener { 193 | callBacks?.invoke(it) 194 | finallyCallBacks?.invoke(it) 195 | } 196 | } 197 | } 198 | 199 | fun setRButton(text: CharSequence?, enable: Boolean = true) { 200 | setRButton(text, enable, null) 201 | } 202 | 203 | fun setRButton(text: CharSequence?, enable: Boolean = true, callBacks: ((View) -> Unit)?) { 204 | rButton.apply { 205 | setText(text) 206 | this.isEnabled = enable 207 | setOnClickListener { 208 | callBacks?.invoke(it) 209 | finallyCallBacks?.invoke(it) 210 | } 211 | visibility = View.VISIBLE 212 | } 213 | } 214 | 215 | fun setRButton(textId: Int, enable: Boolean = true) { 216 | setRButton(textId, enable, null) 217 | } 218 | 219 | fun setRButton(textId: Int, enable: Boolean = true, callBacks: ((View) -> Unit)?) { 220 | rButton.apply { 221 | setText(textId) 222 | this.isEnabled = enable 223 | setOnClickListener { 224 | callBacks?.invoke(it) 225 | finallyCallBacks?.invoke(it) 226 | } 227 | visibility = View.VISIBLE 228 | } 229 | } 230 | 231 | fun getRButton(): TextView = rButton 232 | 233 | fun getLButton(): TextView = lButton 234 | 235 | override fun show() { 236 | build() 237 | window!!.setWindowAnimations(R.style.DialogAnim) 238 | if (rButton.visibility == View.VISIBLE && lButton.visibility == View.VISIBLE) { 239 | if (isRtl(context)) { 240 | (rButton.layoutParams as LinearLayout.LayoutParams).setMargins(dp2px(context, 24f), 0, dp2px(context, 5f), 0) 241 | (lButton.layoutParams as LinearLayout.LayoutParams).setMargins(dp2px(context, 5f), 0, dp2px(context, 24f), 0) 242 | } else { 243 | (rButton.layoutParams as LinearLayout.LayoutParams).setMargins(dp2px(context, 5f), 0, dp2px(context, 24f), 0) 244 | (lButton.layoutParams as LinearLayout.LayoutParams).setMargins(dp2px(context, 24f), 0, dp2px(context, 5f), 0) 245 | } 246 | } 247 | super.show() 248 | val layoutParams = window!!.attributes 249 | layoutParams.dimAmount = 0.3F 250 | if (newStyle) { 251 | val resources = context.resources 252 | val dm: DisplayMetrics = resources.displayMetrics 253 | val width = dm.widthPixels 254 | layoutParams.width = (width * 0.94f).roundToInt() 255 | layoutParams.y = (width * 0.03f).roundToInt() 256 | } else { 257 | layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT 258 | } 259 | layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT 260 | window!!.attributes = layoutParams 261 | } 262 | 263 | fun setMessage(textId: Int, isCenter: Boolean = true) { 264 | if (isCenter) { 265 | message.gravity = Gravity.CENTER 266 | } else { 267 | message.gravity = Gravity.START 268 | } 269 | message.apply { 270 | setText(textId) 271 | visibility = View.VISIBLE 272 | } 273 | } 274 | 275 | fun setMessage(text: CharSequence, isCenter: Boolean = true) { 276 | if (isCenter) { 277 | message.gravity = Gravity.CENTER 278 | } else { 279 | message.gravity = Gravity.START 280 | } 281 | message.apply { 282 | this.text = text 283 | visibility = View.VISIBLE 284 | } 285 | } 286 | 287 | fun setEditText(text: String, hint: String, isSingleLine: Boolean = true, config: ((EditText) -> Unit)? = null, editCallBacks: ((String) -> Unit)? = null) { 288 | editText.apply { 289 | setText(text.toCharArray(), 0, text.length) 290 | this.hint = hint 291 | this.isSingleLine = isSingleLine 292 | this.maxLines = 5 293 | visibility = View.VISIBLE 294 | editCallBacks?.let { 295 | addTextChangedListener(object : TextWatcher { 296 | override fun afterTextChanged(var1: Editable?) { 297 | it(var1.toString()) 298 | } 299 | 300 | override fun beforeTextChanged(var1: CharSequence?, var2: Int, var3: Int, var4: Int) {} 301 | override fun onTextChanged(var1: CharSequence?, var2: Int, var3: Int, var4: Int) {} 302 | }) 303 | } 304 | config?.invoke(this) 305 | } 306 | } 307 | 308 | fun finally(callBacks: (View) -> Unit) { 309 | finallyCallBacks = callBacks 310 | } 311 | 312 | fun getEditText(): String = editText.text.toString() 313 | } -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/dialog/NewDialog.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * BlockMIUI 3 | * Copyright (C) 2022 fkj@fkj233.cn 4 | * https://github.com/577fkj/BlockMIUI 5 | * 6 | * This software is free opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Lesser General Public License v2.1 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version and our eula as published 10 | * by 577fkj. 11 | * 12 | * This software is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * GNU Lesser General Public License v2.1 for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License v2.1 18 | * and eula along with this software. If not, see 19 | * 20 | * . 21 | */ 22 | 23 | @file:Suppress("FunctionName") 24 | 25 | package cn.fkj233.ui.dialog 26 | 27 | import android.app.Dialog 28 | import android.content.Context 29 | import android.graphics.Typeface 30 | import android.graphics.drawable.GradientDrawable 31 | import android.os.Build 32 | import android.text.Editable 33 | import android.text.TextWatcher 34 | import android.util.DisplayMetrics 35 | import android.util.TypedValue 36 | import android.view.Gravity 37 | import android.view.View 38 | import android.view.WindowManager 39 | import android.widget.Button 40 | import android.widget.LinearLayout 41 | import android.widget.RelativeLayout 42 | import android.widget.TextView 43 | import cn.fkj233.ui.R 44 | import cn.fkj233.ui.activity.dp2px 45 | import cn.fkj233.ui.activity.view.MIUIEditText 46 | import kotlin.math.roundToInt 47 | 48 | class NewDialog(context: Context, private val newStyle: Boolean = true, val build: NewDialog.() -> Unit) : Dialog(context, R.style.CustomDialog) { 49 | 50 | private var finallyCallBacks: ((View) -> Unit)? = null 51 | 52 | private val title by lazy { 53 | TextView(context).also { textView -> 54 | textView.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { 55 | it.setMargins(0, dp2px(context, 20f), 0, dp2px(context, 20f)) 56 | } 57 | textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 19f) 58 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 59 | textView.paint.typeface = Typeface.create(null, 500, false) 60 | } 61 | textView.setTextColor(context.getColor(R.color.whiteText)) 62 | textView.gravity = Gravity.CENTER 63 | textView.setPadding(0, dp2px(context, 10f), 0, 0) 64 | } 65 | } 66 | 67 | private val message by lazy { 68 | TextView(context).also { textView -> 69 | textView.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { 70 | it.setMargins(dp2px(context, 20f), 0, dp2px(context, 20f), dp2px(context, 5f)) 71 | } 72 | textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 17f) 73 | textView.setTextColor(context.getColor(R.color.whiteText)) 74 | textView.gravity = Gravity.CENTER 75 | textView.visibility = View.GONE 76 | textView.setPadding(dp2px(context, 10f), 0, dp2px(context, 10f), 0) 77 | } 78 | } 79 | 80 | private val editText by lazy { MIUIEditText(context) } 81 | 82 | 83 | private val view by lazy { 84 | LinearLayout(context).also { linearLayout -> 85 | linearLayout.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT) 86 | linearLayout.orientation = LinearLayout.VERTICAL 87 | linearLayout.addView(message) 88 | linearLayout.addView(editText) 89 | } 90 | } 91 | 92 | private var bView: LinearLayout 93 | 94 | private val root = RelativeLayout(context).also { viewRoot -> 95 | viewRoot.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT) 96 | viewRoot.addView(LinearLayout(context).also { viewLinearLayout -> 97 | viewLinearLayout.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT) 98 | viewLinearLayout.orientation = LinearLayout.VERTICAL 99 | viewLinearLayout.addView(title) 100 | viewLinearLayout.addView(view) 101 | viewLinearLayout.addView(LinearLayout(context).also { linearLayout -> 102 | linearLayout.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { 103 | it.gravity = Gravity.CENTER_HORIZONTAL 104 | } 105 | linearLayout.orientation = LinearLayout.VERTICAL 106 | linearLayout.setPadding(0, 0, 0, dp2px(context, 35f)) 107 | bView = linearLayout 108 | }) 109 | }) 110 | } 111 | 112 | fun Button(text: CharSequence?, enable: Boolean = true, cancelStyle: Boolean = false) { 113 | Button(text, enable, cancelStyle, null) 114 | } 115 | 116 | fun Button(text: CharSequence?, enable: Boolean = true, cancelStyle: Boolean = false, callBacks: ((View) -> Unit)?) { 117 | bView.addView(Button(context).also { buttonView -> 118 | buttonView.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, dp2px(context, 48f), 1f).also { 119 | it.setMargins(dp2px(context, 30f), dp2px(context, 10f), dp2px(context, 30f), 0) 120 | it.gravity = Gravity.CENTER 121 | } 122 | buttonView.setPadding(0, 0, 0, 0) 123 | buttonView.typeface = Typeface.defaultFromStyle(Typeface.BOLD) 124 | buttonView.setTextColor(context.getColor(if (cancelStyle) R.color.LButtonText else R.color.RButtonText)) 125 | if (!enable) { 126 | buttonView.setTextColor(context.getColor(R.color.disable_button_text)) 127 | } 128 | buttonView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 17.5f) 129 | buttonView.text = text 130 | buttonView.isEnabled = enable 131 | buttonView.stateListAnimator = null 132 | buttonView.background = context.getDrawable(if (cancelStyle) R.drawable.l_button_background else R.drawable.r_button_background) 133 | buttonView.setOnClickListener { 134 | callBacks?.invoke(it) 135 | finallyCallBacks?.invoke(it) 136 | } 137 | }) 138 | } 139 | 140 | init { 141 | window?.setGravity(Gravity.BOTTOM) 142 | setContentView(root) 143 | window?.setBackgroundDrawable(GradientDrawable().apply { 144 | if (newStyle) { 145 | cornerRadius = dp2px(context, 30f).toFloat() 146 | } else { 147 | val dp30 = dp2px(context, 30f).toFloat() 148 | cornerRadii = floatArrayOf(dp30, dp30, dp30, dp30, 0f, 0f, 0f, 0f) 149 | } 150 | setColor(context.getColor(R.color.dialog_background)) 151 | }) 152 | } 153 | 154 | fun addView(mView: View) { 155 | view.addView(mView) 156 | } 157 | 158 | override fun setTitle(title: CharSequence?) { 159 | this.title.text = title 160 | } 161 | 162 | override fun setTitle(titleId: Int) { 163 | this.title.setText(titleId) 164 | } 165 | 166 | override fun show() { 167 | build() 168 | window!!.setWindowAnimations(R.style.DialogAnim) 169 | super.show() 170 | val layoutParams = window!!.attributes 171 | layoutParams.dimAmount = 0.5F 172 | if (newStyle) { 173 | val resources = context.resources 174 | val dm: DisplayMetrics = resources.displayMetrics 175 | val width = dm.widthPixels 176 | layoutParams.width = (width * 0.92f).roundToInt() 177 | layoutParams.y = (width * 0.045f).roundToInt() 178 | } else { 179 | layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT 180 | } 181 | layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT 182 | window!!.attributes = layoutParams 183 | } 184 | 185 | fun setMessage(textId: Int) { 186 | message.apply { 187 | setText(textId) 188 | visibility = View.VISIBLE 189 | } 190 | } 191 | 192 | fun setMessage(text: CharSequence?, isCenter: Boolean = true) { 193 | if (isCenter) { 194 | message.gravity = Gravity.CENTER 195 | } else { 196 | message.gravity = Gravity.START 197 | } 198 | message.apply { 199 | this.text = text 200 | visibility = View.VISIBLE 201 | } 202 | } 203 | 204 | fun setEditText(text: String, hint: String, isSingleLine: Boolean = true, editCallBacks: ((String) -> Unit)? = null) { 205 | editText.apply { 206 | setText(text.toCharArray(), 0, text.length) 207 | this.hint = hint 208 | this.isSingleLine = isSingleLine 209 | this.maxLines = 5 210 | visibility = View.VISIBLE 211 | editCallBacks?.let { 212 | addTextChangedListener(object : TextWatcher { 213 | override fun afterTextChanged(var1: Editable?) { 214 | it(var1.toString()) 215 | } 216 | 217 | override fun beforeTextChanged(var1: CharSequence?, var2: Int, var3: Int, var4: Int) {} 218 | override fun onTextChanged(var1: CharSequence?, var2: Int, var3: Int, var4: Int) {} 219 | }) 220 | } 221 | } 222 | } 223 | 224 | fun Finally(callBacks: (View) -> Unit) { 225 | finallyCallBacks = callBacks 226 | } 227 | 228 | fun getEditText(): String = editText.text.toString() 229 | } 230 | -------------------------------------------------------------------------------- /src/main/kotlin/cn/fkj233/ui/switch/MIUISwitch.kt: -------------------------------------------------------------------------------- 1 | package cn.fkj233.ui.switch 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Context 5 | import android.widget.Switch 6 | import cn.fkj233.ui.R 7 | import cn.fkj233.ui.activity.dp2px 8 | import java.lang.reflect.Field 9 | 10 | class MIUISwitch(context: Context) : Switch(context) { 11 | init { 12 | background = null 13 | setThumbResource(R.drawable.switch_thumb) 14 | setTrackResource(R.drawable.switch_track) 15 | showText = false 16 | } 17 | 18 | @SuppressLint("DiscouragedPrivateApi", "DrawAllocation") 19 | override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { 20 | super.onMeasure(widthMeasureSpec, heightMeasureSpec) 21 | val mSwitchWidth: Field = Switch::class.java.getDeclaredField("mSwitchWidth") 22 | mSwitchWidth.isAccessible = true 23 | mSwitchWidth.setInt(this, dp2px(context, 53f)) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/res/animator/dialog_enter.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 11 | -------------------------------------------------------------------------------- /src/main/res/animator/dialog_exit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 11 | -------------------------------------------------------------------------------- /src/main/res/animator/slide_left_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 10 | 16 | -------------------------------------------------------------------------------- /src/main/res/animator/slide_left_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 10 | 16 | -------------------------------------------------------------------------------- /src/main/res/animator/slide_right_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 10 | 16 | -------------------------------------------------------------------------------- /src/main/res/animator/slide_right_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 10 | 16 | -------------------------------------------------------------------------------- /src/main/res/drawable/abc_ic_ab_back_material.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /src/main/res/drawable/abc_ic_menu_overflow_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 11 | -------------------------------------------------------------------------------- /src/main/res/drawable/editview_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/main/res/drawable/ic_click_check.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/res/drawable/ic_loading.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Block-Network/blockmiui/33a54b10d1a049d7e1237cb909b0f5d58fcd6b22/src/main/res/drawable/ic_loading.webp -------------------------------------------------------------------------------- /src/main/res/drawable/ic_main_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/main/res/drawable/ic_main_down_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/main/res/drawable/ic_popup_select.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/main/res/drawable/ic_right_arrow.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | -------------------------------------------------------------------------------- /src/main/res/drawable/ic_up_down.xml: -------------------------------------------------------------------------------- 1 | 7 | 11 | -------------------------------------------------------------------------------- /src/main/res/drawable/l_button_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/res/drawable/l_button_background_disable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/res/drawable/l_button_background_no_pressed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/res/drawable/l_button_background_pressed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/res/drawable/loading_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/res/drawable/miui_rounded_corners_pop.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/res/drawable/r_button_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/res/drawable/r_button_background_disable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/res/drawable/r_button_background_no_pressed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/res/drawable/r_button_background_pressed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/res/drawable/seekbar_progress_drawable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/main/res/drawable/switch_thumb.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 11 | -------------------------------------------------------------------------------- /src/main/res/drawable/switch_track.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #000000 4 | #333333 5 | #FFFFFF 6 | #ACACAC 7 | #333333 8 | #292929 9 | #FFFFFF 10 | #5C5C5C 11 | #2D2D2D 12 | #0374A7 13 | #FFFFFF 14 | #353535 15 | #222222 16 | #c3c3c3 17 | #373737 18 | #353535 19 | #0073dd 20 | #2688e2 21 | #343434 22 | #242424 23 | #454545 24 | #1F2F4C 25 | #404E67 26 | #666666 27 | #242424 28 | #0073dd 29 | -------------------------------------------------------------------------------- /src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 13 | -------------------------------------------------------------------------------- /src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFF 4 | #FFFFFF 5 | #000000 6 | #656565 7 | #e6e6e6 8 | #D3D3D3 9 | #000000 10 | #5C5C5C 11 | #E6E6E6 12 | #0374A7 13 | #FFFFFF 14 | #000000 15 | #FFFFFF 16 | #F0F0F0 17 | #0c84FF 18 | #0d7AEC 19 | #303030 20 | #F0F0F0 21 | #f0f0f0 22 | #dddddd 23 | #f4f4f4 24 | #FFFFFF 25 | #EBEBEB 26 | #E6F2FF 27 | #D4DFEB 28 | #1385FF 29 | #999999 30 | #0d7AEC 31 | #FFFFFF 32 | #0d84ff 33 | -------------------------------------------------------------------------------- /src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 18 | 19 | 31 | --------------------------------------------------------------------------------