Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4b786ff4 authored by John Spurlock's avatar John Spurlock
Browse files

Battery meter: remove bolt color compromise & improve pct.

 - Bolt remains opaque (white) below a threshold level, otherwise
   transparent.
 - Draw the entire shape using a path, removing the need for a
   software layer.
 - Use a similar approach to make the percentage text readable,
   but this still requires a software layer (since text is involved).

Bug: 12131168
Change-Id: Ifde5e99121155bf1be171f44b2c80c116b17c9e7
parent bcf40bcd
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@
    <color name="notification_panel_scrim_color">#B0000000</color>
    <color name="batterymeter_frame_color">#66FFFFFF</color><!-- 40% white -->
    <color name="batterymeter_charge_color">#FFFFFFFF</color>
    <color name="batterymeter_bolt_color">#B2000000</color><!-- 70% black -->
    <color name="batterymeter_bolt_color">#FFFFFFFF</color>
    <color name="status_bar_clock_color">#FFFFFFFF</color>
    <drawable name="notification_item_background_color">#ff111111</drawable>
    <drawable name="notification_item_background_color_pressed">#ff454545</drawable>
+93 −56
Original line number Diff line number Diff line
@@ -39,20 +39,20 @@ public class BatteryMeterView extends View implements DemoMode {
    public static final String TAG = BatteryMeterView.class.getSimpleName();
    public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST";

    public static final boolean ENABLE_PERCENT = true;
    public static final boolean SINGLE_DIGIT_PERCENT = false;
    public static final boolean SHOW_100_PERCENT = false;
    private static final boolean ENABLE_PERCENT = true;
    private static final boolean SINGLE_DIGIT_PERCENT = false;
    private static final boolean SHOW_100_PERCENT = false;

    public static final int FULL = 96;
    public static final int EMPTY = 4;
    private static final int FULL = 96;
    private static final int EMPTY = 4;

    public static final float SUBPIXEL = 0.4f;  // inset rects for softer edges
    private static final float SUBPIXEL = 0.4f;  // inset rects for softer edges
    private static final float BOLT_LEVEL_THRESHOLD = 0.3f;  // opaque bolt below this fraction

    int[] mColors;
    private final int[] mColors;

    boolean mShowPercent = true;
    Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint;
    int mButtonHeight;
    private final Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint;
    private float mTextHeight, mWarningTextHeight;

    private int mHeight;
@@ -64,9 +64,11 @@ public class BatteryMeterView extends View implements DemoMode {

    private final RectF mFrame = new RectF();
    private final RectF mButtonFrame = new RectF();
    private final RectF mClipFrame = new RectF();
    private final RectF mBoltFrame = new RectF();

    private final Path mShapePath = new Path();
    private final Path mClipPath = new Path();

    private class BatteryTracker extends BroadcastReceiver {
        public static final int UNKNOWN_LEVEL = -1;

@@ -188,7 +190,9 @@ public class BatteryMeterView extends View implements DemoMode {
        colors.recycle();
        mShowPercent = ENABLE_PERCENT && 0 != Settings.System.getInt(
                context.getContentResolver(), "status_bar_show_battery_percent", 0);

        if (mShowPercent) {
            setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        }
        mWarningString = context.getString(R.string.battery_meter_very_low_overlay_symbol);

        mFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
@@ -196,7 +200,6 @@ public class BatteryMeterView extends View implements DemoMode {
        mFramePaint.setDither(true);
        mFramePaint.setStrokeWidth(0);
        mFramePaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mFramePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));

        mBatteryPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBatteryPaint.setDither(true);
@@ -204,8 +207,7 @@ public class BatteryMeterView extends View implements DemoMode {
        mBatteryPaint.setStyle(Paint.Style.FILL_AND_STROKE);

        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint.setColor(0xFFFFFFFF);
        Typeface font = Typeface.create("sans-serif-condensed", Typeface.NORMAL);
        Typeface font = Typeface.create("sans-serif-condensed", Typeface.BOLD);
        mTextPaint.setTypeface(font);
        mTextPaint.setTextAlign(Paint.Align.CENTER);

@@ -217,11 +219,9 @@ public class BatteryMeterView extends View implements DemoMode {

        mChargeColor = getResources().getColor(R.color.batterymeter_charge_color);

        mBoltPaint = new Paint();
        mBoltPaint.setAntiAlias(true);
        mBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBoltPaint.setColor(res.getColor(R.color.batterymeter_bolt_color));
        mBoltPoints = loadBoltPoints(res);
        setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }

    private static float[] loadBoltPoints(Resources res) {
@@ -269,36 +269,34 @@ public class BatteryMeterView extends View implements DemoMode {
        final int pl = getPaddingLeft();
        final int pr = getPaddingRight();
        final int pb = getPaddingBottom();
        int height = mHeight - pt - pb;
        int width = mWidth - pl - pr;
        final int height = mHeight - pt - pb;
        final int width = mWidth - pl - pr;

        mButtonHeight = (int) (height * 0.12f);
        final int buttonHeight = (int) (height * 0.12f);

        mFrame.set(0, 0, width, height);
        mFrame.offset(pl, pt);

        // button-frame: area above the battery body
        mButtonFrame.set(
                mFrame.left + width * 0.25f,
                mFrame.top,
                mFrame.right - width * 0.25f,
                mFrame.top + mButtonHeight + 5 /*cover frame border of intersecting area*/);
                mFrame.top + buttonHeight);

        mButtonFrame.top += SUBPIXEL;
        mButtonFrame.left += SUBPIXEL;
        mButtonFrame.right -= SUBPIXEL;

        mFrame.top += mButtonHeight;
        // frame: battery body area
        mFrame.top += buttonHeight;
        mFrame.left += SUBPIXEL;
        mFrame.top += SUBPIXEL;
        mFrame.right -= SUBPIXEL;
        mFrame.bottom -= SUBPIXEL;

        // first, draw the battery shape
        c.drawRect(mFrame, mFramePaint);

        // fill 'er up
        final int color = tracker.plugged ? mChargeColor : getColorForLevel(level);
        mBatteryPaint.setColor(color);
        // set the battery charging color
        mBatteryPaint.setColor(tracker.plugged ? mChargeColor : getColorForLevel(level));

        if (level >= FULL) {
            drawFrac = 1f;
@@ -306,18 +304,23 @@ public class BatteryMeterView extends View implements DemoMode {
            drawFrac = 0f;
        }

        c.drawRect(mButtonFrame, drawFrac == 1f ? mBatteryPaint : mFramePaint);

        mClipFrame.set(mFrame);
        mClipFrame.top += (mFrame.height() * (1f - drawFrac));

        c.save(Canvas.CLIP_SAVE_FLAG);
        c.clipRect(mClipFrame);
        c.drawRect(mFrame, mBatteryPaint);
        c.restore();
        final float levelTop = drawFrac == 1f ? mButtonFrame.top
                : (mFrame.top + (mFrame.height() * (1f - drawFrac)));

        // define the battery shape
        mShapePath.reset();
        mShapePath.moveTo(mButtonFrame.left, mButtonFrame.top);
        mShapePath.lineTo(mButtonFrame.right, mButtonFrame.top);
        mShapePath.lineTo(mButtonFrame.right, mFrame.top);
        mShapePath.lineTo(mFrame.right, mFrame.top);
        mShapePath.lineTo(mFrame.right, mFrame.bottom);
        mShapePath.lineTo(mFrame.left, mFrame.bottom);
        mShapePath.lineTo(mFrame.left, mFrame.top);
        mShapePath.lineTo(mButtonFrame.left, mFrame.top);
        mShapePath.lineTo(mButtonFrame.left, mButtonFrame.top);

        if (tracker.plugged) {
            // draw the bolt
            // define the bolt shape
            final float bl = mFrame.left + mFrame.width() / 4.5f;
            final float bt = mFrame.top + mFrame.height() / 6f;
            final float br = mFrame.right - mFrame.width() / 7f;
@@ -338,12 +341,37 @@ public class BatteryMeterView extends View implements DemoMode {
                        mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(),
                        mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height());
            }

            float boltPct = (mBoltFrame.bottom - levelTop) / (mBoltFrame.bottom - mBoltFrame.top);
            boltPct = Math.min(Math.max(boltPct, 0), 1);
            if (boltPct <= BOLT_LEVEL_THRESHOLD) {
                // draw the bolt if opaque
                c.drawPath(mBoltPath, mBoltPaint);
        } else if (level <= EMPTY) {
            } else {
                // otherwise cut the bolt out of the overall shape
                mShapePath.op(mBoltPath, Path.Op.DIFFERENCE);
            }
        }

        // draw the battery shape background
        c.drawPath(mShapePath, mFramePaint);

        // draw the battery shape, clipped to charging level
        mFrame.top = levelTop;
        mClipPath.reset();
        mClipPath.addRect(mFrame,  Path.Direction.CCW);
        mShapePath.op(mClipPath, Path.Op.INTERSECT);
        c.drawPath(mShapePath, mBatteryPaint);

        if (!tracker.plugged) {
            if (level <= EMPTY) {
                // draw the warning text
                final float x = mWidth * 0.5f;
                final float y = (mHeight + mWarningTextHeight) * 0.48f;
                c.drawText(mWarningString, x, y, mWarningTextPaint);
            } else if (mShowPercent && !(tracker.level == 100 && !SHOW_100_PERCENT)) {
                // draw the percentage text
                mTextPaint.setColor(getColorForLevel(level));
                mTextPaint.setTextSize(height *
                        (SINGLE_DIGIT_PERCENT ? 0.75f
                                : (tracker.level == 100 ? 0.38f : 0.5f)));
@@ -352,12 +380,21 @@ public class BatteryMeterView extends View implements DemoMode {
                final String str = String.valueOf(SINGLE_DIGIT_PERCENT ? (level/10) : level);
                final float x = mWidth * 0.5f;
                final float y = (mHeight + mTextHeight) * 0.47f;

                boolean opaque = levelTop > y;
                if (opaque) {
                    mTextPaint.setXfermode(null);
                } else {
                    mTextPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
                }

                c.drawText(str,
                        x,
                        y,
                        mTextPaint);
            }
        }
    }

    private boolean mDemoMode;
    private BatteryTracker mDemoTracker = new BatteryTracker();