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

Commit 62d5fccd authored by Sven Dawitz's avatar Sven Dawitz
Browse files

Added "Rotary revamped" and "Lense" lockscreen style.

    This patch was a team effort by me and
    Stefano Pignataro (Drakknar on xda)
    who initiated this and did all the
    grafics involved. Thanks mate!

    - Added revamped rotary lockscreen which looks
      much more polished
    - Added lense lockscreen (simple drop down
      as known from other roms)
    - Fixed landscape lockscreen for new styles
    - Fixed clipping issue - drag down now looks flawless
    - Modified lense style - it contains the date and time
      on the slider now - everything else is invisible
      -> only applies in portrait - in landscape no date/time
      on slider since impossible to read
    - Scaled lense in landscape for the ****ing status bar
    - Postioned buttons in landscape for the ****ing status bar
    - Modified default style to rotary revamped
    - added supported for user modifed density in build.prop
    - tested mdpi+hdpi both portrait+landscape (thx emulator!)

    Screenshots for easy preview:
    https://picasaweb.google.com/Dave.Astator/Cm7RotaryRevamped#

Change-Id: I9d24678a35b8ae1903412f0fa1cd0e4450e800a9
parent eac7b0af
Loading
Loading
Loading
Loading
+196 −27
Original line number Diff line number Diff line
@@ -16,23 +16,31 @@

package com.android.internal.widget;

import java.util.Date;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.drawable.Drawable;
import android.graphics.Typeface;
import android.os.Vibrator;
import android.text.format.DateFormat;
import android.text.format.Time;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.view.animation.DecelerateInterpolator;

import static android.view.animation.AnimationUtils.currentAnimationTimeMillis;
import com.android.internal.R;

@@ -55,6 +63,9 @@ public class RotarySelector extends View {

    private float mDensity;

    // Stores a scale factor for user modified density via build.prop
    private float mDensityScaleFactor=1;

    // UI elements
    private Bitmap mBackground;
    private Bitmap mDimple;
@@ -82,8 +93,16 @@ public class RotarySelector extends View {
    private int mEventStartY;
    // controls display of custom app dimple
    private boolean mCustomAppDimple=false;
    // size of the status bar for resizing the background
    private int mStatusBarSize=0;
    // backgrond Scale for landscape mode with status bar in our way
    private float mStatusBarScale=1;
    // controls hiding of directional arrows
    private boolean mHideArrows=false;
    // are we in lense mode?
    private boolean mLenseMode=false;
    // are we in rotary revamped mode?
    private boolean mRevampedMode=false;

    // state of the animation used to bring the handle back to its start position when
    // the user lets go before triggering an action
@@ -99,10 +118,12 @@ public class RotarySelector extends View {
    private DecelerateInterpolator mInterpolator;

    private Paint mPaint = new Paint();
    private Paint mLensePaint = new Paint ();

    // used to rotate the background and arrow assets depending on orientation
    final Matrix mBgMatrix = new Matrix();
    final Matrix mArrowMatrix = new Matrix();
    final Matrix drawMatrix = new Matrix();

    /**
     * If the user is currently dragging something.
@@ -113,6 +134,13 @@ public class RotarySelector extends View {
    public static final int MID_HANDLE_GRABBED = 2;
    public static final int RIGHT_HANDLE_GRABBED = 3;

    /**
     * Static status bar sizes for ldpi/mdpi/hdpi
     */
    private static final int STATUS_BAR_HEIGHT_LDPI = 19;
    private static final int STATUS_BAR_HEIGHT_MDPI = 25;
    private static final int STATUS_BAR_HEIGHT_HDPI = 38;

    /**
     * Whether the user has triggered something (e.g dragging the left handle all the way over to
     * the right).
@@ -147,6 +175,8 @@ public class RotarySelector extends View {
    static final int ROTARY_STROKE_WIDTH_DIP = 83;
    static final int SNAP_BACK_ANIMATION_DURATION_MILLIS = 300;
    static final int SPIN_ANIMATION_DURATION_MILLIS = 800;
    static final int LENSE_DATE_SIZE_DIP = 18;
    static final int LENSE_TIME_SIZE_DIP = 30;

    private int mEdgeTriggerThresh;
    private int mDimpleWidth;
@@ -172,6 +202,12 @@ public class RotarySelector extends View {
     */
    private int mOrientation;

    /**
     * the deleted Margin from xml layout - fixes clipping
     */
    private int mMarginBottom=0;

    private String mDateFormatString;

    public RotarySelector(Context context) {
        this(context, null);
@@ -190,6 +226,21 @@ public class RotarySelector extends View {

        Resources r = getResources();
        mDensity = r.getDisplayMetrics().density;
        int densityDpi;
        densityDpi = r.getDisplayMetrics().densityDpi;

        /*
         * this hack assumes people change build.prop for increasing
         * the virtual size of their screen by decreasing dpi in
         * build.prop file. this is often done especially for hd
         * phones. keep in mind changing build.prop and density
         * isnt officially supported, but this should do for most cases
         */
        if(densityDpi < 240 && densityDpi >160)
            mDensityScaleFactor=(float)(240.0 / densityDpi);
        if(densityDpi < 160 && densityDpi >120)
            mDensityScaleFactor=(float)(160.0 / densityDpi);

        if (DBG) log("- Density: " + mDensity);

        // Assets (all are BitmapDrawables).
@@ -210,12 +261,44 @@ public class RotarySelector extends View {

        mBackgroundWidth = mBackground.getWidth();
        mBackgroundHeight = mBackground.getHeight();
        mOuterRadius = (int) (mDensity * OUTER_ROTARY_RADIUS_DIP);
        mInnerRadius = (int) ((OUTER_ROTARY_RADIUS_DIP - ROTARY_STROKE_WIDTH_DIP) * mDensity);
        mOuterRadius = (int) (mDensity * mDensityScaleFactor * OUTER_ROTARY_RADIUS_DIP);
        mInnerRadius = (int) ((OUTER_ROTARY_RADIUS_DIP - ROTARY_STROKE_WIDTH_DIP) * mDensity * mDensityScaleFactor);

        final ViewConfiguration configuration = ViewConfiguration.get(mContext);
        mMinimumVelocity = configuration.getScaledMinimumFlingVelocity() * 2;
        mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();

        mMarginBottom = (int)(60 * mDensity * mDensityScaleFactor);

        mLensePaint.setColor(Color.BLACK);
        mLensePaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mLensePaint.setTextAlign(Paint.Align.CENTER);
        mLensePaint.setFlags(Typeface.BOLD);

        // get status bar size in every possible orientation
        DisplayMetrics displayMetrics = new DisplayMetrics();
        ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(displayMetrics);

        switch (displayMetrics.densityDpi) {
            case DisplayMetrics.DENSITY_HIGH:
                mStatusBarSize = STATUS_BAR_HEIGHT_HDPI;
                break;
            case DisplayMetrics.DENSITY_MEDIUM:
                mStatusBarSize = STATUS_BAR_HEIGHT_MDPI;
                break;
            case DisplayMetrics.DENSITY_LOW:
                mStatusBarSize = STATUS_BAR_HEIGHT_LDPI;
                break;
            default:
                mStatusBarSize = STATUS_BAR_HEIGHT_HDPI;
        }

        // set up the scale in landscape mode
        if(!isHoriz()){
            mStatusBarScale = (float) ((mBackgroundWidth - mStatusBarSize) / (float)mBackgroundWidth);
        }

        mDateFormatString = context.getString(R.string.full_wday_month_day_no_year);
    }

    private Bitmap getBitmapFor(int resId) {
@@ -235,12 +318,16 @@ public class RotarySelector extends View {

        // bg matrix only needs to be calculated once
        mBgMatrix.setTranslate(0, 0);
        mBgMatrix.postScale(mDensityScaleFactor, mDensityScaleFactor);
        if (!isHoriz()) {
            // set up matrix for translating drawing of background and arrow assets
            final int left = w - mBackgroundHeight;
            mBgMatrix.preRotate(-90, 0, 0);
            if(mLenseMode){
                mBgMatrix.postTranslate(left, h + mStatusBarSize);
                mBgMatrix.postScale(1, mStatusBarScale);
            }else
                mBgMatrix.postTranslate(left, h);

        } else {
            mBgMatrix.postTranslate(0, h - mBackgroundHeight);
        }
@@ -308,7 +395,7 @@ public class RotarySelector extends View {
        // this works because the arrows are drawn from the top, and the rotary bg is drawn
        // from the bottom.

        final int height = mBackgroundHeight + arrowH - arrowScrunch;
        final int height = mBackgroundHeight + arrowH - arrowScrunch + mMarginBottom;

        if (isHoriz()) {
            setMeasuredDimension(length, height);
@@ -342,9 +429,30 @@ public class RotarySelector extends View {
        }

        // Background:
        mBgMatrix.setTranslate(0, (float)(mRotaryOffsetY + bgTop));
        canvas.drawBitmap(mBackground, mBgMatrix, mPaint);
        mBgMatrix.setTranslate(0, - (float)(mRotaryOffsetY + bgTop));
        drawMatrix.set(mBgMatrix);
        if (isHoriz())
            drawMatrix.postTranslate(0, (float) mRotaryOffsetY - mMarginBottom);
        else
            drawMatrix.postTranslate((float) mRotaryOffsetY - mMarginBottom, 0);
        canvas.drawBitmap(mBackground, drawMatrix, mPaint);

        // for lense mode, we are done after time and date
        if(mLenseMode){
            if(isHoriz()){
                Time mTime = new Time();
                mTime.setToNow();

                String mTimeString=mTime.format("%R");
                String mDate=(String) DateFormat.format(mDateFormatString, new Date());

                canvas.translate(0, 0);
                mLensePaint.setTextSize(LENSE_TIME_SIZE_DIP * mDensity * mDensityScaleFactor);
                canvas.drawText(mTimeString, mBackgroundWidth / 2 * mDensityScaleFactor, mRotaryOffsetY + mMarginBottom + LENSE_TIME_SIZE_DIP * mDensity, mLensePaint);
                mLensePaint.setTextSize(LENSE_DATE_SIZE_DIP * mDensity * mDensityScaleFactor);
                canvas.drawText(mDate, mBackgroundWidth / 2 * mDensityScaleFactor, mRotaryOffsetY + mMarginBottom + LENSE_DATE_SIZE_DIP * mDensity * 3, mLensePaint);
            }
            return;
        }

        // Draw the correct arrow(s) depending on the current state:
        if (!mHideArrows) {
@@ -355,6 +463,7 @@ public class RotarySelector extends View {
                    break;
                case LEFT_HANDLE_GRABBED:
                    mArrowMatrix.setTranslate(0, 0);
                    mArrowMatrix.postScale(mDensityScaleFactor, mDensityScaleFactor);
                    if (!isHoriz()) {
                        mArrowMatrix.preRotate(-90, 0, 0);
                        mArrowMatrix.postTranslate(0, height);
@@ -363,6 +472,7 @@ public class RotarySelector extends View {
                    break;
                case MID_HANDLE_GRABBED:
                    mArrowMatrix.setTranslate(0, 0);
                    mArrowMatrix.postScale(mDensityScaleFactor, mDensityScaleFactor);
                    if (!isHoriz()) {
                        mArrowMatrix.preRotate(-90, 0, 0);
                    }
@@ -378,6 +488,7 @@ public class RotarySelector extends View {
                    break;
                case RIGHT_HANDLE_GRABBED:
                    mArrowMatrix.setTranslate(0, 0);
                    mArrowMatrix.postScale(mDensityScaleFactor, mDensityScaleFactor);
                    if (!isHoriz()) {
                        mArrowMatrix.preRotate(-90, 0, 0);
                        // since bg width is > height of screen in landscape mode...
@@ -404,7 +515,8 @@ public class RotarySelector extends View {

        // left dimple / icon
        {
            final int xOffset = mLeftHandleX + mRotaryOffsetX;
            int xOffset = mLeftHandleX + mRotaryOffsetX;
            if(!isHoriz()) xOffset = xOffset + mStatusBarSize/2;
            final int drawableY = getYOnArc(
                    mBackgroundWidth,
                    mInnerRadius,
@@ -412,7 +524,8 @@ public class RotarySelector extends View {
                    xOffset);
            final int x = isHoriz() ? xOffset : drawableY + bgTop;
            final int y = isHoriz() ? drawableY + bgTop : height - xOffset;
            if (mGrabbedState != RIGHT_HANDLE_GRABBED) {
            if (mRevampedMode || (mGrabbedState != RIGHT_HANDLE_GRABBED
                    && mGrabbedState != MID_HANDLE_GRABBED)) {
                drawCentered(mDimple, canvas, x, y);
                drawCentered(mLeftHandleIcon, canvas, x, y);
            } else {
@@ -422,7 +535,8 @@ public class RotarySelector extends View {

        // center dimple / icon
        {
            final int xOffset = mMidHandleX + mRotaryOffsetX;
            int xOffset = mMidHandleX + mRotaryOffsetX;
            if(!isHoriz()) xOffset = xOffset + mStatusBarSize/2;
            final int drawableY = getYOnArc(
                    mBackgroundWidth,
                    mInnerRadius,
@@ -430,7 +544,8 @@ public class RotarySelector extends View {
                    xOffset);
            final int x = isHoriz() ? xOffset : drawableY + bgTop;
            final int y = isHoriz() ? drawableY + bgTop : height - xOffset;
            if (mGrabbedState != LEFT_HANDLE_GRABBED && mGrabbedState != RIGHT_HANDLE_GRABBED && mCustomAppDimple) {
            if ((mRevampedMode || (mGrabbedState != LEFT_HANDLE_GRABBED
                    && mGrabbedState != RIGHT_HANDLE_GRABBED)) && mCustomAppDimple) {
                drawCentered(mDimple, canvas, x, y);
                drawCentered(mMidHandleIcon, canvas, x, y);
            } else {
@@ -440,16 +555,17 @@ public class RotarySelector extends View {

        // right dimple / icon
        {
            final int xOffset = mRightHandleX + mRotaryOffsetX;
            int xOffset = mRightHandleX + mRotaryOffsetX;
            if(!isHoriz()) xOffset = xOffset + mStatusBarSize/2;
            final int drawableY = getYOnArc(
                    mBackgroundWidth,
                    mInnerRadius,
                    mOuterRadius,
                    xOffset);

            final int x = isHoriz() ? xOffset : drawableY + bgTop;
            final int y = isHoriz() ? drawableY + bgTop : height - xOffset;
            if (mGrabbedState != LEFT_HANDLE_GRABBED) {
            if (mRevampedMode || (mGrabbedState != LEFT_HANDLE_GRABBED
                    && mGrabbedState != MID_HANDLE_GRABBED)) {
                drawCentered(mDimple, canvas, x, y);
                drawCentered(mRightHandleIcon, canvas, x, y);
            } else {
@@ -459,6 +575,7 @@ public class RotarySelector extends View {

        // draw extra left hand dimples
        int dimpleLeft = mRotaryOffsetX + mLeftHandleX - mDimpleSpacing;
        if(!isHoriz()) dimpleLeft = dimpleLeft + mStatusBarSize/2;
        while (dimpleLeft > -halfdimple) {
            final int drawableY = getYOnArc(
                    mBackgroundWidth,
@@ -476,6 +593,7 @@ public class RotarySelector extends View {

        // draw extra middle dimples
        int dimpleMid = mRotaryOffsetX + mMidHandleX + mDimpleSpacing;
        if(!isHoriz()) dimpleMid = dimpleMid + mStatusBarSize/2;
        final int midThresh = mMidHandleX + halfdimple;
        while (dimpleMid < midThresh) {
            final int drawableY = getYOnArc(
@@ -494,6 +612,7 @@ public class RotarySelector extends View {

        // draw extra right hand dimples
        int dimpleRight = mRotaryOffsetX + mRightHandleX + mDimpleSpacing;
        if(!isHoriz()) dimpleRight = dimpleRight + mStatusBarSize/2;
        final int rightThresh = mRight + halfdimple;
        while (dimpleRight < rightThresh) {
            final int drawableY = getYOnArc(
@@ -533,7 +652,7 @@ public class RotarySelector extends View {
        final int middleRadius = innerRadius + halfWidth;

        // the bottom leg of the triangle
        final int triangleBottom = (backgroundWidth / 2) - x;
        final int triangleBottom = (int) ((backgroundWidth / 2.0 * mDensityScaleFactor) - x);

        // "Our offense is like the pythagorean theorem: There is no answer!" - Shaquille O'Neal
        final int triangleY =
@@ -543,7 +662,7 @@ public class RotarySelector extends View {
        // middleRadius - triangleY =
        //   the vertical distance from the outer edge of the circle to the desired point
        // from there we add the distance from the top of the drawable to the middle circle
        return middleRadius - triangleY + halfWidth + mRotaryOffsetY;
        return middleRadius - triangleY + halfWidth + mRotaryOffsetY - mMarginBottom;
    }

    /**
@@ -570,9 +689,9 @@ public class RotarySelector extends View {
                height - ((int) event.getY());
        final int eventY = isHoriz() ?
                (int) event.getY():
                width - ((int) event.getY());
                width - ((int) event.getX());
        final int hitWindow = mDimpleWidth;
        final int downThresh = (isHoriz() ? width : height) - mDimpleWidth;
        final int downThresh = mDimpleWidth * 2;

        final int action = event.getAction();
        switch (action) {
@@ -584,6 +703,12 @@ public class RotarySelector extends View {
                    reset();
                    invalidate();
                }
                if (mLenseMode){
                    setGrabbedState(MID_HANDLE_GRABBED);
                    invalidate();
                    vibrate(VIBRATE_SHORT);
                    break;
                }
                if (eventX < mLeftHandleX + hitWindow) {
                    mRotaryOffsetX = eventX - mLeftHandleX;
                    setGrabbedState(LEFT_HANDLE_GRABBED);
@@ -625,16 +750,23 @@ public class RotarySelector extends View {
                                mDimplesOfFling * mDimpleSpacing,
                                velocity);
                    }
                } else if (mGrabbedState == MID_HANDLE_GRABBED && mCustomAppDimple) {
                } else if (mGrabbedState == MID_HANDLE_GRABBED && (mCustomAppDimple || mLenseMode)) {
                    mRotaryOffsetY = eventY - mEventStartY;
                    if (!isHoriz())
                        mRotaryOffsetY = mEventStartY - eventY;
                    if (mRotaryOffsetY < 0) mRotaryOffsetY=0;
                    invalidate();

                    if (mRotaryOffsetY >= mDimpleWidth * 2 && !mTriggered) {
                    if (Math.abs(mRotaryOffsetY) >= downThresh && !mTriggered) {
                        mTriggered = true;
                        // lense mode is handled as "middle dimple" for up/down movement, yet we need to emit left handle for unlock
                        if(mLenseMode)
                            dispatchTriggerEvent(OnDialTriggerListener.LEFT_HANDLE);
                        else
                            dispatchTriggerEvent(OnDialTriggerListener.MID_HANDLE);
                        // set up "flow up" animation
                        startAnimationUp(eventY - mEventStartY, 0, SNAP_BACK_ANIMATION_DURATION_MILLIS);
                        int delta = (isHoriz() ? eventY - mEventStartY : mEventStartY - eventY);
                        startAnimationUp(delta, 0, SNAP_BACK_ANIMATION_DURATION_MILLIS);
                    }
                } else if (mGrabbedState == RIGHT_HANDLE_GRABBED) {
                    mRotaryOffsetX = eventX - mRightHandleX;
@@ -665,10 +797,11 @@ public class RotarySelector extends View {
                        && Math.abs(eventX - mLeftHandleX) > 5) {
                    // set up "snap back" animation
                    startAnimation(eventX - mLeftHandleX, 0, SNAP_BACK_ANIMATION_DURATION_MILLIS);
                } else if (mGrabbedState == MID_HANDLE_GRABBED && mCustomAppDimple
                        && eventY - mEventStartY > 5) {
                } else if (mGrabbedState == MID_HANDLE_GRABBED) {
                    // set up "flow up" animation
                    startAnimationUp(eventY - mEventStartY, 0, SNAP_BACK_ANIMATION_DURATION_MILLIS);
                    int delta = (isHoriz() ? eventY - mEventStartY : mEventStartY - eventY);
                    if (delta > 5)
                        startAnimationUp(delta, 0, SNAP_BACK_ANIMATION_DURATION_MILLIS);
                } else if (mGrabbedState == RIGHT_HANDLE_GRABBED
                        && Math.abs(eventX - mRightHandleX) > 5) {
                    // set up "snap back" animation
@@ -890,6 +1023,42 @@ public class RotarySelector extends View {
        mHideArrows=newState;
    }

    /**
     * Sets up the original rotary style - called from InCallTouchUi.java only
     */
    public void setRotary(boolean newState){
        if(newState){
            mBackground = getBitmapFor(R.drawable.jog_dial_bg);
            mDimple = getBitmapFor(R.drawable.jog_dial_dimple);
            mDimpleDim = getBitmapFor(R.drawable.jog_dial_dimple_dim);
        }
    }

    /**
     * Sets up the rotary revamped style - called from LockScreen.java and InCallTouchUi.java
     */
    public void setRevamped(boolean newState){
        if(newState){
            if(mCustomAppDimple)
                mBackground = getBitmapFor(R.drawable.jog_dial_bg_rev_down);
            else
                mBackground = getBitmapFor(R.drawable.jog_dial_bg_rev);
            mDimple = getBitmapFor(R.drawable.jog_dial_dimple_rev);
            mDimpleDim = getBitmapFor(R.drawable.jog_dial_dimple_dim_rev);
        }
        mRevampedMode=newState;
    }

    /**
     * Sets up the lense square style - called from LockScreen.java and InCallTouchUi.java
     */
    public void setLenseSquare(boolean newState){
        mLenseMode=false;
        if(newState){
            mLenseMode=true;
            mBackground = getBitmapFor(R.drawable.lense_square_bg);
        }
    }

    // Debugging / testing code

+18.3 KiB
Loading image diff...
+18.4 KiB
Loading image diff...
+3.37 KiB
Loading image diff...
+4.18 KiB
Loading image diff...
Loading