mirror of
https://github.com/fankes/TSBattery.git
synced 2025-09-04 17:55:30 +08:00
Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
8b657a8aab
|
|||
f0ab310620
|
|||
711e0ac730
|
|||
b1e83a1073
|
|||
b562337995
|
|||
6b990c50f8
|
|||
|
bae91688b1 | ||
|
a59d260321 | ||
|
e850a73c49 | ||
|
1dc725c294 | ||
ce89da3ee8
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
[](https://github.com/fankes/TSBattery)
|
[](https://github.com/fankes/TSBattery)
|
||||||
[](https://github.com/fankes/TSBattery/blob/master/LICENSE)
|
[](https://github.com/fankes/TSBattery/blob/master/LICENSE)
|
||||||
[](https://github.com/fankes/TSBattery/releases)
|
[](https://github.com/fankes/TSBattery/releases)
|
||||||
[](https://github.com/fankes/TSBattery/releases)
|
[](https://github.com/fankes/TSBattery/releases)
|
||||||
[](https://github.com/Xposed-Modules-Repo/com.fankes.tsbattery/releases)
|
[](https://github.com/Xposed-Modules-Repo/com.fankes.tsbattery/releases)
|
||||||
[](https://t.me/XiaofangInternet)
|
[](https://t.me/XiaofangInternet)
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'com.android.application'
|
id 'com.android.application'
|
||||||
id 'kotlin-android'
|
id 'kotlin-android'
|
||||||
id 'com.google.devtools.ksp' version '1.7.0-1.0.6'
|
id 'com.google.devtools.ksp' version '1.7.10-1.0.6'
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
@@ -60,6 +60,7 @@ dependencies {
|
|||||||
compileOnly 'de.robv.android.xposed:api:82'
|
compileOnly 'de.robv.android.xposed:api:82'
|
||||||
implementation 'com.highcapable.yukihookapi:api:1.0.92'
|
implementation 'com.highcapable.yukihookapi:api:1.0.92'
|
||||||
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.92'
|
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.92'
|
||||||
|
implementation 'com.github.duanhong169:drawabletoolbox:1.0.7'
|
||||||
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.7'
|
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.7'
|
||||||
implementation 'androidx.core:core-ktx:1.8.0'
|
implementation 'androidx.core:core-ktx:1.8.0'
|
||||||
implementation 'androidx.appcompat:appcompat:1.4.2'
|
implementation 'androidx.appcompat:appcompat:1.4.2'
|
||||||
|
@@ -107,24 +107,78 @@ class HookEntry : IYukiHookXposedInit {
|
|||||||
*/
|
*/
|
||||||
private fun PackageParam.hookQQBaseChatPie(version: String) {
|
private fun PackageParam.hookQQBaseChatPie(version: String) {
|
||||||
when (version) {
|
when (version) {
|
||||||
"8.2.11" -> {
|
"8.0.0" -> {
|
||||||
|
interceptBaseChatPie(methodName = "bq")
|
||||||
|
interceptBaseChatPie(methodName = "aL")
|
||||||
|
}
|
||||||
|
"8.0.5", "8.0.7" -> {
|
||||||
|
interceptBaseChatPie(methodName = "bw")
|
||||||
|
interceptBaseChatPie(methodName = "aQ")
|
||||||
|
}
|
||||||
|
"8.1.0", "8.1.3" -> {
|
||||||
|
interceptBaseChatPie(methodName = "bE")
|
||||||
|
interceptBaseChatPie(methodName = "aT")
|
||||||
|
}
|
||||||
|
"8.1.5" -> {
|
||||||
|
interceptBaseChatPie(methodName = "bF")
|
||||||
|
interceptBaseChatPie(methodName = "aT")
|
||||||
|
}
|
||||||
|
"8.1.8", "8.2.0", "8.2.6" -> {
|
||||||
|
interceptBaseChatPie(methodName = "bC")
|
||||||
|
interceptBaseChatPie(methodName = "aT")
|
||||||
|
}
|
||||||
|
"8.2.7", "8.2.8", "8.2.11", "8.3.0" -> {
|
||||||
interceptBaseChatPie(methodName = "bE")
|
interceptBaseChatPie(methodName = "bE")
|
||||||
interceptBaseChatPie(methodName = "aV")
|
interceptBaseChatPie(methodName = "aV")
|
||||||
}
|
}
|
||||||
"8.8.17" -> {
|
"8.3.5" -> {
|
||||||
|
interceptBaseChatPie(methodName = "bR")
|
||||||
|
interceptBaseChatPie(methodName = "aX")
|
||||||
|
}
|
||||||
|
"8.3.6" -> {
|
||||||
|
interceptBaseChatPie(methodName = "cp")
|
||||||
|
interceptBaseChatPie(methodName = "aX")
|
||||||
|
}
|
||||||
|
"8.3.9" -> {
|
||||||
|
interceptBaseChatPie(methodName = "cj")
|
||||||
|
interceptBaseChatPie(methodName = "aT")
|
||||||
|
}
|
||||||
|
"8.4.1", "8.4.5" -> {
|
||||||
|
interceptBaseChatPie(methodName = "ck")
|
||||||
|
interceptBaseChatPie(methodName = "aT")
|
||||||
|
}
|
||||||
|
"8.4.8", "8.4.10", "8.4.17", "8.4.18", "8.5.0" -> {
|
||||||
|
interceptBaseChatPie(methodName = "remainScreenOn")
|
||||||
|
interceptBaseChatPie(methodName = "cancelRemainScreenOn")
|
||||||
|
}
|
||||||
|
"8.5.5" -> {
|
||||||
|
interceptBaseChatPie(methodName = "bT")
|
||||||
|
interceptBaseChatPie(methodName = "aN")
|
||||||
|
}
|
||||||
|
"8.6.0", "8.6.5", "8.7.0", "8.7.5", "8.7.8", "8.8.0", "8.8.3", "8.8.5" -> {
|
||||||
|
interceptBaseChatPie(methodName = "ag")
|
||||||
|
interceptBaseChatPie(methodName = "ah")
|
||||||
|
}
|
||||||
|
"8.8.11", "8.8.12" -> {
|
||||||
|
interceptBaseChatPie(methodName = "bc")
|
||||||
|
interceptBaseChatPie(methodName = "bd")
|
||||||
|
}
|
||||||
|
"8.8.17", "8.8.20" -> {
|
||||||
interceptBaseChatPie(methodName = "bd")
|
interceptBaseChatPie(methodName = "bd")
|
||||||
interceptBaseChatPie(methodName = "be")
|
interceptBaseChatPie(methodName = "be")
|
||||||
}
|
}
|
||||||
"8.8.23" -> {
|
"8.8.23", "8.8.28" -> {
|
||||||
interceptBaseChatPie(methodName = "bf")
|
interceptBaseChatPie(methodName = "bf")
|
||||||
interceptBaseChatPie(methodName = "bg")
|
interceptBaseChatPie(methodName = "bg")
|
||||||
}
|
}
|
||||||
/** 8.8.35 贡献者:StarWishsama */
|
"8.8.33" -> {
|
||||||
|
interceptBaseChatPie(methodName = "bg")
|
||||||
|
interceptBaseChatPie(methodName = "bh")
|
||||||
|
}
|
||||||
"8.8.35", "8.8.38" -> {
|
"8.8.35", "8.8.38" -> {
|
||||||
interceptBaseChatPie(methodName = "bi")
|
interceptBaseChatPie(methodName = "bi")
|
||||||
interceptBaseChatPie(methodName = "bj")
|
interceptBaseChatPie(methodName = "bj")
|
||||||
}
|
}
|
||||||
/** 贡献者:JiZhi-Error */
|
|
||||||
"8.8.50" -> {
|
"8.8.50" -> {
|
||||||
interceptBaseChatPie(methodName = "bj")
|
interceptBaseChatPie(methodName = "bj")
|
||||||
interceptBaseChatPie(methodName = "bk")
|
interceptBaseChatPie(methodName = "bk")
|
||||||
@@ -145,8 +199,7 @@ class HookEntry : IYukiHookXposedInit {
|
|||||||
interceptBaseChatPie(methodName = "M3")
|
interceptBaseChatPie(methodName = "M3")
|
||||||
interceptBaseChatPie(methodName = "S")
|
interceptBaseChatPie(methodName = "S")
|
||||||
}
|
}
|
||||||
/** 8.9.0 贡献者:StarWishsama */
|
"8.9.0", "8.9.1", "8.9.2" -> {
|
||||||
"8.9.0", "8.9.1" -> {
|
|
||||||
interceptBaseChatPie(methodName = "N3")
|
interceptBaseChatPie(methodName = "N3")
|
||||||
interceptBaseChatPie(methodName = "S")
|
interceptBaseChatPie(methodName = "S")
|
||||||
}
|
}
|
||||||
|
@@ -47,11 +47,14 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
|
|
||||||
private const val moduleVersion = BuildConfig.VERSION_NAME
|
private const val moduleVersion = BuildConfig.VERSION_NAME
|
||||||
private val qqSupportVersions = arrayOf(
|
private val qqSupportVersions = arrayOf(
|
||||||
"8.2.11(Play)", "8.8.17", "8.8.23",
|
"8.0.0", "8.0.5", "8.0.7", "8.1.0", "8.1.3", "8.1.5", "8.1.8",
|
||||||
"8.8.35", "8.8.38", "8.8.50", "8.8.55",
|
"8.2.0", "8.2.6", "8.2.7", "8.2.8", "8.2.11", "8.3.0", "8.3.5",
|
||||||
"8.8.68", "8.8.80", "8.8.83", "8.8.85",
|
"8.3.6", "8.3.9", "8.4.1", "8.4.5", "8.4.8", "8.4.10", "8.4.17",
|
||||||
"8.8.88", "8.8.90", "8.8.93", "8.8.95",
|
"8.4.18", "8.5.0", "8.5.5", "8.6.0", "8.6.5", "8.7.0", "8.7.5",
|
||||||
"8.8.98", "8.9.0", "8.9.1"
|
"8.7.8", "8.8.0", "8.8.3", "8.8.5", "8.8.11", "8.8.12", "8.8.17",
|
||||||
|
"8.8.20", "8.8.23", "8.8.28", "8.8.33", "8.8.35", "8.8.38", "8.8.50",
|
||||||
|
"8.8.55", "8.8.68", "8.8.80", "8.8.83", "8.8.85", "8.8.88", "8.8.90",
|
||||||
|
"8.8.93", "8.8.95", "8.8.98", "8.9.0", "8.9.1", "8.9.2"
|
||||||
)
|
)
|
||||||
private val qqSupportVersion by lazy {
|
private val qqSupportVersion by lazy {
|
||||||
if (qqSupportVersions.isNotEmpty()) {
|
if (qqSupportVersions.isNotEmpty()) {
|
||||||
|
@@ -29,9 +29,9 @@ import android.graphics.Color
|
|||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import androidx.appcompat.widget.SwitchCompat
|
import androidx.appcompat.widget.SwitchCompat
|
||||||
import com.fankes.tsbattery.utils.drawable.drawabletoolbox.DrawableBuilder
|
|
||||||
import com.fankes.tsbattery.utils.factory.dp
|
import com.fankes.tsbattery.utils.factory.dp
|
||||||
import com.fankes.tsbattery.utils.factory.isSystemInDarkMode
|
import com.fankes.tsbattery.utils.factory.isSystemInDarkMode
|
||||||
|
import top.defaults.drawabletoolbox.DrawableBuilder
|
||||||
|
|
||||||
class MaterialSwitch(context: Context, attrs: AttributeSet?) : SwitchCompat(context, attrs) {
|
class MaterialSwitch(context: Context, attrs: AttributeSet?) : SwitchCompat(context, attrs) {
|
||||||
|
|
||||||
|
@@ -1,292 +0,0 @@
|
|||||||
/*
|
|
||||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
|
||||||
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
|
|
||||||
* https://github.com/fankes/TSBattery
|
|
||||||
*
|
|
||||||
* This software is non-free but opensource software: you can redistribute it
|
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
|
||||||
* as published by the Free Software Foundation; either
|
|
||||||
* version 3 of the License, or any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* and eula along with this software. If not, see
|
|
||||||
* <https://www.gnu.org/licenses/>
|
|
||||||
*
|
|
||||||
* This file is Created by fankes on 2022/1/8.
|
|
||||||
*/
|
|
||||||
@file:Suppress("SameParameterValue")
|
|
||||||
|
|
||||||
package com.fankes.tsbattery.utils.drawable.drawabletoolbox
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.graphics.drawable.GradientDrawable
|
|
||||||
import android.graphics.drawable.RippleDrawable
|
|
||||||
import android.graphics.drawable.RotateDrawable
|
|
||||||
import android.os.Build
|
|
||||||
import java.lang.reflect.Field
|
|
||||||
import java.lang.reflect.Method
|
|
||||||
|
|
||||||
private val gradientState = resolveGradientState()
|
|
||||||
|
|
||||||
private fun resolveGradientState(): Class<*> {
|
|
||||||
val classes = GradientDrawable::class.java.declaredClasses
|
|
||||||
for (singleClass in classes) {
|
|
||||||
if (singleClass.simpleName == "GradientState") return singleClass
|
|
||||||
}
|
|
||||||
throw RuntimeException("GradientState could not be found in thisAny GradientDrawable implementation")
|
|
||||||
}
|
|
||||||
|
|
||||||
private val rotateState = resolveRotateState()
|
|
||||||
|
|
||||||
private fun resolveRotateState(): Class<*> {
|
|
||||||
val classes = RotateDrawable::class.java.declaredClasses
|
|
||||||
for (singleClass in classes) {
|
|
||||||
if (singleClass.simpleName == "RotateState") return singleClass
|
|
||||||
}
|
|
||||||
throw RuntimeException("RotateState could not be found in thisAny RotateDrawable implementation")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(SecurityException::class, NoSuchFieldException::class)
|
|
||||||
private fun resolveField(source: Class<*>, fieldName: String): Field {
|
|
||||||
val field = source.getDeclaredField(fieldName)
|
|
||||||
field.isAccessible = true
|
|
||||||
return field
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(SecurityException::class, NoSuchMethodException::class)
|
|
||||||
private fun resolveMethod(
|
|
||||||
source: Class<*>,
|
|
||||||
methodName: String,
|
|
||||||
vararg parameterTypes: Class<*>
|
|
||||||
): Method {
|
|
||||||
val method = source.getDeclaredMethod(methodName, *parameterTypes)
|
|
||||||
method.isAccessible = true
|
|
||||||
return method
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setInnerRadius(drawable: GradientDrawable, value: Int) {
|
|
||||||
try {
|
|
||||||
val innerRadius = resolveField(gradientState, "mInnerRadius")
|
|
||||||
innerRadius.setInt(drawable.constantState, value)
|
|
||||||
} catch (e: NoSuchFieldException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: IllegalAccessException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setInnerRadiusRatio(drawable: GradientDrawable, value: Float) {
|
|
||||||
try {
|
|
||||||
val innerRadius = resolveField(gradientState, "mInnerRadiusRatio")
|
|
||||||
innerRadius.setFloat(drawable.constantState, value)
|
|
||||||
} catch (e: NoSuchFieldException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: IllegalAccessException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setThickness(drawable: GradientDrawable, value: Int) {
|
|
||||||
try {
|
|
||||||
val innerRadius = resolveField(gradientState, "mThickness")
|
|
||||||
innerRadius.setInt(drawable.constantState, value)
|
|
||||||
} catch (e: NoSuchFieldException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: IllegalAccessException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setThicknessRatio(drawable: GradientDrawable, value: Float) {
|
|
||||||
try {
|
|
||||||
val innerRadius = resolveField(gradientState, "mThicknessRatio")
|
|
||||||
innerRadius.setFloat(drawable.constantState, value)
|
|
||||||
} catch (e: NoSuchFieldException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: IllegalAccessException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setUseLevelForShape(drawable: GradientDrawable, value: Boolean) {
|
|
||||||
try {
|
|
||||||
val useLevelForShape = resolveField(gradientState, "mUseLevelForShape")
|
|
||||||
useLevelForShape.setBoolean(drawable.constantState, value)
|
|
||||||
} catch (e: NoSuchFieldException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: IllegalAccessException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("ObsoleteSdkInt")
|
|
||||||
fun setOrientation(drawable: GradientDrawable, value: GradientDrawable.Orientation) {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
|
||||||
drawable.orientation = value
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
val orientation = resolveField(gradientState, "mOrientation")
|
|
||||||
orientation.set(drawable.constantState, value)
|
|
||||||
val rectIdDirty = resolveField(GradientDrawable::class.java, "mRectIsDirty")
|
|
||||||
rectIdDirty.setBoolean(drawable, true)
|
|
||||||
drawable.invalidateSelf()
|
|
||||||
} catch (e: NoSuchFieldException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: IllegalAccessException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("ObsoleteSdkInt")
|
|
||||||
fun setColors(drawable: GradientDrawable, value: IntArray) {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
|
||||||
drawable.colors = value
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
val colors = resolveField(gradientState, "mColors")
|
|
||||||
colors.set(drawable.constantState, value)
|
|
||||||
drawable.invalidateSelf()
|
|
||||||
} catch (e: NoSuchFieldException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: IllegalAccessException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setGradientRadiusType(drawable: GradientDrawable, value: Int) {
|
|
||||||
try {
|
|
||||||
val type = resolveField(gradientState, "mGradientRadiusType")
|
|
||||||
type.setInt(drawable.constantState, value)
|
|
||||||
} catch (e: NoSuchFieldException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: IllegalAccessException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setGradientRadius(drawable: GradientDrawable, value: Float) {
|
|
||||||
try {
|
|
||||||
val gradientRadius = resolveField(gradientState, "mGradientRadius")
|
|
||||||
gradientRadius.setFloat(drawable.constantState, value)
|
|
||||||
} catch (e: NoSuchFieldException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: IllegalAccessException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setStrokeColor(drawable: GradientDrawable, value: Int) {
|
|
||||||
try {
|
|
||||||
val type = resolveField(gradientState, "mStrokeColor")
|
|
||||||
type.setInt(drawable.constantState, value)
|
|
||||||
} catch (e: NoSuchFieldException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: IllegalAccessException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setDrawable(rotateDrawable: RotateDrawable, drawable: Drawable) {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
rotateDrawable.drawable = drawable
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
val drawableField = resolveField(rotateState, "mDrawable")
|
|
||||||
val stateField = resolveField(RotateDrawable::class.java, "mState")
|
|
||||||
drawableField.set(stateField.get(rotateDrawable), drawable)
|
|
||||||
drawable.callback = rotateDrawable
|
|
||||||
} catch (e: NoSuchFieldException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: IllegalAccessException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setPivotX(rotateDrawable: RotateDrawable, value: Float) {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
rotateDrawable.pivotX = value
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
val pivotXField = resolveField(rotateState, "mPivotX")
|
|
||||||
pivotXField.setFloat(rotateDrawable.constantState, value)
|
|
||||||
val pivotXRelField = resolveField(rotateState, "mPivotXRel")
|
|
||||||
pivotXRelField.setBoolean(rotateDrawable.constantState, true)
|
|
||||||
} catch (e: NoSuchFieldException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: IllegalAccessException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setPivotY(rotateDrawable: RotateDrawable, value: Float) {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
rotateDrawable.pivotY = value
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
val pivotYField = resolveField(rotateState, "mPivotY")
|
|
||||||
pivotYField.setFloat(rotateDrawable.constantState, value)
|
|
||||||
val pivotYRelField = resolveField(rotateState, "mPivotYRel")
|
|
||||||
pivotYRelField.setBoolean(rotateDrawable.constantState, true)
|
|
||||||
} catch (e: NoSuchFieldException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: IllegalAccessException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setFromDegrees(rotateDrawable: RotateDrawable, value: Float) {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
rotateDrawable.fromDegrees = value
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
val fromDegreesField = resolveField(rotateState, "mFromDegrees")
|
|
||||||
fromDegreesField.setFloat(rotateDrawable.constantState, value)
|
|
||||||
} catch (e: NoSuchFieldException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: IllegalAccessException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setToDegrees(rotateDrawable: RotateDrawable, value: Float) {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
rotateDrawable.toDegrees = value
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
val toDegreesField = resolveField(rotateState, "mToDegrees")
|
|
||||||
toDegreesField.setFloat(rotateDrawable.constantState, value)
|
|
||||||
} catch (e: NoSuchFieldException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: IllegalAccessException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setRadius(rippleDrawable: RippleDrawable, value: Int) {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
||||||
rippleDrawable.radius = value
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
val setRadiusMethod =
|
|
||||||
resolveMethod(RippleDrawable::class.java, "setMaxRadius", Int::class.java)
|
|
||||||
setRadiusMethod.invoke(rippleDrawable, value)
|
|
||||||
} catch (e: NoSuchFieldException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: IllegalAccessException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
|
||||||
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
|
|
||||||
* https://github.com/fankes/TSBattery
|
|
||||||
*
|
|
||||||
* This software is non-free but opensource software: you can redistribute it
|
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
|
||||||
* as published by the Free Software Foundation; either
|
|
||||||
* version 3 of the License, or any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* and eula along with this software. If not, see
|
|
||||||
* <https://www.gnu.org/licenses/>
|
|
||||||
*
|
|
||||||
* This file is Created by fankes on 2022/1/8.
|
|
||||||
*/
|
|
||||||
package com.fankes.tsbattery.utils.drawable.drawabletoolbox
|
|
||||||
|
|
||||||
class Constants {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val DEFAULT_COLOR = 0xFFBA68C8.toInt()
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,489 +0,0 @@
|
|||||||
/*
|
|
||||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
|
||||||
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
|
|
||||||
* https://github.com/fankes/TSBattery
|
|
||||||
*
|
|
||||||
* This software is non-free but opensource software: you can redistribute it
|
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
|
||||||
* as published by the Free Software Foundation; either
|
|
||||||
* version 3 of the License, or any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* and eula along with this software. If not, see
|
|
||||||
* <https://www.gnu.org/licenses/>
|
|
||||||
*
|
|
||||||
* This file is Created by fankes on 2022/1/8.
|
|
||||||
*/
|
|
||||||
@file:Suppress("unused", "MemberVisibilityCanBePrivate")
|
|
||||||
|
|
||||||
package com.fankes.tsbattery.utils.drawable.drawabletoolbox
|
|
||||||
|
|
||||||
import android.content.res.ColorStateList
|
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.graphics.drawable.GradientDrawable
|
|
||||||
import android.util.StateSet
|
|
||||||
import java.util.*
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
|
||||||
|
|
||||||
class DrawableBuilder {
|
|
||||||
|
|
||||||
private var properties = DrawableProperties()
|
|
||||||
private var order: AtomicInteger = AtomicInteger(1)
|
|
||||||
private var transformsMap = TreeMap<Int, (Drawable) -> Drawable>()
|
|
||||||
private var baseDrawable: Drawable? = null
|
|
||||||
|
|
||||||
fun batch(properties: DrawableProperties) = apply { this.properties = properties.copy() }
|
|
||||||
fun baseDrawable(drawable: Drawable) = apply { baseDrawable = drawable }
|
|
||||||
|
|
||||||
// <shape>
|
|
||||||
fun shape(shape: Int) = apply { properties.shape = shape }
|
|
||||||
|
|
||||||
fun rectangle() = apply { shape(GradientDrawable.RECTANGLE) }
|
|
||||||
fun oval() = apply { shape(GradientDrawable.OVAL) }
|
|
||||||
fun line() = apply { shape(GradientDrawable.LINE) }
|
|
||||||
fun ring() = apply { shape(GradientDrawable.RING) }
|
|
||||||
fun innerRadius(innerRadius: Int) = apply { properties.innerRadius = innerRadius }
|
|
||||||
fun innerRadiusRatio(innerRadiusRatio: Float) =
|
|
||||||
apply { properties.innerRadiusRatio = innerRadiusRatio }
|
|
||||||
|
|
||||||
fun thickness(thickness: Int) = apply { properties.thickness = thickness }
|
|
||||||
fun thicknessRatio(thicknessRatio: Float) = apply { properties.thicknessRatio = thicknessRatio }
|
|
||||||
|
|
||||||
fun useLevelForRing(use: Boolean = true) = apply { properties.useLevelForRing = use }
|
|
||||||
|
|
||||||
// <corner>
|
|
||||||
fun cornerRadius(cornerRadius: Int) = apply { properties.cornerRadius = cornerRadius }
|
|
||||||
|
|
||||||
fun topLeftRadius(topLeftRadius: Int) = apply { properties.topLeftRadius = topLeftRadius }
|
|
||||||
fun topRightRadius(topRightRadius: Int) = apply { properties.topRightRadius = topRightRadius }
|
|
||||||
fun bottomRightRadius(bottomRightRadius: Int) =
|
|
||||||
apply { properties.bottomRightRadius = bottomRightRadius }
|
|
||||||
|
|
||||||
fun bottomLeftRadius(bottomLeftRadius: Int) =
|
|
||||||
apply { properties.bottomLeftRadius = bottomLeftRadius }
|
|
||||||
|
|
||||||
fun rounded() = apply { cornerRadius(Int.MAX_VALUE) }
|
|
||||||
fun cornerRadii(
|
|
||||||
topLeftRadius: Int,
|
|
||||||
topRightRadius: Int,
|
|
||||||
bottomRightRadius: Int,
|
|
||||||
bottomLeftRadius: Int
|
|
||||||
) = apply {
|
|
||||||
topLeftRadius(topLeftRadius); topRightRadius(topRightRadius); bottomRightRadius(
|
|
||||||
bottomRightRadius
|
|
||||||
); bottomLeftRadius(bottomLeftRadius)
|
|
||||||
}
|
|
||||||
|
|
||||||
// <gradient>
|
|
||||||
|
|
||||||
fun gradient(useGradient: Boolean = true) = apply { properties.useGradient = useGradient }
|
|
||||||
|
|
||||||
fun gradientType(type: Int) = apply { properties.type = type }
|
|
||||||
fun linearGradient() = apply { gradientType(GradientDrawable.LINEAR_GRADIENT) }
|
|
||||||
fun radialGradient() = apply { gradientType(GradientDrawable.RADIAL_GRADIENT) }
|
|
||||||
fun sweepGradient() = apply { gradientType(GradientDrawable.SWEEP_GRADIENT) }
|
|
||||||
fun angle(angle: Int) = apply { properties.angle = angle }
|
|
||||||
fun centerX(centerX: Float) = apply { properties.centerX = centerX }
|
|
||||||
fun centerY(centerY: Float) = apply { properties.centerY = centerY }
|
|
||||||
fun center(centerX: Float, centerY: Float) = apply { centerX(centerX); centerY(centerY) }
|
|
||||||
|
|
||||||
fun useCenterColor(useCenterColor: Boolean = true) =
|
|
||||||
apply { properties.useCenterColor = useCenterColor }
|
|
||||||
|
|
||||||
fun startColor(startColor: Int) = apply { properties.startColor = startColor }
|
|
||||||
fun centerColor(centerColor: Int) = apply {
|
|
||||||
properties.centerColor = centerColor
|
|
||||||
useCenterColor(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun endColor(endColor: Int) = apply { properties.endColor = endColor }
|
|
||||||
fun gradientColors(startColor: Int, endColor: Int, centerColor: Int?) = apply {
|
|
||||||
startColor(startColor); endColor(endColor)
|
|
||||||
useCenterColor(centerColor != null)
|
|
||||||
centerColor?.let {
|
|
||||||
centerColor(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun gradientRadiusType(gradientRadiusType: Int) =
|
|
||||||
apply { properties.gradientRadiusType = gradientRadiusType }
|
|
||||||
|
|
||||||
fun gradientRadius(gradientRadius: Float) = apply { properties.gradientRadius = gradientRadius }
|
|
||||||
fun gradientRadius(radius: Float, type: Int) =
|
|
||||||
apply { gradientRadius(radius); gradientRadiusType(type) }
|
|
||||||
|
|
||||||
fun gradientRadiusInPixel(radius: Float) =
|
|
||||||
apply { gradientRadius(radius); gradientRadiusType(DrawableProperties.RADIUS_TYPE_PIXELS) }
|
|
||||||
|
|
||||||
fun gradientRadiusInFraction(radius: Float) =
|
|
||||||
apply { gradientRadius(radius); gradientRadiusType(DrawableProperties.RADIUS_TYPE_FRACTION) }
|
|
||||||
|
|
||||||
fun useLevelForGradient(use: Boolean) = apply { properties.useLevelForGradient = use }
|
|
||||||
fun useLevelForGradient() = apply { useLevelForGradient(true) }
|
|
||||||
|
|
||||||
// <size>
|
|
||||||
fun width(width: Int) = apply { properties.width = width }
|
|
||||||
|
|
||||||
fun height(height: Int) = apply { properties.height = height }
|
|
||||||
fun size(width: Int, height: Int) = apply { width(width); height(height) }
|
|
||||||
fun size(size: Int) = apply { width(size).height(size) }
|
|
||||||
|
|
||||||
// <solid>
|
|
||||||
fun solidColor(solidColor: Int) = apply { properties.solidColor = solidColor }
|
|
||||||
|
|
||||||
private var solidColorPressed: Int? = null
|
|
||||||
fun solidColorPressed(color: Int?) = apply { solidColorPressed = color }
|
|
||||||
private var solidColorPressedWhenRippleUnsupported: Int? = null
|
|
||||||
fun solidColorPressedWhenRippleUnsupported(color: Int?) =
|
|
||||||
apply { solidColorPressedWhenRippleUnsupported = color }
|
|
||||||
|
|
||||||
private var solidColorDisabled: Int? = null
|
|
||||||
fun solidColorDisabled(color: Int?) = apply { solidColorDisabled = color }
|
|
||||||
private var solidColorSelected: Int? = null
|
|
||||||
fun solidColorSelected(color: Int?) = apply { solidColorSelected = color }
|
|
||||||
fun solidColorStateList(colorStateList: ColorStateList) =
|
|
||||||
apply { properties.solidColorStateList = colorStateList }
|
|
||||||
|
|
||||||
// <stroke>
|
|
||||||
fun strokeWidth(strokeWidth: Int) = apply { properties.strokeWidth = strokeWidth }
|
|
||||||
|
|
||||||
fun strokeColor(strokeColor: Int) = apply { properties.strokeColor = strokeColor }
|
|
||||||
private var strokeColorPressed: Int? = null
|
|
||||||
fun strokeColorPressed(color: Int?) = apply { strokeColorPressed = color }
|
|
||||||
private var strokeColorDisabled: Int? = null
|
|
||||||
fun strokeColorDisabled(color: Int?) = apply { strokeColorDisabled = color }
|
|
||||||
private var strokeColorSelected: Int? = null
|
|
||||||
fun strokeColorSelected(color: Int?) = apply { strokeColorSelected = color }
|
|
||||||
fun strokeColorStateList(colorStateList: ColorStateList) =
|
|
||||||
apply { properties.strokeColorStateList = colorStateList }
|
|
||||||
|
|
||||||
fun dashWidth(dashWidth: Int) = apply { properties.dashWidth = dashWidth }
|
|
||||||
fun dashGap(dashGap: Int) = apply { properties.dashGap = dashGap }
|
|
||||||
fun hairlineBordered() = apply { strokeWidth(1) }
|
|
||||||
fun shortDashed() = apply { dashWidth(12).dashGap(12) }
|
|
||||||
fun mediumDashed() = apply { dashWidth(24).dashGap(24) }
|
|
||||||
fun longDashed() = apply { dashWidth(36).dashGap(36) }
|
|
||||||
fun dashed() = apply { mediumDashed() }
|
|
||||||
|
|
||||||
// <rotate>
|
|
||||||
private var rotateOrder = 0
|
|
||||||
|
|
||||||
|
|
||||||
fun rotate(boolean: Boolean = true) = apply {
|
|
||||||
properties.useRotate = boolean
|
|
||||||
rotateOrder = if (boolean) {
|
|
||||||
order.getAndIncrement()
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun pivotX(pivotX: Float) = apply { properties.pivotX = pivotX }
|
|
||||||
fun pivotY(pivotY: Float) = apply { properties.pivotY = pivotY }
|
|
||||||
fun pivot(pivotX: Float, pivotY: Float) = apply { pivotX(pivotX).pivotY(pivotY) }
|
|
||||||
fun fromDegrees(degrees: Float) = apply { properties.fromDegrees = degrees }
|
|
||||||
fun toDegrees(degrees: Float) = apply { properties.toDegrees = degrees }
|
|
||||||
fun degrees(fromDegrees: Float, toDegrees: Float) =
|
|
||||||
apply { fromDegrees(fromDegrees).toDegrees(toDegrees) }
|
|
||||||
|
|
||||||
fun degrees(degrees: Float) = apply { fromDegrees(degrees).toDegrees(degrees) }
|
|
||||||
fun rotate(fromDegrees: Float, toDegrees: Float) =
|
|
||||||
apply { rotate().fromDegrees(fromDegrees).toDegrees(toDegrees) }
|
|
||||||
|
|
||||||
fun rotate(degrees: Float) = apply { rotate().degrees(degrees) }
|
|
||||||
|
|
||||||
// <scale>
|
|
||||||
private var scaleOrder = 0
|
|
||||||
|
|
||||||
|
|
||||||
fun scale(boolean: Boolean = true) = apply {
|
|
||||||
properties.useScale = boolean
|
|
||||||
scaleOrder = if (boolean) {
|
|
||||||
order.getAndIncrement()
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun scaleLevel(level: Int) = apply { properties.scaleLevel = level }
|
|
||||||
fun scaleGravity(gravity: Int) = apply { properties.scaleGravity = gravity }
|
|
||||||
fun scaleWidth(scale: Float) = apply { properties.scaleWidth = scale }
|
|
||||||
fun scaleHeight(scale: Float) = apply { properties.scaleHeight = scale }
|
|
||||||
fun scale(scale: Float) = apply { scale().scaleWidth(scale).scaleHeight(scale) }
|
|
||||||
fun scale(scaleWidth: Float, scaleHeight: Float) =
|
|
||||||
apply { scale().scaleWidth(scaleWidth).scaleHeight(scaleHeight) }
|
|
||||||
|
|
||||||
// flip
|
|
||||||
|
|
||||||
fun flip(boolean: Boolean = true) = apply { properties.useFlip = boolean }
|
|
||||||
|
|
||||||
fun orientation(orientation: Int) = apply { properties.orientation = orientation }
|
|
||||||
fun flipVertical() = apply { flip().orientation(FlipDrawable.ORIENTATION_VERTICAL) }
|
|
||||||
|
|
||||||
// <ripple>
|
|
||||||
|
|
||||||
fun ripple(boolean: Boolean = true) = apply { properties.useRipple = boolean }
|
|
||||||
|
|
||||||
fun rippleColor(color: Int) = apply { properties.rippleColor = color }
|
|
||||||
fun rippleColorStateList(colorStateList: ColorStateList) =
|
|
||||||
apply { properties.rippleColorStateList = colorStateList }
|
|
||||||
|
|
||||||
fun rippleRadius(radius: Int) = apply { properties.rippleRadius = radius }
|
|
||||||
|
|
||||||
fun build(): Drawable {
|
|
||||||
if (baseDrawable != null) {
|
|
||||||
return wrap(baseDrawable!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
var drawable: Drawable
|
|
||||||
|
|
||||||
// fall back when ripple is unavailable on devices with API < 21
|
|
||||||
if (shouldFallbackRipple()) {
|
|
||||||
if (solidColorPressedWhenRippleUnsupported != null) {
|
|
||||||
solidColorPressed(solidColorPressedWhenRippleUnsupported)
|
|
||||||
} else {
|
|
||||||
solidColorPressed(properties.rippleColor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needStateListDrawable()) {
|
|
||||||
drawable = StateListDrawableBuilder()
|
|
||||||
.pressed(buildPressedDrawable())
|
|
||||||
.disabled(buildDisabledDrawable())
|
|
||||||
.selected(buildSelectedDrawable())
|
|
||||||
.normal(buildNormalDrawable())
|
|
||||||
.build()
|
|
||||||
} else {
|
|
||||||
drawable = GradientDrawable()
|
|
||||||
setupGradientDrawable(drawable)
|
|
||||||
}
|
|
||||||
drawable = wrap(drawable)
|
|
||||||
return drawable
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getSolidColorStateList(): ColorStateList {
|
|
||||||
if (properties.solidColorStateList != null) {
|
|
||||||
return properties.solidColorStateList!!
|
|
||||||
}
|
|
||||||
|
|
||||||
val states = mutableListOf<IntArray>()
|
|
||||||
val colors = mutableListOf<Int>()
|
|
||||||
|
|
||||||
solidColorPressed?.let {
|
|
||||||
states.add(intArrayOf(android.R.attr.state_pressed))
|
|
||||||
colors.add(it)
|
|
||||||
}
|
|
||||||
solidColorDisabled?.let {
|
|
||||||
states.add(intArrayOf(-android.R.attr.state_enabled))
|
|
||||||
colors.add(it)
|
|
||||||
}
|
|
||||||
solidColorSelected?.let {
|
|
||||||
states.add(intArrayOf(android.R.attr.state_selected))
|
|
||||||
colors.add(it)
|
|
||||||
}
|
|
||||||
states.add(StateSet.WILD_CARD)
|
|
||||||
colors.add(properties.solidColor)
|
|
||||||
|
|
||||||
return ColorStateList(states.toTypedArray(), colors.toIntArray())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getStrokeColorStateList(): ColorStateList {
|
|
||||||
if (properties.strokeColorStateList != null) {
|
|
||||||
return properties.strokeColorStateList!!
|
|
||||||
}
|
|
||||||
|
|
||||||
val states = mutableListOf<IntArray>()
|
|
||||||
val colors = mutableListOf<Int>()
|
|
||||||
|
|
||||||
strokeColorPressed?.let {
|
|
||||||
states.add(intArrayOf(android.R.attr.state_pressed))
|
|
||||||
colors.add(it)
|
|
||||||
}
|
|
||||||
strokeColorDisabled?.let {
|
|
||||||
states.add(intArrayOf(-android.R.attr.state_enabled))
|
|
||||||
colors.add(it)
|
|
||||||
}
|
|
||||||
strokeColorSelected?.let {
|
|
||||||
states.add(intArrayOf(android.R.attr.state_selected))
|
|
||||||
colors.add(it)
|
|
||||||
}
|
|
||||||
states.add(StateSet.WILD_CARD)
|
|
||||||
colors.add(properties.strokeColor)
|
|
||||||
|
|
||||||
return ColorStateList(states.toTypedArray(), colors.toIntArray())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildPressedDrawable(): Drawable? {
|
|
||||||
if (solidColorPressed == null && strokeColorPressed == null) return null
|
|
||||||
|
|
||||||
val pressedDrawable = GradientDrawable()
|
|
||||||
setupGradientDrawable(pressedDrawable)
|
|
||||||
solidColorPressed?.let {
|
|
||||||
pressedDrawable.setColor(it)
|
|
||||||
}
|
|
||||||
strokeColorPressed?.let {
|
|
||||||
setStrokeColor(pressedDrawable, it)
|
|
||||||
}
|
|
||||||
return pressedDrawable
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildDisabledDrawable(): Drawable? {
|
|
||||||
if (solidColorDisabled == null && strokeColorDisabled == null) return null
|
|
||||||
|
|
||||||
val disabledDrawable = GradientDrawable()
|
|
||||||
setupGradientDrawable(disabledDrawable)
|
|
||||||
solidColorDisabled?.let {
|
|
||||||
disabledDrawable.setColor(it)
|
|
||||||
}
|
|
||||||
strokeColorDisabled?.let {
|
|
||||||
setStrokeColor(disabledDrawable, it)
|
|
||||||
}
|
|
||||||
return disabledDrawable
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildSelectedDrawable(): Drawable? {
|
|
||||||
if (solidColorSelected == null && strokeColorSelected == null) return null
|
|
||||||
|
|
||||||
val selectedDrawable = GradientDrawable()
|
|
||||||
setupGradientDrawable(selectedDrawable)
|
|
||||||
solidColorSelected?.let {
|
|
||||||
selectedDrawable.setColor(it)
|
|
||||||
}
|
|
||||||
strokeColorSelected?.let {
|
|
||||||
setStrokeColor(selectedDrawable, it)
|
|
||||||
}
|
|
||||||
return selectedDrawable
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildNormalDrawable(): Drawable {
|
|
||||||
val pressedDrawable = GradientDrawable()
|
|
||||||
setupGradientDrawable(pressedDrawable)
|
|
||||||
return pressedDrawable
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setupGradientDrawable(drawable: GradientDrawable) {
|
|
||||||
properties.apply {
|
|
||||||
drawable.shape = shape
|
|
||||||
if (shape == GradientDrawable.RING) {
|
|
||||||
setInnerRadius(drawable, innerRadius)
|
|
||||||
setInnerRadiusRatio(drawable, innerRadiusRatio)
|
|
||||||
setThickness(drawable, thickness)
|
|
||||||
setThicknessRatio(drawable, thicknessRatio)
|
|
||||||
setUseLevelForShape(drawable, useLevelForRing)
|
|
||||||
}
|
|
||||||
drawable.cornerRadii = getCornerRadii()
|
|
||||||
if (useGradient) {
|
|
||||||
drawable.gradientType = type
|
|
||||||
setGradientRadiusType(drawable, gradientRadiusType)
|
|
||||||
setGradientRadius(drawable, gradientRadius)
|
|
||||||
drawable.setGradientCenter(centerX, centerY)
|
|
||||||
setOrientation(drawable, getOrientation())
|
|
||||||
setColors(drawable, getColors())
|
|
||||||
drawable.useLevel = useLevelForGradient
|
|
||||||
} else {
|
|
||||||
drawable.color = getSolidColorStateList()
|
|
||||||
}
|
|
||||||
drawable.setSize(width, height)
|
|
||||||
drawable.setStroke(
|
|
||||||
strokeWidth,
|
|
||||||
getStrokeColorStateList(),
|
|
||||||
dashWidth.toFloat(),
|
|
||||||
dashGap.toFloat()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun needStateListDrawable(): Boolean {
|
|
||||||
return (hasStrokeColorStateList() || (!properties.useGradient && hasSolidColorStateList()))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun needRotateDrawable(): Boolean {
|
|
||||||
return properties.useRotate &&
|
|
||||||
!(properties.pivotX == 0.5f && properties.pivotY == 0.5f
|
|
||||||
&& properties.fromDegrees == 0f && properties.toDegrees == 0f)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun needScaleDrawable(): Boolean {
|
|
||||||
return properties.useScale
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun wrap(drawable: Drawable): Drawable {
|
|
||||||
var wrappedDrawable = drawable
|
|
||||||
|
|
||||||
if (rotateOrder > 0) {
|
|
||||||
transformsMap[rotateOrder] = ::wrapRotateIfNeeded
|
|
||||||
}
|
|
||||||
if (scaleOrder > 0) {
|
|
||||||
transformsMap[scaleOrder] = ::wrapScaleIfNeeded
|
|
||||||
}
|
|
||||||
|
|
||||||
for (action in transformsMap.values) {
|
|
||||||
wrappedDrawable = action.invoke(wrappedDrawable)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (properties.useFlip) {
|
|
||||||
wrappedDrawable = FlipDrawableBuilder()
|
|
||||||
.drawable(wrappedDrawable)
|
|
||||||
.orientation(properties.orientation)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isRippleSupported() && properties.useRipple) {
|
|
||||||
wrappedDrawable = RippleDrawableBuilder()
|
|
||||||
.drawable(wrappedDrawable)
|
|
||||||
.color(properties.rippleColor)
|
|
||||||
.colorStateList(properties.rippleColorStateList)
|
|
||||||
.radius(properties.rippleRadius)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
return wrappedDrawable
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun shouldFallbackRipple(): Boolean {
|
|
||||||
return properties.useRipple && !isRippleSupported()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isRippleSupported() = true
|
|
||||||
|
|
||||||
private fun wrapRotateIfNeeded(drawable: Drawable): Drawable {
|
|
||||||
if (!needRotateDrawable()) return drawable
|
|
||||||
|
|
||||||
with(properties) {
|
|
||||||
return RotateDrawableBuilder()
|
|
||||||
.drawable(drawable)
|
|
||||||
.pivotX(pivotX)
|
|
||||||
.pivotY(pivotY)
|
|
||||||
.fromDegrees(fromDegrees)
|
|
||||||
.toDegrees(toDegrees)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun wrapScaleIfNeeded(drawable: Drawable): Drawable {
|
|
||||||
if (!needScaleDrawable()) return drawable
|
|
||||||
|
|
||||||
with(properties) {
|
|
||||||
return ScaleDrawableBuilder()
|
|
||||||
.drawable(drawable)
|
|
||||||
.level(scaleLevel)
|
|
||||||
.scaleGravity(scaleGravity)
|
|
||||||
.scaleWidth(scaleWidth)
|
|
||||||
.scaleHeight(scaleHeight)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun hasSolidColorStateList(): Boolean {
|
|
||||||
return solidColorPressed != null || solidColorDisabled != null || solidColorSelected != null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun hasStrokeColorStateList(): Boolean {
|
|
||||||
return strokeColorPressed != null || strokeColorDisabled != null || strokeColorSelected != null
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,221 +0,0 @@
|
|||||||
/*
|
|
||||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
|
||||||
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
|
|
||||||
* https://github.com/fankes/TSBattery
|
|
||||||
*
|
|
||||||
* This software is non-free but opensource software: you can redistribute it
|
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
|
||||||
* as published by the Free Software Foundation; either
|
|
||||||
* version 3 of the License, or any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* and eula along with this software. If not, see
|
|
||||||
* <https://www.gnu.org/licenses/>
|
|
||||||
*
|
|
||||||
* This file is Created by fankes on 2022/1/8.
|
|
||||||
*/
|
|
||||||
@file:Suppress("SetterBackingFieldAssignment", "unused")
|
|
||||||
|
|
||||||
package com.fankes.tsbattery.utils.drawable.drawabletoolbox
|
|
||||||
|
|
||||||
import android.content.res.ColorStateList
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.graphics.drawable.GradientDrawable
|
|
||||||
import android.os.Parcel
|
|
||||||
import android.os.Parcelable
|
|
||||||
import android.view.Gravity
|
|
||||||
import java.io.Serializable
|
|
||||||
|
|
||||||
data class DrawableProperties(
|
|
||||||
|
|
||||||
// <shape>
|
|
||||||
@JvmField var shape: Int = GradientDrawable.RECTANGLE,
|
|
||||||
@JvmField var innerRadius: Int = -1,
|
|
||||||
@JvmField var innerRadiusRatio: Float = 9f,
|
|
||||||
@JvmField var thickness: Int = -1,
|
|
||||||
@JvmField var thicknessRatio: Float = 3f,
|
|
||||||
@JvmField var useLevelForRing: Boolean = false,
|
|
||||||
|
|
||||||
// <corner>
|
|
||||||
private var _cornerRadius: Int = 0,
|
|
||||||
@JvmField var topLeftRadius: Int = 0,
|
|
||||||
@JvmField var topRightRadius: Int = 0,
|
|
||||||
@JvmField var bottomRightRadius: Int = 0,
|
|
||||||
@JvmField var bottomLeftRadius: Int = 0,
|
|
||||||
|
|
||||||
// <gradient>
|
|
||||||
@JvmField var useGradient: Boolean = false,
|
|
||||||
@JvmField var type: Int = GradientDrawable.RADIAL_GRADIENT,
|
|
||||||
@JvmField var angle: Int = 0,
|
|
||||||
@JvmField var centerX: Float = 0.5f,
|
|
||||||
@JvmField var centerY: Float = 0.5f,
|
|
||||||
@JvmField var useCenterColor: Boolean = false,
|
|
||||||
@JvmField var startColor: Int = Constants.DEFAULT_COLOR,
|
|
||||||
@JvmField var centerColor: Int? = null,
|
|
||||||
@JvmField var endColor: Int = 0x7FFFFFFF,
|
|
||||||
@JvmField var gradientRadiusType: Int = RADIUS_TYPE_FRACTION,
|
|
||||||
@JvmField var gradientRadius: Float = 0.5f,
|
|
||||||
@JvmField var useLevelForGradient: Boolean = false,
|
|
||||||
|
|
||||||
// <size>
|
|
||||||
@JvmField var width: Int = -1,
|
|
||||||
@JvmField var height: Int = -1,
|
|
||||||
|
|
||||||
// <solid>
|
|
||||||
@JvmField var solidColor: Int = Color.TRANSPARENT,
|
|
||||||
@JvmField var solidColorStateList: ColorStateList? = null,
|
|
||||||
|
|
||||||
// <stroke>
|
|
||||||
@JvmField var strokeWidth: Int = 0,
|
|
||||||
@JvmField var strokeColor: Int = Color.DKGRAY,
|
|
||||||
@JvmField var strokeColorStateList: ColorStateList? = null,
|
|
||||||
@JvmField var dashWidth: Int = 0,
|
|
||||||
@JvmField var dashGap: Int = 0,
|
|
||||||
|
|
||||||
// <rotate>
|
|
||||||
@JvmField var useRotate: Boolean = false,
|
|
||||||
@JvmField var pivotX: Float = 0.5f,
|
|
||||||
@JvmField var pivotY: Float = 0.5f,
|
|
||||||
@JvmField var fromDegrees: Float = 0f,
|
|
||||||
@JvmField var toDegrees: Float = 0f,
|
|
||||||
|
|
||||||
// <scale>
|
|
||||||
@JvmField var useScale: Boolean = false,
|
|
||||||
@JvmField var scaleLevel: Int = 10000,
|
|
||||||
@JvmField var scaleGravity: Int = Gravity.CENTER,
|
|
||||||
@JvmField var scaleWidth: Float = 0f,
|
|
||||||
@JvmField var scaleHeight: Float = 0f,
|
|
||||||
|
|
||||||
// flip
|
|
||||||
@JvmField var useFlip: Boolean = false,
|
|
||||||
@JvmField var orientation: Int = FlipDrawable.ORIENTATION_HORIZONTAL,
|
|
||||||
|
|
||||||
// ripple
|
|
||||||
@JvmField var useRipple: Boolean = false,
|
|
||||||
@JvmField var rippleColor: Int = Constants.DEFAULT_COLOR,
|
|
||||||
@JvmField var rippleColorStateList: ColorStateList? = null,
|
|
||||||
@JvmField var rippleRadius: Int = -1
|
|
||||||
) : Serializable {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val RADIUS_TYPE_PIXELS = 0
|
|
||||||
const val RADIUS_TYPE_FRACTION = 1
|
|
||||||
|
|
||||||
@JvmField
|
|
||||||
val CREATOR = object : Parcelable.Creator<DrawableProperties> {
|
|
||||||
override fun createFromParcel(parcel: Parcel): DrawableProperties {
|
|
||||||
return DrawableProperties(parcel)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun newArray(size: Int): Array<DrawableProperties?> {
|
|
||||||
return arrayOfNulls(size)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var cornerRadius: Int = _cornerRadius
|
|
||||||
set(value) {
|
|
||||||
_cornerRadius = value
|
|
||||||
topLeftRadius = value
|
|
||||||
topRightRadius = value
|
|
||||||
bottomRightRadius = value
|
|
||||||
bottomLeftRadius = value
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(parcel: Parcel) : this(
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readFloat(),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readFloat(),
|
|
||||||
parcel.readByte() != 0.toByte(),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readByte() != 0.toByte(),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readFloat(),
|
|
||||||
parcel.readFloat(),
|
|
||||||
parcel.readByte() != 0.toByte(),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readValue(Int::class.java.classLoader) as? Int,
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readFloat(),
|
|
||||||
parcel.readByte() != 0.toByte(),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readParcelable(ColorStateList::class.java.classLoader),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readParcelable(ColorStateList::class.java.classLoader),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readByte() != 0.toByte(),
|
|
||||||
parcel.readFloat(),
|
|
||||||
parcel.readFloat(),
|
|
||||||
parcel.readFloat(),
|
|
||||||
parcel.readFloat(),
|
|
||||||
parcel.readByte() != 0.toByte(),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readFloat(),
|
|
||||||
parcel.readFloat(),
|
|
||||||
parcel.readByte() != 0.toByte(),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readByte() != 0.toByte(),
|
|
||||||
parcel.readInt(),
|
|
||||||
parcel.readParcelable(ColorStateList::class.java.classLoader),
|
|
||||||
parcel.readInt()
|
|
||||||
)
|
|
||||||
|
|
||||||
fun copy(): DrawableProperties {
|
|
||||||
val parcel = Parcel.obtain()
|
|
||||||
parcel.setDataPosition(0)
|
|
||||||
val properties = CREATOR.createFromParcel(parcel)
|
|
||||||
parcel.recycle()
|
|
||||||
return properties
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getCornerRadii(): FloatArray {
|
|
||||||
return floatArrayOf(
|
|
||||||
topLeftRadius.toFloat(), topLeftRadius.toFloat(),
|
|
||||||
topRightRadius.toFloat(), topRightRadius.toFloat(),
|
|
||||||
bottomRightRadius.toFloat(), bottomRightRadius.toFloat(),
|
|
||||||
bottomLeftRadius.toFloat(), bottomLeftRadius.toFloat()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getOrientation(): GradientDrawable.Orientation {
|
|
||||||
val orientation: GradientDrawable.Orientation = when (val angle = this.angle % 360) {
|
|
||||||
0 -> GradientDrawable.Orientation.LEFT_RIGHT
|
|
||||||
45 -> GradientDrawable.Orientation.BL_TR
|
|
||||||
90 -> GradientDrawable.Orientation.BOTTOM_TOP
|
|
||||||
135 -> GradientDrawable.Orientation.BR_TL
|
|
||||||
180 -> GradientDrawable.Orientation.RIGHT_LEFT
|
|
||||||
225 -> GradientDrawable.Orientation.TR_BL
|
|
||||||
270 -> GradientDrawable.Orientation.TOP_BOTTOM
|
|
||||||
315 -> GradientDrawable.Orientation.TL_BR
|
|
||||||
else -> throw IllegalArgumentException("Unsupported angle: $angle")
|
|
||||||
}
|
|
||||||
return orientation
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getColors(): IntArray {
|
|
||||||
return if (useCenterColor && centerColor != null) {
|
|
||||||
intArrayOf(startColor, centerColor!!, endColor)
|
|
||||||
} else intArrayOf(startColor, endColor)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun materialization(): Drawable = DrawableBuilder().batch(this).build()
|
|
||||||
}
|
|
@@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
|
||||||
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
|
|
||||||
* https://github.com/fankes/TSBattery
|
|
||||||
*
|
|
||||||
* This software is non-free but opensource software: you can redistribute it
|
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
|
||||||
* as published by the Free Software Foundation; either
|
|
||||||
* version 3 of the License, or any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* and eula along with this software. If not, see
|
|
||||||
* <https://www.gnu.org/licenses/>
|
|
||||||
*
|
|
||||||
* This file is Created by fankes on 2022/1/8.
|
|
||||||
*/
|
|
||||||
package com.fankes.tsbattery.utils.drawable.drawabletoolbox
|
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
|
|
||||||
abstract class DrawableWrapperBuilder<T: DrawableWrapperBuilder<T>> {
|
|
||||||
|
|
||||||
protected var drawable: Drawable? = null
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
fun drawable(drawable: Drawable): T = apply { this.drawable = drawable } as T
|
|
||||||
|
|
||||||
abstract fun build(): Drawable
|
|
||||||
}
|
|
@@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
|
||||||
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
|
|
||||||
* https://github.com/fankes/TSBattery
|
|
||||||
*
|
|
||||||
* This software is non-free but opensource software: you can redistribute it
|
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
|
||||||
* as published by the Free Software Foundation; either
|
|
||||||
* version 3 of the License, or any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* and eula along with this software. If not, see
|
|
||||||
* <https://www.gnu.org/licenses/>
|
|
||||||
*
|
|
||||||
* This file is Created by fankes on 2022/1/8.
|
|
||||||
*/
|
|
||||||
@file:Suppress("DEPRECATION", "CanvasSize", "OVERRIDE_DEPRECATION")
|
|
||||||
|
|
||||||
package com.fankes.tsbattery.utils.drawable.drawabletoolbox
|
|
||||||
|
|
||||||
import android.graphics.Canvas
|
|
||||||
import android.graphics.ColorFilter
|
|
||||||
import android.graphics.Rect
|
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
|
|
||||||
class FlipDrawable(
|
|
||||||
private var drawable: Drawable,
|
|
||||||
private var orientation: Int = ORIENTATION_HORIZONTAL
|
|
||||||
) : Drawable() {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val ORIENTATION_HORIZONTAL = 0
|
|
||||||
const val ORIENTATION_VERTICAL = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun draw(canvas: Canvas) {
|
|
||||||
val saveCount = canvas.save()
|
|
||||||
if (orientation == ORIENTATION_VERTICAL) {
|
|
||||||
canvas.scale(1f, -1f, (canvas.width / 2).toFloat(), (canvas.height / 2).toFloat())
|
|
||||||
} else {
|
|
||||||
canvas.scale(-1f, 1f, (canvas.width / 2).toFloat(), (canvas.height / 2).toFloat())
|
|
||||||
}
|
|
||||||
drawable.bounds = Rect(0, 0, canvas.width, canvas.height)
|
|
||||||
drawable.draw(canvas)
|
|
||||||
canvas.restoreToCount(saveCount)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onLevelChange(level: Int): Boolean {
|
|
||||||
drawable.level = level
|
|
||||||
invalidateSelf()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getIntrinsicWidth(): Int {
|
|
||||||
return drawable.intrinsicWidth
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getIntrinsicHeight(): Int {
|
|
||||||
return drawable.intrinsicHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setAlpha(alpha: Int) {
|
|
||||||
drawable.alpha = alpha
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getOpacity(): Int {
|
|
||||||
return drawable.opacity
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setColorFilter(colorFilter: ColorFilter?) {
|
|
||||||
drawable.colorFilter = colorFilter
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
|
||||||
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
|
|
||||||
* https://github.com/fankes/TSBattery
|
|
||||||
*
|
|
||||||
* This software is non-free but opensource software: you can redistribute it
|
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
|
||||||
* as published by the Free Software Foundation; either
|
|
||||||
* version 3 of the License, or any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* and eula along with this software. If not, see
|
|
||||||
* <https://www.gnu.org/licenses/>
|
|
||||||
*
|
|
||||||
* This file is Created by fankes on 2022/1/8.
|
|
||||||
*/
|
|
||||||
package com.fankes.tsbattery.utils.drawable.drawabletoolbox
|
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
|
|
||||||
class FlipDrawableBuilder : DrawableWrapperBuilder<FlipDrawableBuilder>() {
|
|
||||||
|
|
||||||
private var orientation: Int = FlipDrawable.ORIENTATION_HORIZONTAL
|
|
||||||
|
|
||||||
fun orientation(orientation: Int) = apply { this.orientation = orientation }
|
|
||||||
|
|
||||||
override fun build(): Drawable {
|
|
||||||
return FlipDrawable(drawable!!, orientation)
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,182 +0,0 @@
|
|||||||
/*
|
|
||||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
|
||||||
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
|
|
||||||
* https://github.com/fankes/TSBattery
|
|
||||||
*
|
|
||||||
* This software is non-free but opensource software: you can redistribute it
|
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
|
||||||
* as published by the Free Software Foundation; either
|
|
||||||
* version 3 of the License, or any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* and eula along with this software. If not, see
|
|
||||||
* <https://www.gnu.org/licenses/>
|
|
||||||
*
|
|
||||||
* This file is Created by fankes on 2022/1/8.
|
|
||||||
*/
|
|
||||||
package com.fankes.tsbattery.utils.drawable.drawabletoolbox
|
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.graphics.drawable.LayerDrawable
|
|
||||||
import android.os.Build
|
|
||||||
import android.view.Gravity
|
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class LayerDrawableBuilder {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val DIMEN_UNDEFINED = Int.MIN_VALUE
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
private var paddingMode = LayerDrawable.PADDING_MODE_NEST
|
|
||||||
private var paddingLeft = 0
|
|
||||||
private var paddingTop = 0
|
|
||||||
private var paddingRight = 0
|
|
||||||
private var paddingBottom = 0
|
|
||||||
private var paddingStart = 0
|
|
||||||
private var paddingEnd = 0
|
|
||||||
private val layers = ArrayList<Layer>()
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
fun paddingMode(mode: Int) = apply { paddingMode = mode }
|
|
||||||
fun paddingLeft(padding: Int) = apply { paddingLeft = padding }
|
|
||||||
fun paddingTop(padding: Int) = apply { paddingTop = padding }
|
|
||||||
fun paddingRight(padding: Int) = apply { paddingRight = padding }
|
|
||||||
fun paddingBottom(padding: Int) = apply { paddingBottom = padding }
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.M)
|
|
||||||
fun paddingStart(padding: Int) = apply { paddingStart = padding }
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.M)
|
|
||||||
fun paddingEnd(padding: Int) = apply { paddingEnd = padding }
|
|
||||||
fun padding(padding: Int) = apply {
|
|
||||||
paddingLeft(padding).paddingTop(padding).paddingRight(padding).paddingBottom(padding)
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.M)
|
|
||||||
fun paddingRelative(padding: Int) = apply {
|
|
||||||
paddingStart(padding).paddingTop(padding).paddingEnd(padding).paddingBottom(padding)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun add(drawable: Drawable) = apply { layers.add(Layer(drawable)) }
|
|
||||||
|
|
||||||
fun width(width: Int) = apply { layers.last().width = width }
|
|
||||||
fun height(height: Int) = apply { layers.last().height = height }
|
|
||||||
|
|
||||||
fun insetLeft(inset: Int) = apply { layers.last().insetLeft = inset }
|
|
||||||
fun insetTop(inset: Int) = apply { layers.last().insetTop = inset }
|
|
||||||
fun insetRight(inset: Int) = apply { layers.last().insetRight = inset }
|
|
||||||
fun insetBottom(inset: Int) = apply { layers.last().insetBottom = inset }
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.M)
|
|
||||||
fun insetStart(inset: Int) = apply { layers.last().insetStart = inset }
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.M)
|
|
||||||
fun insetEnd(inset: Int) = apply { layers.last().insetEnd = inset }
|
|
||||||
fun inset(inset: Int) =
|
|
||||||
apply { insetLeft(inset).insetTop(inset).insetRight(inset).insetBottom(inset) }
|
|
||||||
|
|
||||||
fun inset(insetLeft: Int, insetTop: Int, insetRight: Int, insetBottom: Int) = apply {
|
|
||||||
insetLeft(insetLeft).insetTop(insetTop).insetRight(insetRight).insetBottom(insetBottom)
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.M)
|
|
||||||
fun insetRelative(inset: Int) =
|
|
||||||
apply { insetStart(inset).insetTop(inset).insetEnd(inset).insetBottom(inset) }
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.M)
|
|
||||||
fun insetRelative(insetStart: Int, insetTop: Int, insetEnd: Int, insetBottom: Int) = apply {
|
|
||||||
insetStart(insetStart).insetTop(insetTop).insetEnd(insetEnd).insetBottom(insetBottom)
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.M)
|
|
||||||
fun gravity(gravity: Int) = apply { layers.last().gravity = gravity }
|
|
||||||
|
|
||||||
fun modify(
|
|
||||||
index: Int, drawable: Drawable,
|
|
||||||
width: Int = DIMEN_UNDEFINED,
|
|
||||||
height: Int = DIMEN_UNDEFINED,
|
|
||||||
insetLeft: Int = DIMEN_UNDEFINED,
|
|
||||||
insetTop: Int = DIMEN_UNDEFINED,
|
|
||||||
insetRight: Int = DIMEN_UNDEFINED,
|
|
||||||
insetBottom: Int = DIMEN_UNDEFINED,
|
|
||||||
insetStart: Int = DIMEN_UNDEFINED,
|
|
||||||
insetEnd: Int = DIMEN_UNDEFINED
|
|
||||||
) =
|
|
||||||
apply {
|
|
||||||
val layer = layers[index]
|
|
||||||
layer.drawable = drawable
|
|
||||||
if (width != DIMEN_UNDEFINED) layer.width = width
|
|
||||||
if (height != DIMEN_UNDEFINED) layer.height = height
|
|
||||||
if (insetLeft != DIMEN_UNDEFINED) layer.insetLeft = insetLeft
|
|
||||||
if (insetTop != DIMEN_UNDEFINED) layer.insetTop = insetTop
|
|
||||||
if (insetRight != DIMEN_UNDEFINED) layer.insetRight = insetRight
|
|
||||||
if (insetBottom != DIMEN_UNDEFINED) layer.insetBottom = insetBottom
|
|
||||||
if (insetStart != DIMEN_UNDEFINED) layer.insetStart = insetStart
|
|
||||||
if (insetEnd != DIMEN_UNDEFINED) layer.insetEnd = insetEnd
|
|
||||||
}
|
|
||||||
|
|
||||||
fun build(): LayerDrawable {
|
|
||||||
val layerDrawable = LayerDrawable(layers.map { it -> it.drawable }.toTypedArray())
|
|
||||||
for (i in 0 until layers.size) {
|
|
||||||
val layer = layers[i]
|
|
||||||
layerDrawable.setLayerInset(
|
|
||||||
i,
|
|
||||||
layer.insetLeft,
|
|
||||||
layer.insetTop,
|
|
||||||
layer.insetRight,
|
|
||||||
layer.insetBottom
|
|
||||||
)
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
||||||
if (layer.insetStart != DIMEN_UNDEFINED || layer.insetEnd != DIMEN_UNDEFINED) {
|
|
||||||
layerDrawable.setLayerInsetRelative(
|
|
||||||
i,
|
|
||||||
layer.insetStart,
|
|
||||||
layer.insetTop,
|
|
||||||
layer.insetEnd,
|
|
||||||
layer.insetBottom
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
layerDrawable.setId(i, i)
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
||||||
layerDrawable.setLayerGravity(i, layer.gravity)
|
|
||||||
layerDrawable.setLayerInsetStart(i, layer.insetStart)
|
|
||||||
layerDrawable.setLayerInsetEnd(i, layer.insetEnd)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
layerDrawable.paddingMode = paddingMode
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
||||||
layerDrawable.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom)
|
|
||||||
if (paddingStart != DIMEN_UNDEFINED || paddingEnd != DIMEN_UNDEFINED) {
|
|
||||||
layerDrawable.setPaddingRelative(
|
|
||||||
paddingStart,
|
|
||||||
paddingTop,
|
|
||||||
paddingEnd,
|
|
||||||
paddingBottom
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return layerDrawable
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class Layer(var drawable: Drawable) {
|
|
||||||
var gravity: Int = Gravity.NO_GRAVITY
|
|
||||||
var width: Int = -1
|
|
||||||
var height: Int = -1
|
|
||||||
var insetLeft: Int = 0
|
|
||||||
var insetTop: Int = 0
|
|
||||||
var insetRight: Int = 0
|
|
||||||
var insetBottom: Int = 0
|
|
||||||
var insetStart: Int = DIMEN_UNDEFINED
|
|
||||||
var insetEnd: Int = DIMEN_UNDEFINED
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
|
||||||
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
|
|
||||||
* https://github.com/fankes/TSBattery
|
|
||||||
*
|
|
||||||
* This software is non-free but opensource software: you can redistribute it
|
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
|
||||||
* as published by the Free Software Foundation; either
|
|
||||||
* version 3 of the License, or any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* and eula along with this software. If not, see
|
|
||||||
* <https://www.gnu.org/licenses/>
|
|
||||||
*
|
|
||||||
* This file is Created by fankes on 2022/1/8.
|
|
||||||
*/
|
|
||||||
package com.fankes.tsbattery.utils.drawable.drawabletoolbox
|
|
||||||
|
|
||||||
import android.graphics.Path
|
|
||||||
import android.graphics.drawable.ShapeDrawable
|
|
||||||
import android.graphics.drawable.shapes.PathShape
|
|
||||||
|
|
||||||
class PathShapeDrawableBuilder {
|
|
||||||
|
|
||||||
private var path: Path? = null
|
|
||||||
private var pathStandardWidth: Float = 100f
|
|
||||||
private var pathStandardHeight: Float = 100f
|
|
||||||
private var width: Int = -1
|
|
||||||
private var height: Int = -1
|
|
||||||
|
|
||||||
fun path(path: Path, pathStandardWidth: Float, pathStandardHeight: Float) = apply {
|
|
||||||
this.path = path
|
|
||||||
this.pathStandardWidth = pathStandardWidth
|
|
||||||
this.pathStandardHeight = pathStandardHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
fun width(width: Int) = apply { this.width = width }
|
|
||||||
fun height(height: Int) = apply { this.height = height }
|
|
||||||
fun size(size: Int) = apply { width(size).height(size) }
|
|
||||||
|
|
||||||
fun build(custom: ((shapeDrawable: ShapeDrawable) -> Unit)? = null): ShapeDrawable {
|
|
||||||
val shapeDrawable = ShapeDrawable()
|
|
||||||
if (path == null || width <= 0 || height <= 0) {
|
|
||||||
return shapeDrawable
|
|
||||||
}
|
|
||||||
val pathShape = PathShape(path!!, pathStandardWidth, pathStandardHeight)
|
|
||||||
|
|
||||||
shapeDrawable.shape = pathShape
|
|
||||||
shapeDrawable.intrinsicWidth = width
|
|
||||||
shapeDrawable.intrinsicHeight = height
|
|
||||||
if (custom != null) {
|
|
||||||
custom(shapeDrawable)
|
|
||||||
}
|
|
||||||
return shapeDrawable
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,73 +0,0 @@
|
|||||||
/*
|
|
||||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
|
||||||
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
|
|
||||||
* https://github.com/fankes/TSBattery
|
|
||||||
*
|
|
||||||
* This software is non-free but opensource software: you can redistribute it
|
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
|
||||||
* as published by the Free Software Foundation; either
|
|
||||||
* version 3 of the License, or any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* and eula along with this software. If not, see
|
|
||||||
* <https://www.gnu.org/licenses/>
|
|
||||||
*
|
|
||||||
* This file is Created by fankes on 2022/1/8.
|
|
||||||
*/
|
|
||||||
package com.fankes.tsbattery.utils.drawable.drawabletoolbox
|
|
||||||
|
|
||||||
import android.content.res.ColorStateList
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.drawable.*
|
|
||||||
import android.util.StateSet
|
|
||||||
|
|
||||||
class RippleDrawableBuilder : DrawableWrapperBuilder<RippleDrawableBuilder>() {
|
|
||||||
|
|
||||||
private var color: Int = Constants.DEFAULT_COLOR
|
|
||||||
private var colorStateList: ColorStateList? = null
|
|
||||||
private var radius: Int = -1
|
|
||||||
|
|
||||||
fun color(color: Int) = apply { this.color = color }
|
|
||||||
fun colorStateList(colorStateList: ColorStateList?) =
|
|
||||||
apply { this.colorStateList = colorStateList }
|
|
||||||
|
|
||||||
fun radius(radius: Int) = apply { this.radius = radius }
|
|
||||||
|
|
||||||
override fun build(): Drawable {
|
|
||||||
var drawable = this.drawable!!
|
|
||||||
val colorStateList = this.colorStateList ?: ColorStateList(
|
|
||||||
arrayOf(StateSet.WILD_CARD),
|
|
||||||
intArrayOf(color)
|
|
||||||
)
|
|
||||||
|
|
||||||
var mask = if (drawable is DrawableContainer) drawable.getCurrent() else drawable
|
|
||||||
if (mask is ShapeDrawable) {
|
|
||||||
val state = mask.getConstantState()
|
|
||||||
if (state != null) {
|
|
||||||
val temp = state.newDrawable().mutate() as ShapeDrawable
|
|
||||||
temp.paint.color = Color.BLACK
|
|
||||||
mask = temp
|
|
||||||
}
|
|
||||||
} else if (mask is GradientDrawable) {
|
|
||||||
val state = mask.getConstantState()
|
|
||||||
if (state != null) {
|
|
||||||
val temp = state.newDrawable().mutate() as GradientDrawable
|
|
||||||
temp.setColor(Color.BLACK)
|
|
||||||
mask = temp
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mask = ColorDrawable(Color.BLACK)
|
|
||||||
}
|
|
||||||
|
|
||||||
val rippleDrawable = RippleDrawable(colorStateList, drawable, mask)
|
|
||||||
setRadius(rippleDrawable, radius)
|
|
||||||
rippleDrawable.invalidateSelf()
|
|
||||||
drawable = rippleDrawable
|
|
||||||
return drawable
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
|
||||||
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
|
|
||||||
* https://github.com/fankes/TSBattery
|
|
||||||
*
|
|
||||||
* This software is non-free but opensource software: you can redistribute it
|
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
|
||||||
* as published by the Free Software Foundation; either
|
|
||||||
* version 3 of the License, or any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* and eula along with this software. If not, see
|
|
||||||
* <https://www.gnu.org/licenses/>
|
|
||||||
*
|
|
||||||
* This file is Created by fankes on 2022/1/8.
|
|
||||||
*/
|
|
||||||
package com.fankes.tsbattery.utils.drawable.drawabletoolbox
|
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.graphics.drawable.RotateDrawable
|
|
||||||
|
|
||||||
class RotateDrawableBuilder : DrawableWrapperBuilder<RotateDrawableBuilder>() {
|
|
||||||
|
|
||||||
private var pivotX: Float = 0.5f
|
|
||||||
private var pivotY: Float = 0.5f
|
|
||||||
private var fromDegrees: Float = 0f
|
|
||||||
private var toDegrees: Float = 360f
|
|
||||||
|
|
||||||
fun pivotX(x: Float) = apply { pivotX = x }
|
|
||||||
fun pivotY(y: Float) = apply { pivotY = y }
|
|
||||||
fun fromDegrees(degree: Float) = apply { fromDegrees = degree }
|
|
||||||
fun toDegrees(degree: Float) = apply { toDegrees = degree }
|
|
||||||
|
|
||||||
override fun build(): Drawable {
|
|
||||||
val rotateDrawable = RotateDrawable()
|
|
||||||
drawable?.let {
|
|
||||||
setDrawable(rotateDrawable, it)
|
|
||||||
apply {
|
|
||||||
setPivotX(rotateDrawable, pivotX)
|
|
||||||
setPivotY(rotateDrawable, pivotY)
|
|
||||||
setFromDegrees(rotateDrawable, fromDegrees)
|
|
||||||
setToDegrees(rotateDrawable, toDegrees)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rotateDrawable
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
|
||||||
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
|
|
||||||
* https://github.com/fankes/TSBattery
|
|
||||||
*
|
|
||||||
* This software is non-free but opensource software: you can redistribute it
|
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
|
||||||
* as published by the Free Software Foundation; either
|
|
||||||
* version 3 of the License, or any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* and eula along with this software. If not, see
|
|
||||||
* <https://www.gnu.org/licenses/>
|
|
||||||
*
|
|
||||||
* This file is Created by fankes on 2022/1/8.
|
|
||||||
*/
|
|
||||||
package com.fankes.tsbattery.utils.drawable.drawabletoolbox
|
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.graphics.drawable.ScaleDrawable
|
|
||||||
import android.view.Gravity
|
|
||||||
|
|
||||||
class ScaleDrawableBuilder : DrawableWrapperBuilder<ScaleDrawableBuilder>() {
|
|
||||||
|
|
||||||
private var level: Int = 10000
|
|
||||||
private var scaleGravity = Gravity.CENTER
|
|
||||||
private var scaleWidth: Float = 0f
|
|
||||||
private var scaleHeight: Float = 0f
|
|
||||||
|
|
||||||
fun level(level: Int) = apply { this.level = level }
|
|
||||||
fun scaleGravity(gravity: Int) = apply { this.scaleGravity = gravity }
|
|
||||||
fun scaleWidth(scale: Float) = apply { this.scaleWidth = scale }
|
|
||||||
fun scaleHeight(scale: Float) = apply { this.scaleHeight = scale }
|
|
||||||
|
|
||||||
override fun build(): Drawable {
|
|
||||||
val scaleDrawable = ScaleDrawable(drawable, scaleGravity, scaleWidth, scaleHeight)
|
|
||||||
scaleDrawable.level = level
|
|
||||||
return scaleDrawable
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,60 +0,0 @@
|
|||||||
/*
|
|
||||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
|
||||||
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
|
|
||||||
* https://github.com/fankes/TSBattery
|
|
||||||
*
|
|
||||||
* This software is non-free but opensource software: you can redistribute it
|
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
|
||||||
* as published by the Free Software Foundation; either
|
|
||||||
* version 3 of the License, or any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* and eula along with this software. If not, see
|
|
||||||
* <https://www.gnu.org/licenses/>
|
|
||||||
*
|
|
||||||
* This file is Created by fankes on 2022/1/8.
|
|
||||||
*/
|
|
||||||
package com.fankes.tsbattery.utils.drawable.drawabletoolbox
|
|
||||||
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.drawable.ColorDrawable
|
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.graphics.drawable.StateListDrawable
|
|
||||||
import android.util.StateSet
|
|
||||||
|
|
||||||
class StateListDrawableBuilder {
|
|
||||||
|
|
||||||
private var pressed: Drawable? = null
|
|
||||||
private var disabled: Drawable? = null
|
|
||||||
private var selected: Drawable? = null
|
|
||||||
private var normal: Drawable = ColorDrawable(Color.TRANSPARENT)
|
|
||||||
|
|
||||||
fun pressed(pressed: Drawable?) = apply { this.pressed = pressed }
|
|
||||||
fun disabled(disabled: Drawable?) = apply { this.disabled = disabled }
|
|
||||||
fun selected(selected: Drawable?) = apply { this.selected = selected }
|
|
||||||
fun normal(normal: Drawable) = apply { this.normal = normal }
|
|
||||||
|
|
||||||
fun build(): StateListDrawable {
|
|
||||||
val stateListDrawable = StateListDrawable()
|
|
||||||
setupStateListDrawable(stateListDrawable)
|
|
||||||
return stateListDrawable
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setupStateListDrawable(stateListDrawable: StateListDrawable) {
|
|
||||||
pressed?.let {
|
|
||||||
stateListDrawable.addState(intArrayOf(android.R.attr.state_pressed), it)
|
|
||||||
}
|
|
||||||
disabled?.let {
|
|
||||||
stateListDrawable.addState(intArrayOf(-android.R.attr.state_enabled), it)
|
|
||||||
}
|
|
||||||
selected?.let {
|
|
||||||
stateListDrawable.addState(intArrayOf(android.R.attr.state_selected), it)
|
|
||||||
}
|
|
||||||
stateListDrawable.addState(StateSet.WILD_CARD, normal)
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,12 +1,12 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'com.android.application' version '7.2.1' apply false
|
id 'com.android.application' version '7.2.1' apply false
|
||||||
id 'com.android.library' version '7.2.1' apply false
|
id 'com.android.library' version '7.2.1' apply false
|
||||||
id 'org.jetbrains.kotlin.android' version '1.7.0' apply false
|
id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
appVersionName = "3.99"
|
appVersionName = "3.99.6"
|
||||||
appVersionCode = 22
|
appVersionCode = 24
|
||||||
enableR8 = true
|
enableR8 = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
|||||||
#Wed May 25 04:34:58 CST 2022
|
#Wed May 25 04:34:58 CST 2022
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
@@ -10,6 +10,7 @@ dependencyResolutionManagement {
|
|||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
maven { url "https://api.xposed.info/" }
|
maven { url "https://api.xposed.info/" }
|
||||||
|
maven { url "https://www.jitpack.io" }
|
||||||
maven { url "https://s01.oss.sonatype.org/content/repositories/releases" }
|
maven { url "https://s01.oss.sonatype.org/content/repositories/releases" }
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user