Home | History | Annotate | Download | only in stackdivider
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.systemui.stackdivider;
     18 
     19 import android.animation.Animator;
     20 import android.animation.AnimatorListenerAdapter;
     21 import android.animation.AnimatorSet;
     22 import android.animation.ObjectAnimator;
     23 import android.annotation.Nullable;
     24 import android.content.Context;
     25 import android.graphics.Canvas;
     26 import android.graphics.Paint;
     27 import android.util.AttributeSet;
     28 import android.util.Property;
     29 import android.view.View;
     30 
     31 import com.android.systemui.Interpolators;
     32 import com.android.systemui.R;
     33 
     34 /**
     35  * View for the handle in the docked stack divider.
     36  */
     37 public class DividerHandleView extends View {
     38 
     39     private final static Property<DividerHandleView, Integer> WIDTH_PROPERTY
     40             = new Property<DividerHandleView, Integer>(Integer.class, "width") {
     41 
     42         @Override
     43         public Integer get(DividerHandleView object) {
     44             return object.mCurrentWidth;
     45         }
     46 
     47         @Override
     48         public void set(DividerHandleView object, Integer value) {
     49             object.mCurrentWidth = value;
     50             object.invalidate();
     51         }
     52     };
     53 
     54     private final static Property<DividerHandleView, Integer> HEIGHT_PROPERTY
     55             = new Property<DividerHandleView, Integer>(Integer.class, "height") {
     56 
     57         @Override
     58         public Integer get(DividerHandleView object) {
     59             return object.mCurrentHeight;
     60         }
     61 
     62         @Override
     63         public void set(DividerHandleView object, Integer value) {
     64             object.mCurrentHeight = value;
     65             object.invalidate();
     66         }
     67     };
     68 
     69     private final Paint mPaint = new Paint();
     70     private final int mWidth;
     71     private final int mHeight;
     72     private final int mCircleDiameter;
     73     private int mCurrentWidth;
     74     private int mCurrentHeight;
     75     private AnimatorSet mAnimator;
     76     private boolean mTouching;
     77 
     78     public DividerHandleView(Context context, @Nullable AttributeSet attrs) {
     79         super(context, attrs);
     80         mPaint.setColor(getResources().getColor(R.color.docked_divider_handle, null));
     81         mPaint.setAntiAlias(true);
     82         mWidth = getResources().getDimensionPixelSize(R.dimen.docked_divider_handle_width);
     83         mHeight = getResources().getDimensionPixelSize(R.dimen.docked_divider_handle_height);
     84         mCurrentWidth = mWidth;
     85         mCurrentHeight = mHeight;
     86         mCircleDiameter = (mWidth + mHeight) / 3;
     87     }
     88 
     89     public void setTouching(boolean touching, boolean animate) {
     90         if (touching == mTouching) {
     91             return;
     92         }
     93         if (mAnimator != null) {
     94             mAnimator.cancel();
     95             mAnimator = null;
     96         }
     97         if (!animate) {
     98             if (touching) {
     99                 mCurrentWidth = mCircleDiameter;
    100                 mCurrentHeight = mCircleDiameter;
    101             } else {
    102                 mCurrentWidth = mWidth;
    103                 mCurrentHeight = mHeight;
    104             }
    105             invalidate();
    106         } else {
    107             animateToTarget(touching ? mCircleDiameter : mWidth,
    108                     touching ? mCircleDiameter : mHeight, touching);
    109         }
    110         mTouching = touching;
    111     }
    112 
    113     private void animateToTarget(int targetWidth, int targetHeight, boolean touching) {
    114         ObjectAnimator widthAnimator = ObjectAnimator.ofInt(this, WIDTH_PROPERTY,
    115                 mCurrentWidth, targetWidth);
    116         ObjectAnimator heightAnimator = ObjectAnimator.ofInt(this, HEIGHT_PROPERTY,
    117                 mCurrentHeight, targetHeight);
    118         mAnimator = new AnimatorSet();
    119         mAnimator.playTogether(widthAnimator, heightAnimator);
    120         mAnimator.setDuration(touching
    121                 ? DividerView.TOUCH_ANIMATION_DURATION
    122                 : DividerView.TOUCH_RELEASE_ANIMATION_DURATION);
    123         mAnimator.setInterpolator(touching
    124                 ? Interpolators.TOUCH_RESPONSE
    125                 : Interpolators.FAST_OUT_SLOW_IN);
    126         mAnimator.addListener(new AnimatorListenerAdapter() {
    127             @Override
    128             public void onAnimationEnd(Animator animation) {
    129                 mAnimator = null;
    130             }
    131         });
    132         mAnimator.start();
    133     }
    134 
    135     @Override
    136     protected void onDraw(Canvas canvas) {
    137         int left = getWidth() / 2 - mCurrentWidth / 2;
    138         int top = getHeight() / 2 - mCurrentHeight / 2;
    139         int radius = Math.min(mCurrentWidth, mCurrentHeight) / 2;
    140         canvas.drawRoundRect(left, top, left + mCurrentWidth, top + mCurrentHeight,
    141                 radius, radius, mPaint);
    142     }
    143 
    144     @Override
    145     public boolean hasOverlappingRendering() {
    146         return false;
    147     }
    148 }
    149