DividerHandleView.java revision 514b2cf0f8ddd11a4176412cb3584ab96fbb763a
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;
29514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport android.view.animation.AnimationUtils;
30514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport android.view.animation.Interpolator;
31514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport android.widget.ImageButton;
32514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
33514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggiimport com.android.systemui.R;
34514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
35514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi/**
36514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi * View for the handle in the docked stack divider.
37514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi */
38514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggipublic class DividerHandleView extends ImageButton {
39514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
40514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    private final static Property<DividerHandleView, Integer> WIDTH_PROPERTY
41514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            = new Property<DividerHandleView, Integer>(Integer.class, "width") {
42514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
43514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        @Override
44514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        public Integer get(DividerHandleView object) {
45514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            return object.mCurrentWidth;
46514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        }
47514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
48514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        @Override
49514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        public void set(DividerHandleView object, Integer value) {
50514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            object.mCurrentWidth = value;
51514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            object.invalidate();
52514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        }
53514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    };
54514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
55514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    private final static Property<DividerHandleView, Integer> HEIGHT_PROPERTY
56514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            = new Property<DividerHandleView, Integer>(Integer.class, "height") {
57514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
58514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        @Override
59514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        public Integer get(DividerHandleView object) {
60514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            return object.mCurrentHeight;
61514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        }
62514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
63514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        @Override
64514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        public void set(DividerHandleView object, Integer value) {
65514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            object.mCurrentHeight = value;
66514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            object.invalidate();
67514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        }
68514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    };
69514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
70514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    private final Paint mPaint = new Paint();
71514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    private final int mWidth;
72514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    private final int mHeight;
73514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    private final int mCircleDiameter;
74514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    private final Interpolator mFastOutSlowInInterpolator;
75514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    private int mCurrentWidth;
76514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    private int mCurrentHeight;
77514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    private AnimatorSet mAnimator;
78514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
79514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    public DividerHandleView(Context context, @Nullable AttributeSet attrs) {
80514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        super(context, attrs);
81514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mPaint.setColor(getResources().getColor(R.color.docked_divider_handle, null));
82514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mPaint.setAntiAlias(true);
83514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mWidth = getResources().getDimensionPixelSize(R.dimen.docked_divider_handle_width);
84514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mHeight = getResources().getDimensionPixelSize(R.dimen.docked_divider_handle_height);
85514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mCurrentWidth = mWidth;
86514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mCurrentHeight = mHeight;
87514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mCircleDiameter = (mWidth + mHeight) / 3;
88514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(),
89514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi                android.R.interpolator.fast_out_slow_in);
90514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    }
91514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
92514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    public void setTouching(boolean touching, boolean animate) {
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        }
110514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    }
111514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
112514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    private void animateToTarget(int targetWidth, int targetHeight, boolean touching) {
113514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        ObjectAnimator widthAnimator = ObjectAnimator.ofInt(this, WIDTH_PROPERTY,
114514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi                mCurrentWidth, targetWidth);
115514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        ObjectAnimator heightAnimator = ObjectAnimator.ofInt(this, HEIGHT_PROPERTY,
116514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi                mCurrentHeight, targetHeight);
117514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mAnimator = new AnimatorSet();
118514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mAnimator.playTogether(widthAnimator, heightAnimator);
119514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mAnimator.setDuration(touching
120514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi                ? DividerView.TOUCH_ANIMATION_DURATION
121514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi                : DividerView.TOUCH_RELEASE_ANIMATION_DURATION);
122514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mAnimator.setInterpolator(touching
123514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi                ? DividerView.TOUCH_RESPONSE_INTERPOLATOR
124514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi                : mFastOutSlowInInterpolator);
125514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mAnimator.addListener(new AnimatorListenerAdapter() {
126514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            @Override
127514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            public void onAnimationEnd(Animator animation) {
128514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi                mAnimator = null;
129514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi            }
130514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        });
131514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        mAnimator.start();
132514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    }
133514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi
134514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    @Override
135514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    protected void onDraw(Canvas canvas) {
136514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        int left = getWidth() / 2 - mCurrentWidth / 2;
137514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        int top = getHeight() / 2 - mCurrentHeight / 2;
138514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        int radius = Math.min(mCurrentWidth, mCurrentHeight) / 2;
139514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi        canvas.drawRoundRect(left, top, left + mCurrentWidth, top + mCurrentHeight,
140514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi                radius, radius, mPaint);
141514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi    }
142514b2cf0f8ddd11a4176412cb3584ab96fbb763aJorim Jaggi}
143