Jorim Jaggi | be565df | 2014-04-28 17:51:23 +0200 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2014 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.statusbar; |
| 18 | |
| 19 | import android.content.Context; |
| 20 | import android.graphics.Outline; |
Chris Craik | 7b7ca3c | 2014-07-11 13:32:19 -0700 | [diff] [blame] | 21 | import android.graphics.Rect; |
Selim Cinek | 8efa6dd | 2014-05-19 16:27:37 +0200 | [diff] [blame] | 22 | import android.graphics.RectF; |
Jorim Jaggi | be565df | 2014-04-28 17:51:23 +0200 | [diff] [blame] | 23 | import android.util.AttributeSet; |
Chris Craik | 7b7ca3c | 2014-07-11 13:32:19 -0700 | [diff] [blame] | 24 | import android.view.View; |
| 25 | import android.view.ViewOutlineProvider; |
Jorim Jaggi | be565df | 2014-04-28 17:51:23 +0200 | [diff] [blame] | 26 | |
| 27 | /** |
| 28 | * Like {@link ExpandableView}, but setting an outline for the height and clipping. |
| 29 | */ |
| 30 | public abstract class ExpandableOutlineView extends ExpandableView { |
| 31 | |
Chris Craik | 7b7ca3c | 2014-07-11 13:32:19 -0700 | [diff] [blame] | 32 | private final Rect mOutlineRect = new Rect(); |
Selim Cinek | 8efa6dd | 2014-05-19 16:27:37 +0200 | [diff] [blame] | 33 | private boolean mCustomOutline; |
Selim Cinek | d35c279 | 2016-01-21 13:20:57 -0800 | [diff] [blame] | 34 | private float mOutlineAlpha = -1f; |
Jorim Jaggi | be565df | 2014-04-28 17:51:23 +0200 | [diff] [blame] | 35 | |
Mady Mellor | b0a8246 | 2016-04-30 17:31:02 -0700 | [diff] [blame] | 36 | ViewOutlineProvider mProvider = new ViewOutlineProvider() { |
| 37 | @Override |
| 38 | public void getOutline(View view, Outline outline) { |
| 39 | int translation = (int) getTranslation(); |
| 40 | if (!mCustomOutline) { |
| 41 | outline.setRect(translation, |
| 42 | mClipTopAmount, |
| 43 | getWidth() + translation, |
Selim Cinek | b3dadcc | 2016-11-21 17:21:13 -0800 | [diff] [blame] | 44 | Math.max(getActualHeight() - mClipBottomAmount, mClipTopAmount)); |
Mady Mellor | b0a8246 | 2016-04-30 17:31:02 -0700 | [diff] [blame] | 45 | } else { |
| 46 | outline.setRect(mOutlineRect); |
| 47 | } |
| 48 | outline.setAlpha(mOutlineAlpha); |
| 49 | } |
| 50 | }; |
| 51 | |
Jorim Jaggi | be565df | 2014-04-28 17:51:23 +0200 | [diff] [blame] | 52 | public ExpandableOutlineView(Context context, AttributeSet attrs) { |
| 53 | super(context, attrs); |
Mady Mellor | b0a8246 | 2016-04-30 17:31:02 -0700 | [diff] [blame] | 54 | setOutlineProvider(mProvider); |
Jorim Jaggi | be565df | 2014-04-28 17:51:23 +0200 | [diff] [blame] | 55 | } |
| 56 | |
| 57 | @Override |
Jorim Jaggi | d552d9d | 2014-05-07 19:41:13 +0200 | [diff] [blame] | 58 | public void setActualHeight(int actualHeight, boolean notifyListeners) { |
| 59 | super.setActualHeight(actualHeight, notifyListeners); |
Chris Craik | 7b7ca3c | 2014-07-11 13:32:19 -0700 | [diff] [blame] | 60 | invalidateOutline(); |
Jorim Jaggi | be565df | 2014-04-28 17:51:23 +0200 | [diff] [blame] | 61 | } |
| 62 | |
| 63 | @Override |
| 64 | public void setClipTopAmount(int clipTopAmount) { |
| 65 | super.setClipTopAmount(clipTopAmount); |
Chris Craik | 7b7ca3c | 2014-07-11 13:32:19 -0700 | [diff] [blame] | 66 | invalidateOutline(); |
Jorim Jaggi | be565df | 2014-04-28 17:51:23 +0200 | [diff] [blame] | 67 | } |
| 68 | |
Selim Cinek | b3dadcc | 2016-11-21 17:21:13 -0800 | [diff] [blame] | 69 | @Override |
| 70 | public void setClipBottomAmount(int clipBottomAmount) { |
| 71 | super.setClipBottomAmount(clipBottomAmount); |
| 72 | invalidateOutline(); |
| 73 | } |
| 74 | |
Jorim Jaggi | 83eb6bb | 2015-08-17 17:38:58 -0700 | [diff] [blame] | 75 | protected void setOutlineAlpha(float alpha) { |
Selim Cinek | d35c279 | 2016-01-21 13:20:57 -0800 | [diff] [blame] | 76 | if (alpha != mOutlineAlpha) { |
| 77 | mOutlineAlpha = alpha; |
| 78 | invalidateOutline(); |
| 79 | } |
Jorim Jaggi | 83eb6bb | 2015-08-17 17:38:58 -0700 | [diff] [blame] | 80 | } |
| 81 | |
Selim Cinek | 3322357 | 2016-02-19 19:32:22 -0800 | [diff] [blame] | 82 | @Override |
| 83 | public float getOutlineAlpha() { |
| 84 | return mOutlineAlpha; |
| 85 | } |
| 86 | |
Selim Cinek | 8efa6dd | 2014-05-19 16:27:37 +0200 | [diff] [blame] | 87 | protected void setOutlineRect(RectF rect) { |
| 88 | if (rect != null) { |
| 89 | setOutlineRect(rect.left, rect.top, rect.right, rect.bottom); |
| 90 | } else { |
| 91 | mCustomOutline = false; |
Selim Cinek | 560e64d | 2015-06-09 19:58:11 -0700 | [diff] [blame] | 92 | setClipToOutline(false); |
Chris Craik | 7b7ca3c | 2014-07-11 13:32:19 -0700 | [diff] [blame] | 93 | invalidateOutline(); |
Selim Cinek | 8efa6dd | 2014-05-19 16:27:37 +0200 | [diff] [blame] | 94 | } |
| 95 | } |
| 96 | |
Selim Cinek | 3322357 | 2016-02-19 19:32:22 -0800 | [diff] [blame] | 97 | @Override |
| 98 | public int getOutlineTranslation() { |
Mady Mellor | b0a8246 | 2016-04-30 17:31:02 -0700 | [diff] [blame] | 99 | return mCustomOutline ? mOutlineRect.left : (int) getTranslation(); |
| 100 | } |
| 101 | |
| 102 | public void updateOutline() { |
| 103 | if (mCustomOutline) { |
| 104 | return; |
| 105 | } |
Selim Cinek | ad7fac0 | 2016-10-18 17:09:15 -0700 | [diff] [blame] | 106 | boolean hasOutline = needsOutline(); |
Mady Mellor | b0a8246 | 2016-04-30 17:31:02 -0700 | [diff] [blame] | 107 | setOutlineProvider(hasOutline ? mProvider : null); |
| 108 | } |
| 109 | |
Selim Cinek | ad7fac0 | 2016-10-18 17:09:15 -0700 | [diff] [blame] | 110 | /** |
| 111 | * @return whether the view currently needs an outline. This is usually false in case it doesn't |
| 112 | * have a background. |
| 113 | */ |
| 114 | protected boolean needsOutline() { |
| 115 | if (isChildInGroup()) { |
| 116 | return isGroupExpanded() && !isGroupExpansionChanging(); |
| 117 | } else if (isSummaryWithChildren()) { |
| 118 | return !isGroupExpanded() || isGroupExpansionChanging(); |
| 119 | } |
| 120 | return true; |
| 121 | } |
| 122 | |
Mady Mellor | b0a8246 | 2016-04-30 17:31:02 -0700 | [diff] [blame] | 123 | public boolean isOutlineShowing() { |
| 124 | ViewOutlineProvider op = getOutlineProvider(); |
| 125 | return op != null; |
Selim Cinek | 3322357 | 2016-02-19 19:32:22 -0800 | [diff] [blame] | 126 | } |
| 127 | |
Selim Cinek | 8efa6dd | 2014-05-19 16:27:37 +0200 | [diff] [blame] | 128 | protected void setOutlineRect(float left, float top, float right, float bottom) { |
| 129 | mCustomOutline = true; |
Mady Mellor | b0a8246 | 2016-04-30 17:31:02 -0700 | [diff] [blame] | 130 | setClipToOutline(true); |
Selim Cinek | 8efa6dd | 2014-05-19 16:27:37 +0200 | [diff] [blame] | 131 | |
Chris Craik | 7b7ca3c | 2014-07-11 13:32:19 -0700 | [diff] [blame] | 132 | mOutlineRect.set((int) left, (int) top, (int) right, (int) bottom); |
Selim Cinek | 8efa6dd | 2014-05-19 16:27:37 +0200 | [diff] [blame] | 133 | |
| 134 | // Outlines need to be at least 1 dp |
Selim Cinek | 3969ffa | 2014-09-01 23:08:39 +0200 | [diff] [blame] | 135 | mOutlineRect.bottom = (int) Math.max(top, mOutlineRect.bottom); |
| 136 | mOutlineRect.right = (int) Math.max(left, mOutlineRect.right); |
Chris Craik | 7b7ca3c | 2014-07-11 13:32:19 -0700 | [diff] [blame] | 137 | |
| 138 | invalidateOutline(); |
Jorim Jaggi | be565df | 2014-04-28 17:51:23 +0200 | [diff] [blame] | 139 | } |
Selim Cinek | 8efa6dd | 2014-05-19 16:27:37 +0200 | [diff] [blame] | 140 | |
Jorim Jaggi | be565df | 2014-04-28 17:51:23 +0200 | [diff] [blame] | 141 | } |