RippleComponent.java revision 7bb9f374c07258039232711c49a743ea8dc982ff
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
17package android.graphics.drawable;
18
19import android.animation.Animator;
20import android.graphics.Canvas;
21import android.graphics.Paint;
22import android.graphics.Rect;
23import android.util.DisplayMetrics;
24import android.view.DisplayListCanvas;
25import android.view.RenderNodeAnimator;
26
27import java.util.ArrayList;
28
29/**
30 * Abstract class that handles size & positioning common to the ripple & focus states.
31 */
32abstract class RippleComponent {
33    protected final RippleDrawable mOwner;
34
35    /** Bounds used for computing max radius. May be modified by the owner. */
36    protected final Rect mBounds;
37
38    /** Whether we have an explicit maximum radius. */
39    private boolean mHasMaxRadius;
40
41    /** How big this ripple should be when fully entered. */
42    protected float mTargetRadius;
43
44    /** Screen density used to adjust pixel-based constants. */
45    protected float mDensityScale;
46
47    public RippleComponent(RippleDrawable owner, Rect bounds) {
48        mOwner = owner;
49        mBounds = bounds;
50    }
51
52    public void onBoundsChange() {
53        if (!mHasMaxRadius) {
54            mTargetRadius = getTargetRadius(mBounds);
55            onTargetRadiusChanged(mTargetRadius);
56        }
57    }
58
59    public final void setup(float maxRadius, int densityDpi) {
60        if (maxRadius >= 0) {
61            mHasMaxRadius = true;
62            mTargetRadius = maxRadius;
63        } else {
64            mTargetRadius = getTargetRadius(mBounds);
65        }
66
67        mDensityScale = densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
68
69        onTargetRadiusChanged(mTargetRadius);
70    }
71
72    private static float getTargetRadius(Rect bounds) {
73        final float halfWidth = bounds.width() / 2.0f;
74        final float halfHeight = bounds.height() / 2.0f;
75        return (float) Math.sqrt(halfWidth * halfWidth + halfHeight * halfHeight);
76    }
77
78    /**
79     * Populates {@code bounds} with the maximum drawing bounds of the ripple
80     * relative to its center. The resulting bounds should be translated into
81     * parent drawable coordinates before use.
82     *
83     * @param bounds the rect to populate with drawing bounds
84     */
85    public void getBounds(Rect bounds) {
86        final int r = (int) Math.ceil(mTargetRadius);
87        bounds.set(-r, -r, r, r);
88    }
89
90    protected final void invalidateSelf() {
91        mOwner.invalidateSelf(false);
92    }
93
94    protected final void onHotspotBoundsChanged() {
95        if (!mHasMaxRadius) {
96            mTargetRadius = getTargetRadius(mBounds);
97            onTargetRadiusChanged(mTargetRadius);
98        }
99    }
100
101    /**
102     * Called when the target radius changes.
103     *
104     * @param targetRadius the new target radius
105     */
106    protected void onTargetRadiusChanged(float targetRadius) {
107        // Stub.
108    }
109}
110