ViewInvertHelper.java revision 4e857f4ef0357e05806819d0488a73a12208fe8f
10dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh/*
20dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh * Copyright (C) 2014 The Android Open Source Project
30dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh *
40dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh * Licensed under the Apache License, Version 2.0 (the "License");
50dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh * you may not use this file except in compliance with the License.
60dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh * You may obtain a copy of the License at
70dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh *
80dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh *      http://www.apache.org/licenses/LICENSE-2.0
90dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh *
100dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh * Unless required by applicable law or agreed to in writing, software
110dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh * distributed under the License is distributed on an "AS IS" BASIS,
120dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh * See the License for the specific language governing permissions and
140dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh * limitations under the License
150dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh */
160dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh
170dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yehpackage com.android.systemui;
180dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh
190dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yehimport android.animation.Animator;
200dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yehimport android.animation.AnimatorListenerAdapter;
210dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yehimport android.animation.ValueAnimator;
220dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yehimport android.graphics.ColorMatrix;
230dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yehimport android.graphics.ColorMatrixColorFilter;
240dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yehimport android.graphics.Paint;
250dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yehimport android.view.View;
260dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yehimport android.view.animation.AnimationUtils;
270dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yehimport android.view.animation.Interpolator;
280dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh
290dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yehimport com.android.systemui.statusbar.phone.NotificationPanelView;
300dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh
310dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh/**
320dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh * Helper to invert the colors of views and fade between the states.
330dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh */
340dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yehpublic class ViewInvertHelper {
350dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh
360dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh    private final Paint mDarkPaint = new Paint();
370dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh    private final Interpolator mLinearOutSlowInInterpolator;
380dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh    private final View mTarget;
390dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh    private final ColorMatrix mMatrix = new ColorMatrix();
400dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh    private final ColorMatrix mGrayscaleMatrix = new ColorMatrix();
410dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh    private final long mFadeDuration;
420dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh
430dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh    public ViewInvertHelper(View target, long fadeDuration) {
440dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh        mTarget = target;
450dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh        mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(mTarget.getContext(),
46ead9146f844ee194a4f4244ba8ae1a3aece12b63Yin-Chia Yeh                android.R.interpolator.linear_out_slow_in);
470dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh        mFadeDuration = fadeDuration;
480dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh    }
490dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh
500dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh    public void fade(final boolean invert, long delay) {
510dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh        float startIntensity = invert ? 0f : 1f;
520dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh        float endIntensity = invert ? 1f : 0f;
530dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh        ValueAnimator animator = ValueAnimator.ofFloat(startIntensity, endIntensity);
540dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
550dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh            @Override
560dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh            public void onAnimationUpdate(ValueAnimator animation) {
570dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh                updateInvertPaint((Float) animation.getAnimatedValue());
580dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh                mTarget.setLayerType(View.LAYER_TYPE_HARDWARE, mDarkPaint);
590dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh            }
600dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh        });
610dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh        animator.addListener(new AnimatorListenerAdapter() {
620dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh            @Override
630dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh            public void onAnimationEnd(Animator animation) {
640dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh                if (!invert) {
650dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh                    mTarget.setLayerType(View.LAYER_TYPE_NONE, null);
660dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh                }
670dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh            }
680dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh        });
690dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh        animator.setDuration(mFadeDuration);
70ead9146f844ee194a4f4244ba8ae1a3aece12b63Yin-Chia Yeh        animator.setInterpolator(mLinearOutSlowInInterpolator);
71ead9146f844ee194a4f4244ba8ae1a3aece12b63Yin-Chia Yeh        animator.setStartDelay(delay);
720dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh        animator.start();
730dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh    }
740dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh
750dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh    public void update(boolean invert) {
760dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh        if (invert) {
770dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh            updateInvertPaint(1f);
780dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh            mTarget.setLayerType(View.LAYER_TYPE_HARDWARE, mDarkPaint);
790dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh        } else {
800dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh            mTarget.setLayerType(View.LAYER_TYPE_NONE, null);
810dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh        }
820dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh    }
830dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh
840dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh    public View getTarget() {
850dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh        return mTarget;
860dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh    }
870dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh
880dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh    private void updateInvertPaint(float intensity) {
89ead9146f844ee194a4f4244ba8ae1a3aece12b63Yin-Chia Yeh        float components = 1 - 2 * intensity;
90ead9146f844ee194a4f4244ba8ae1a3aece12b63Yin-Chia Yeh        final float[] invert = {
910dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh                components, 0f,         0f,         0f, 255f * intensity,
920dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh                0f,         components, 0f,         0f, 255f * intensity,
930dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh                0f,         0f,         components, 0f, 255f * intensity,
940dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh                0f,         0f,         0f,         1f, 0f
950dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh        };
960dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh        mMatrix.set(invert);
970dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh        mGrayscaleMatrix.setSaturation(1 - intensity);
980dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh        mMatrix.preConcat(mGrayscaleMatrix);
990dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh        mDarkPaint.setColorFilter(new ColorMatrixColorFilter(mMatrix));
1000dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh    }
1010dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh}