1be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi/* 2be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * Copyright (C) 2014 The Android Open Source Project 3be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * 4be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License"); 5be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * you may not use this file except in compliance with the License. 6be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * You may obtain a copy of the License at 7be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * 8be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * http://www.apache.org/licenses/LICENSE-2.0 9be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * 10be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * Unless required by applicable law or agreed to in writing, software 11be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS, 12be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * See the License for the specific language governing permissions and 14be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * limitations under the License 15be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi */ 16be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 17be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggipackage com.android.systemui.statusbar; 18be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 19be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggiimport android.content.Context; 20be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggiimport android.graphics.Outline; 217b7ca3cdf25bee73aa9e58aaaf6ce75fe81bd045Chris Craikimport android.graphics.Rect; 228efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinekimport android.graphics.RectF; 23be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggiimport android.util.AttributeSet; 247b7ca3cdf25bee73aa9e58aaaf6ce75fe81bd045Chris Craikimport android.view.View; 257b7ca3cdf25bee73aa9e58aaaf6ce75fe81bd045Chris Craikimport android.view.ViewOutlineProvider; 26be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 27be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi/** 28be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * Like {@link ExpandableView}, but setting an outline for the height and clipping. 29be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi */ 30be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggipublic abstract class ExpandableOutlineView extends ExpandableView { 31be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 327b7ca3cdf25bee73aa9e58aaaf6ce75fe81bd045Chris Craik private final Rect mOutlineRect = new Rect(); 338efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek private boolean mCustomOutline; 34d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek private float mOutlineAlpha = -1f; 35be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 36b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor ViewOutlineProvider mProvider = new ViewOutlineProvider() { 37b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor @Override 38b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor public void getOutline(View view, Outline outline) { 39b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor int translation = (int) getTranslation(); 40b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor if (!mCustomOutline) { 41b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor outline.setRect(translation, 42b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor mClipTopAmount, 43b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor getWidth() + translation, 44b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor Math.max(getActualHeight(), mClipTopAmount)); 45b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } else { 46b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor outline.setRect(mOutlineRect); 47b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 48b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor outline.setAlpha(mOutlineAlpha); 49b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 50b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor }; 51b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor 52be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi public ExpandableOutlineView(Context context, AttributeSet attrs) { 53be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi super(context, attrs); 54b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor setOutlineProvider(mProvider); 55be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 56be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 57be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi @Override 58d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi public void setActualHeight(int actualHeight, boolean notifyListeners) { 59d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi super.setActualHeight(actualHeight, notifyListeners); 607b7ca3cdf25bee73aa9e58aaaf6ce75fe81bd045Chris Craik invalidateOutline(); 61be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 62be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 63be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi @Override 64be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi public void setClipTopAmount(int clipTopAmount) { 65be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi super.setClipTopAmount(clipTopAmount); 667b7ca3cdf25bee73aa9e58aaaf6ce75fe81bd045Chris Craik invalidateOutline(); 67be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 68be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 6983eb6bb5d83d3994a3750b566a2109a049ab1388Jorim Jaggi protected void setOutlineAlpha(float alpha) { 70d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek if (alpha != mOutlineAlpha) { 71d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek mOutlineAlpha = alpha; 72d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek invalidateOutline(); 73d35c2793a3f4986f0513c17d729bdca57086c994Selim Cinek } 7483eb6bb5d83d3994a3750b566a2109a049ab1388Jorim Jaggi } 7583eb6bb5d83d3994a3750b566a2109a049ab1388Jorim Jaggi 763322357b5045fdcc3e3b04c65219d39ce1ae441fSelim Cinek @Override 773322357b5045fdcc3e3b04c65219d39ce1ae441fSelim Cinek public float getOutlineAlpha() { 783322357b5045fdcc3e3b04c65219d39ce1ae441fSelim Cinek return mOutlineAlpha; 793322357b5045fdcc3e3b04c65219d39ce1ae441fSelim Cinek } 803322357b5045fdcc3e3b04c65219d39ce1ae441fSelim Cinek 818efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek protected void setOutlineRect(RectF rect) { 828efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek if (rect != null) { 838efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek setOutlineRect(rect.left, rect.top, rect.right, rect.bottom); 848efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek } else { 858efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek mCustomOutline = false; 86560e64d3d95a17123048bebe2fb06ffe4567fb78Selim Cinek setClipToOutline(false); 877b7ca3cdf25bee73aa9e58aaaf6ce75fe81bd045Chris Craik invalidateOutline(); 888efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek } 898efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek } 908efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek 913322357b5045fdcc3e3b04c65219d39ce1ae441fSelim Cinek @Override 923322357b5045fdcc3e3b04c65219d39ce1ae441fSelim Cinek public int getOutlineTranslation() { 93b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor return mCustomOutline ? mOutlineRect.left : (int) getTranslation(); 943322357b5045fdcc3e3b04c65219d39ce1ae441fSelim Cinek } 953322357b5045fdcc3e3b04c65219d39ce1ae441fSelim Cinek 96b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor public void updateOutline() { 97b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor if (mCustomOutline) { 98b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor return; 99b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 100b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor boolean hasOutline = true; 101b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor if (isChildInGroup()) { 102b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor hasOutline = isGroupExpanded() && !isGroupExpansionChanging(); 103b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } else if (isSummaryWithChildren()) { 104b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor hasOutline = !isGroupExpanded() || isGroupExpansionChanging(); 105b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 106b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor setOutlineProvider(hasOutline ? mProvider : null); 1074b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor } 1084b80b1025f82fa7becc8e126bfa4aea39affcf65Mady Mellor 109b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor public boolean isOutlineShowing() { 110b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor ViewOutlineProvider op = getOutlineProvider(); 111b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor return op != null; 112b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor } 113b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor 114b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor protected void setOutlineRect(float left, float top, float right, float bottom) { 1158efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek mCustomOutline = true; 116b0a824687f56b6950338aad169d8d837f8ed657bMady Mellor setClipToOutline(true); 1178efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek 1187b7ca3cdf25bee73aa9e58aaaf6ce75fe81bd045Chris Craik mOutlineRect.set((int) left, (int) top, (int) right, (int) bottom); 1198efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek 1208efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek // Outlines need to be at least 1 dp 1213969ffa2f5830a680490d03fbb113a7fee900b56Selim Cinek mOutlineRect.bottom = (int) Math.max(top, mOutlineRect.bottom); 1223969ffa2f5830a680490d03fbb113a7fee900b56Selim Cinek mOutlineRect.right = (int) Math.max(left, mOutlineRect.right); 1238efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek 1247b7ca3cdf25bee73aa9e58aaaf6ce75fe81bd045Chris Craik invalidateOutline(); 1258efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek } 1267b7ca3cdf25bee73aa9e58aaaf6ce75fe81bd045Chris Craik 127be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi} 128