You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
378 lines
14 KiB
Java
378 lines
14 KiB
Java
package name.mikanoshi.customiuizer.utils;
|
|
|
|
import android.animation.ArgbEvaluator;
|
|
import android.content.BroadcastReceiver;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.content.IntentFilter;
|
|
import android.content.res.Configuration;
|
|
import android.graphics.Color;
|
|
import android.graphics.LinearGradient;
|
|
import android.graphics.Matrix;
|
|
import android.graphics.Paint;
|
|
import android.graphics.Shader;
|
|
import android.graphics.drawable.ShapeDrawable;
|
|
import android.graphics.drawable.shapes.RectShape;
|
|
import android.graphics.drawable.shapes.RoundRectShape;
|
|
import android.net.Uri;
|
|
import android.os.Handler;
|
|
import android.util.AttributeSet;
|
|
import android.view.Gravity;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.widget.FrameLayout;
|
|
import android.widget.ImageView;
|
|
|
|
import de.robv.android.xposed.XposedBridge;
|
|
import de.robv.android.xposed.XposedHelpers;
|
|
|
|
public class BatteryIndicator extends ImageView {
|
|
protected int mDisplayWidth;
|
|
protected boolean mIsBeingCharged;
|
|
protected boolean mIsExtremePowerSave;
|
|
protected boolean mIsPowerSave;
|
|
protected final int mLowLevelSystem = getResources().getInteger(getResources().getIdentifier("config_lowBatteryWarningLevel", "integer", "android"));
|
|
protected int mPowerLevel;
|
|
protected int mTestPowerLevel;
|
|
private int mFullColor = Color.GREEN;
|
|
private int mLowColor = Color.RED;
|
|
private int mPowerSaveColor = Color.rgb(245, 166, 35);
|
|
private int mChargingColor = Color.YELLOW;
|
|
private int mLowLevel = mLowLevelSystem;
|
|
private int mHeight = 5;
|
|
private int mGlow = 0;
|
|
private int mTransparency = 0;
|
|
private int mPadding = 0;
|
|
private int mVisibility = View.VISIBLE;
|
|
private ColorMode mColorMode = ColorMode.DISCRETE;
|
|
private boolean mTesting = false;
|
|
private boolean mRounded = false;
|
|
private boolean mCentered = false;
|
|
private boolean mExpanded = false;
|
|
private boolean mOnKeyguard = false;
|
|
private boolean mBottom = false;
|
|
private boolean mLimited = false;
|
|
private int mTintColor = Color.argb(153, 0, 0, 0);
|
|
private Object mStatusBar = null;
|
|
|
|
enum ColorMode {
|
|
DUMMY, DISCRETE, GRADUAL, RAINBOW
|
|
}
|
|
|
|
public BatteryIndicator(Context context) {
|
|
super(context);
|
|
updateDisplaySize();
|
|
}
|
|
|
|
public BatteryIndicator(Context context, AttributeSet attributeSet) {
|
|
super(context, attributeSet);
|
|
updateDisplaySize();
|
|
}
|
|
|
|
public void init(Object statusBar) {
|
|
mStatusBar = statusBar;
|
|
|
|
try {
|
|
ShapeDrawable shape = new ShapeDrawable();
|
|
Paint paint = shape.getPaint();
|
|
paint.setStyle(Paint.Style.FILL);
|
|
paint.setAntiAlias(true);
|
|
shape.setIntrinsicWidth(9999);
|
|
setImageDrawable(shape);
|
|
} catch (Throwable t) {
|
|
XposedBridge.log(t);
|
|
}
|
|
|
|
updateParameters();
|
|
new Helpers.SharedPrefObserver(getContext(), new Handler(getContext().getMainLooper())) {
|
|
@Override
|
|
public void onChange(Uri uri) {
|
|
try {
|
|
String key = uri.getPathSegments().get(2);
|
|
if (!mTesting && key.contains("pref_key_system_batteryindicator")) {
|
|
updateParameters();
|
|
update();
|
|
}
|
|
} catch (Throwable t) {
|
|
XposedBridge.log(t);
|
|
}
|
|
}
|
|
};
|
|
getContext().registerReceiver(new BroadcastReceiver() {
|
|
@Override
|
|
public void onReceive(Context context, Intent intent) {
|
|
removeCallbacks(step);
|
|
startTest();
|
|
}
|
|
}, new IntentFilter("name.mikanoshi.customiuizer.mods.BatteryIndicatorTest"));
|
|
}
|
|
|
|
Runnable step = new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
mTestPowerLevel--;
|
|
if (mTestPowerLevel >= 0) {
|
|
update();
|
|
postDelayed(step, mTestPowerLevel == mLowLevel - 1 ? 300 : 20);
|
|
} else {
|
|
removeCallbacks(step);
|
|
mTesting = false;
|
|
postDelayed(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
updateParameters();
|
|
update();
|
|
}
|
|
}, 1000);
|
|
}
|
|
}
|
|
};
|
|
|
|
private void startTest() {
|
|
mTesting = true;
|
|
mTestPowerLevel = 100;
|
|
post(step);
|
|
}
|
|
|
|
// int lightPos = 0;
|
|
// Runnable chargingAnim = new Runnable() {
|
|
// @Override
|
|
// public void run() {
|
|
// if (!mTesting) {
|
|
// lightPos += 3;
|
|
// if (lightPos > 180) lightPos = 0;
|
|
// int val = (int)(90 * Math.exp(-Math.pow(lightPos - 90, 2) / 180f));
|
|
// Paint p = ((ShapeDrawable)getDrawable()).getPaint();
|
|
// int color = p.getColor();
|
|
//
|
|
// int runColor = Color.WHITE;
|
|
// if (mColorMode == ColorMode.LIGHTDARK)
|
|
// runColor = Color.argb(
|
|
// Color.alpha(color),
|
|
// Math.max(0, Math.min(255, Math.round(Color.red(color) + val / 180f * (Color.red(~color) - Color.red(color))))),
|
|
// Math.max(0, Math.min(255, Math.round(Color.green(color) + val / 180f * (Color.green(~color) - Color.green(color))))),
|
|
// Math.max(0, Math.min(255, Math.round(Color.blue(color) + val / 180f * (Color.blue(~color) - Color.blue(color)))))
|
|
// );
|
|
// else if (mColorMode != ColorMode.RAINBOW)
|
|
// runColor = Color.argb(
|
|
// Color.alpha(color),
|
|
// Math.max(0, Math.min(255, Color.red(color) + val)),
|
|
// Math.max(0, Math.min(255, Color.green(color) + val)),
|
|
// Math.max(0, Math.min(255, Color.blue(color) + val))
|
|
// );
|
|
// p.setColorFilter(new PorterDuffColorFilter(runColor, PorterDuff.Mode.SRC_ATOP));
|
|
// invalidate();
|
|
// }
|
|
// if (!mIsCharged) postDelayed(chargingAnim, 33);
|
|
// }
|
|
// };
|
|
//
|
|
// private void startChargingAnim() {
|
|
// post(chargingAnim);
|
|
// }
|
|
//
|
|
// private void stopChargingAnim() {
|
|
// removeCallbacks(chargingAnim);
|
|
// ((ShapeDrawable)getDrawable()).getPaint().setColorFilter(null);
|
|
// invalidate();
|
|
// }
|
|
|
|
private void postUpdate() {
|
|
post(BatteryIndicator.this::update);
|
|
}
|
|
|
|
public void onExpandingChanged(boolean expanded) {
|
|
if (mExpanded == expanded) return;
|
|
mExpanded = expanded;
|
|
update();
|
|
}
|
|
|
|
public void onKeyguardStateChanged(boolean showing) {
|
|
if (mOnKeyguard == showing) return;
|
|
mOnKeyguard = showing;
|
|
update();
|
|
}
|
|
|
|
public void onDarkModeChanged(float intensity, int tintColor) {
|
|
//if (intensity != 0.0f && intensity != 1.0f) return;
|
|
if (mTintColor == tintColor) return;
|
|
mTintColor = tintColor;
|
|
update();
|
|
}
|
|
|
|
public void onBatteryLevelChanged(int powerLevel, boolean isCharging, boolean isCharged) {
|
|
if (this.mPowerLevel == powerLevel && this.mIsBeingCharged == isCharging && !isCharged) return;
|
|
this.mPowerLevel = powerLevel;
|
|
this.mIsBeingCharged = isCharging && !isCharged;
|
|
// if (isCharging != this.mIsCharged) {
|
|
// this.mIsCharged = isCharging;
|
|
// if (!this.mIsCharged)
|
|
// startChargingAnim();
|
|
// else
|
|
// stopChargingAnim();
|
|
// }
|
|
update();
|
|
}
|
|
|
|
public void onPowerSaveChanged(boolean isPowerSave) {
|
|
if (this.mIsPowerSave == isPowerSave) return;
|
|
this.mIsPowerSave = isPowerSave;
|
|
update();
|
|
}
|
|
|
|
public void onExtremePowerSaveChanged(boolean isExtremePowerSave) {
|
|
if (this.mIsExtremePowerSave == isExtremePowerSave ) return;
|
|
this.mIsExtremePowerSave = isExtremePowerSave;
|
|
update();
|
|
}
|
|
|
|
@Override
|
|
protected void onConfigurationChanged(Configuration configuration) {
|
|
super.onConfigurationChanged(configuration);
|
|
updateDisplaySize();
|
|
postUpdate();
|
|
}
|
|
|
|
@Override
|
|
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
|
super.onLayout(changed, left, top, right, bottom);
|
|
if (changed) {
|
|
updateDisplaySize();
|
|
postUpdate();
|
|
}
|
|
}
|
|
|
|
public void update() {
|
|
if (mLimited) this.setVisibility(mExpanded || mOnKeyguard ? mVisibility : View.GONE);
|
|
clearAnimation();
|
|
updateDrawable();
|
|
}
|
|
|
|
public void updateDisplaySize() {
|
|
this.mDisplayWidth = getMeasuredWidth();
|
|
}
|
|
|
|
protected void updateParameters() {
|
|
mColorMode = ColorMode.values()[Integer.parseInt(Helpers.getSharedStringPref(getContext(), "pref_key_system_batteryindicator_color", "1"))];
|
|
mFullColor = Helpers.getSharedIntPref(getContext(), "pref_key_system_batteryindicator_colorval1", Color.GREEN);
|
|
mLowColor = Helpers.getSharedIntPref(getContext(), "pref_key_system_batteryindicator_colorval2", Color.RED);
|
|
mPowerSaveColor = Helpers.getSharedIntPref(getContext(), "pref_key_system_batteryindicator_colorval3", Color.rgb(245, 166, 35));
|
|
mChargingColor = Helpers.getSharedIntPref(getContext(), "pref_key_system_batteryindicator_colorval4", Color.YELLOW);
|
|
mLowLevel = Helpers.getSharedIntPref(getContext(), "pref_key_system_batteryindicator_lowlevel", mLowLevelSystem);
|
|
mHeight = Helpers.getSharedIntPref(getContext(), "pref_key_system_batteryindicator_height", 5);
|
|
mGlow = Helpers.getSharedIntPref(getContext(), "pref_key_system_batteryindicator_glow", 0);
|
|
mRounded = Helpers.getSharedBoolPref(getContext(), "pref_key_system_batteryindicator_rounded", false);
|
|
mBottom = Integer.parseInt(Helpers.getSharedStringPref(getContext(), "pref_key_system_batteryindicator_align", "1")) == 2;
|
|
mCentered = Helpers.getSharedBoolPref(getContext(), "pref_key_system_batteryindicator_centered", false);
|
|
mLimited = Helpers.getSharedBoolPref(getContext(), "pref_key_system_batteryindicator_limitvis", false);
|
|
mTransparency = Helpers.getSharedIntPref(getContext(), "pref_key_system_batteryindicator_transp", 0);
|
|
mPadding = Helpers.getSharedIntPref(getContext(), "pref_key_system_batteryindicator_padding", 0);
|
|
mVisibility = Helpers.getSharedBoolPref(getContext(), "pref_key_system_batteryindicator", false) ? View.VISIBLE : View.GONE;
|
|
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams)getLayoutParams();
|
|
lp.width = ViewGroup.LayoutParams.MATCH_PARENT;
|
|
lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
|
|
lp.gravity = mBottom ? Gravity.BOTTOM : Gravity.TOP;
|
|
setLayoutParams(lp);
|
|
try { this.setImageAlpha(255 - Math.round(255 * mTransparency / 100f)); } catch (Throwable ignore) {};
|
|
this.setVisibility(mVisibility);
|
|
this.setScaleType(mCentered ? ScaleType.CENTER : ScaleType.MATRIX);
|
|
Matrix matrix = new Matrix();
|
|
matrix.setTranslate(0, 0);
|
|
matrix.setScale(1, 1);
|
|
this.setImageMatrix(new Matrix());
|
|
}
|
|
|
|
protected void updateDrawable() {
|
|
try {
|
|
int level = this.mTesting ? this.mTestPowerLevel : this.mPowerLevel;
|
|
int color = this.mFullColor;
|
|
if (!this.mTesting && this.mIsBeingCharged)
|
|
color = this.mChargingColor;
|
|
else if (!this.mTesting && (this.mIsPowerSave || this.mIsExtremePowerSave))
|
|
color = this.mPowerSaveColor;
|
|
else if (level <= this.mLowLevel)
|
|
color = this.mLowColor;
|
|
|
|
ShapeDrawable shape = (ShapeDrawable)getDrawable();
|
|
shape.setShaderFactory(null);
|
|
Paint paint = shape.getPaint();
|
|
paint.setShader(null);
|
|
|
|
if (color == Color.TRANSPARENT && mStatusBar != null)
|
|
try {
|
|
if (mExpanded) {
|
|
color = Color.WHITE;
|
|
} else {
|
|
if (mOnKeyguard) {
|
|
boolean isLightWallpaperStatusBar = (boolean)XposedHelpers.callMethod(XposedHelpers.getObjectField(mStatusBar, "mUpdateMonitor"), "isLightWallpaperStatusBar");
|
|
color = (isLightWallpaperStatusBar ? Color.argb(153, 0, 0, 0) : Color.WHITE);
|
|
} else {
|
|
color = mTintColor;
|
|
}
|
|
}
|
|
} catch (Throwable t) {
|
|
XposedBridge.log(t);
|
|
}
|
|
|
|
int mDisplayPadding = Math.round(mPadding / 100f * this.mDisplayWidth);
|
|
|
|
if (mColorMode == ColorMode.GRADUAL) {
|
|
color = level <= this.mLowLevel || (!this.mTesting && (this.mIsBeingCharged || this.mIsPowerSave || this.mIsExtremePowerSave)) ? color : (int)new ArgbEvaluator().evaluate(1f - (level - this.mLowLevel) / (100f - this.mLowLevel), color, mLowColor);
|
|
} else if (mColorMode == ColorMode.RAINBOW) {
|
|
int steps = 15;
|
|
float jump = 300f / (float)steps;
|
|
float[] pos = new float[steps];
|
|
int[] rainbow = new int[steps];
|
|
for (int i = 0; i < steps; i++) {
|
|
pos[i] = i / (float)(steps - 1);
|
|
float c = (mCentered ? 240 : 0) + jump * i;
|
|
if (c > 360) c -= 360;
|
|
rainbow[i] = Color.HSVToColor(255, new float[]{ c, 1.0f, 1.0f});
|
|
}
|
|
shape.setShaderFactory(new ShapeDrawable.ShaderFactory() {
|
|
@Override
|
|
public Shader resize(int width, int height) {
|
|
if (mCentered)
|
|
return new LinearGradient(width / 2f - (mDisplayWidth - mDisplayPadding * 2) / 2f, height / 2f, (mDisplayWidth - mDisplayPadding * 2), height / 2f, rainbow, pos, Shader.TileMode.CLAMP);
|
|
else
|
|
return new LinearGradient(0, height / 2f, (mDisplayWidth - mDisplayPadding * 2), height / 2f, rainbow, pos, Shader.TileMode.CLAMP);
|
|
}
|
|
});
|
|
}
|
|
paint.setColor(color);
|
|
shape.setShape(mRounded ? new RoundRectShape(new float[] { mHeight, mHeight, mHeight, mHeight, mHeight, mHeight, mHeight, mHeight }, null, null) : new RectShape());
|
|
|
|
int mWidth = Math.round((this.mDisplayWidth - mDisplayPadding * 2) * level / 100f);
|
|
float mDensity = getResources().getDisplayMetrics().density;
|
|
int sbHeight = getResources().getDimensionPixelSize(getResources().getIdentifier("status_bar_height", "dimen", "android"));
|
|
if (mGlow == 0) {
|
|
paint.clearShadowLayer();
|
|
if (mBottom)
|
|
setPadding(mDisplayPadding, 0, mDisplayPadding, -mHeight);
|
|
else
|
|
setPadding(mDisplayPadding, -mHeight, mDisplayPadding, 0);
|
|
shape.setIntrinsicHeight(mHeight * 2);
|
|
shape.setIntrinsicWidth(mWidth);
|
|
} else {
|
|
int shadowPadding = sbHeight - mHeight;
|
|
paint.setShadowLayer(
|
|
(mGlow / 100f) * (sbHeight - 9 * mDensity),
|
|
(mCentered || mDisplayPadding > 0) ? 0 : shadowPadding / 2f,
|
|
mBottom ? mHeight - 10 : 10 - mHeight,
|
|
Color.argb(Math.min(Math.round(mGlow / 100f * 255), Math.round(255 - mTransparency / 100f * 255)), Color.red(color), Color.green(color), Color.blue(color))
|
|
);
|
|
if (mDisplayPadding == 0)
|
|
setPadding(mCentered ? 0 : -shadowPadding, mBottom ? shadowPadding : -shadowPadding, mCentered ? 0 : Math.min(mDisplayWidth - mWidth, shadowPadding), mBottom ? -shadowPadding : shadowPadding);
|
|
else
|
|
setPadding(mDisplayPadding, mBottom ? shadowPadding : -shadowPadding, mDisplayPadding, mBottom ? -shadowPadding : shadowPadding);
|
|
shape.setIntrinsicHeight(sbHeight);
|
|
shape.setIntrinsicWidth(mWidth + (mCentered ? 0 : (mDisplayPadding == 0 ? shadowPadding : 0)));
|
|
}
|
|
|
|
invalidate();
|
|
} catch (Throwable t) {
|
|
XposedBridge.log(t);
|
|
}
|
|
}
|
|
|
|
} |