1514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi/* 2514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * Copyright (C) 2015 The Android Open Source Project 3514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * 4514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License"); 5514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * you may not use this file except in compliance with the License. 6514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * You may obtain a copy of the License at 7514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * 8514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * http://www.apache.org/licenses/LICENSE-2.0 9514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * 10514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * Unless required by applicable law or agreed to in writing, software 11514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS, 12514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * See the License for the specific language governing permissions and 14514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * limitations under the License. 15514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi */ 16514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi 17514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggipackage com.android.systemui.stackdivider; 18514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi 19514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport android.animation.Animator; 20514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport android.animation.AnimatorListenerAdapter; 21514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport android.animation.AnimatorSet; 22514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport android.animation.ObjectAnimator; 23514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport android.annotation.Nullable; 24514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport android.content.Context; 25514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport android.graphics.Canvas; 26514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport android.graphics.Paint; 27514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport android.util.AttributeSet; 28514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport android.util.Property; 2988afd020b696af24332547f203eaa2538618ac9eJorim Jaggiimport android.view.View; 30514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi 31ea4a19f1aa27ba4b9fc4ec0af1d19b4177f801dfJorim Jaggiimport com.android.systemui.Interpolators; 32514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport com.android.systemui.R; 33514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi 34514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi/** 35514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * View for the handle in the docked stack divider. 36514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi */ 3788afd020b696af24332547f203eaa2538618ac9eJorim Jaggipublic class DividerHandleView extends View { 38514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi 39514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi private final static Property<DividerHandleView, Integer> WIDTH_PROPERTY 40514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi = new Property<DividerHandleView, Integer>(Integer.class, "width") { 41514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi 42514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi @Override 43514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi public Integer get(DividerHandleView object) { 44514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi return object.mCurrentWidth; 45514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi } 46514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi 47514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi @Override 48514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi public void set(DividerHandleView object, Integer value) { 49514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi object.mCurrentWidth = value; 50514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi object.invalidate(); 51514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi } 52514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi }; 53514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi 54514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi private final static Property<DividerHandleView, Integer> HEIGHT_PROPERTY 55514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi = new Property<DividerHandleView, Integer>(Integer.class, "height") { 56514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi 57514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi @Override 58514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi public Integer get(DividerHandleView object) { 59514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi return object.mCurrentHeight; 60514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi } 61514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi 62514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi @Override 63514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi public void set(DividerHandleView object, Integer value) { 64514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi object.mCurrentHeight = value; 65514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi object.invalidate(); 66514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi } 67514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi }; 68514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi 69514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi private final Paint mPaint = new Paint(); 70514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi private final int mWidth; 71514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi private final int mHeight; 72514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi private final int mCircleDiameter; 73514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi private int mCurrentWidth; 74514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi private int mCurrentHeight; 75514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi private AnimatorSet mAnimator; 76e161f08e98fdbe6fe83f70ffa1ea11142a027ebeJorim Jaggi private boolean mTouching; 77514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi 78514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi public DividerHandleView(Context context, @Nullable AttributeSet attrs) { 79514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi super(context, attrs); 80514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi mPaint.setColor(getResources().getColor(R.color.docked_divider_handle, null)); 81514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi mPaint.setAntiAlias(true); 82514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi mWidth = getResources().getDimensionPixelSize(R.dimen.docked_divider_handle_width); 83514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi mHeight = getResources().getDimensionPixelSize(R.dimen.docked_divider_handle_height); 84514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi mCurrentWidth = mWidth; 85514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi mCurrentHeight = mHeight; 86514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi mCircleDiameter = (mWidth + mHeight) / 3; 87514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi } 88514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi 89514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi public void setTouching(boolean touching, boolean animate) { 90e161f08e98fdbe6fe83f70ffa1ea11142a027ebeJorim Jaggi if (touching == mTouching) { 91e161f08e98fdbe6fe83f70ffa1ea11142a027ebeJorim Jaggi return; 92e161f08e98fdbe6fe83f70ffa1ea11142a027ebeJorim Jaggi } 93514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi if (mAnimator != null) { 94514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi mAnimator.cancel(); 95514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi mAnimator = null; 96514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi } 97514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi if (!animate) { 98514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi if (touching) { 99514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi mCurrentWidth = mCircleDiameter; 100514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi mCurrentHeight = mCircleDiameter; 101514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi } else { 102514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi mCurrentWidth = mWidth; 103514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi mCurrentHeight = mHeight; 104514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi } 105514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi invalidate(); 106514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi } else { 107514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi animateToTarget(touching ? mCircleDiameter : mWidth, 108514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi touching ? mCircleDiameter : mHeight, touching); 109514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi } 110e161f08e98fdbe6fe83f70ffa1ea11142a027ebeJorim Jaggi mTouching = touching; 111514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi } 112514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi 113514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi private void animateToTarget(int targetWidth, int targetHeight, boolean touching) { 114514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi ObjectAnimator widthAnimator = ObjectAnimator.ofInt(this, WIDTH_PROPERTY, 115514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi mCurrentWidth, targetWidth); 116514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi ObjectAnimator heightAnimator = ObjectAnimator.ofInt(this, HEIGHT_PROPERTY, 117514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi mCurrentHeight, targetHeight); 118514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi mAnimator = new AnimatorSet(); 119514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi mAnimator.playTogether(widthAnimator, heightAnimator); 120514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi mAnimator.setDuration(touching 121514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi ? DividerView.TOUCH_ANIMATION_DURATION 122514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi : DividerView.TOUCH_RELEASE_ANIMATION_DURATION); 123514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi mAnimator.setInterpolator(touching 124ea4a19f1aa27ba4b9fc4ec0af1d19b4177f801dfJorim Jaggi ? Interpolators.TOUCH_RESPONSE 125ea4a19f1aa27ba4b9fc4ec0af1d19b4177f801dfJorim Jaggi : Interpolators.FAST_OUT_SLOW_IN); 126514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi mAnimator.addListener(new AnimatorListenerAdapter() { 127514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi @Override 128514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi public void onAnimationEnd(Animator animation) { 129514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi mAnimator = null; 130514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi } 131514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi }); 132514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi mAnimator.start(); 133514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi } 134514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi 135514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi @Override 136514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi protected void onDraw(Canvas canvas) { 137514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi int left = getWidth() / 2 - mCurrentWidth / 2; 138514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi int top = getHeight() / 2 - mCurrentHeight / 2; 139514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi int radius = Math.min(mCurrentWidth, mCurrentHeight) / 2; 140514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi canvas.drawRoundRect(left, top, left + mCurrentWidth, top + mCurrentHeight, 141514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi radius, radius, mPaint); 142514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi } 14342625d1bc7ef99c4d4435e8cdebfe3eee57b8d97Jorim Jaggi 14442625d1bc7ef99c4d4435e8cdebfe3eee57b8d97Jorim Jaggi @Override 14542625d1bc7ef99c4d4435e8cdebfe3eee57b8d97Jorim Jaggi public boolean hasOverlappingRendering() { 14642625d1bc7ef99c4d4435e8cdebfe3eee57b8d97Jorim Jaggi return false; 14742625d1bc7ef99c4d4435e8cdebfe3eee57b8d97Jorim Jaggi } 148514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi} 149