diff --git a/packages/SystemUI/res/layout/bubble_expanded_view.xml b/packages/SystemUI/res/layout/bubble_expanded_view.xml new file mode 100644 index 0000000000000..b2307e71e3ce5 --- /dev/null +++ b/packages/SystemUI/res/layout/bubble_expanded_view.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 8e0bfb65428e9..4b07b5f132904 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -991,4 +991,8 @@ 24dp 400dp + + 4dp + + 6dp diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedViewContainer.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedViewContainer.java new file mode 100644 index 0000000000000..e28d96b2def93 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedViewContainer.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.bubbles; + +import android.annotation.Nullable; +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Color; +import android.graphics.drawable.ShapeDrawable; +import android.util.AttributeSet; +import android.view.View; +import android.widget.LinearLayout; + +import com.android.systemui.R; +import com.android.systemui.recents.TriangleShape; + +/** + * Container for the expanded bubble view, handles rendering the caret and header of the view. + */ +public class BubbleExpandedViewContainer extends LinearLayout { + + // The triangle pointing to the expanded view + private View mPointerView; + // The view that is being displayed for the expanded state + private View mExpandedView; + + public BubbleExpandedViewContainer(Context context) { + this(context, null); + } + + public BubbleExpandedViewContainer(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public BubbleExpandedViewContainer(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } + + public BubbleExpandedViewContainer(Context context, AttributeSet attrs, int defStyleAttr, + int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + setOrientation(VERTICAL); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + + Resources res = getResources(); + mPointerView = findViewById(R.id.pointer_view); + int width = res.getDimensionPixelSize(R.dimen.bubble_pointer_width); + int height = res.getDimensionPixelSize(R.dimen.bubble_pointer_height); + ShapeDrawable triangleDrawable = new ShapeDrawable( + TriangleShape.create(width, height, true /* pointUp */)); + triangleDrawable.setTint(Color.WHITE); // TODO: dark mode + mPointerView.setBackground(triangleDrawable); + } + + /** + * Set the x position that the tip of the triangle should point to. + */ + public void setPointerPosition(int x) { + // Adjust for the pointer size + x -= (mPointerView.getWidth() / 2); + mPointerView.setTranslationX(x); + } + + /** + * Set the view to display for the expanded state. Passing null will clear the view. + */ + public void setExpandedView(View view) { + if (mExpandedView != null) { + removeView(mExpandedView); + } + mExpandedView = view; + if (mExpandedView != null) { + addView(mExpandedView); + } + } + + /** + * @return the view containing the expanded content, can be null. + */ + @Nullable + public View getExpandedView() { + return mExpandedView; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java index e395c4c2765c8..dfd18b23a5e39 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java @@ -25,6 +25,7 @@ import android.content.Context; import android.content.res.Resources; import android.graphics.Point; import android.graphics.RectF; +import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -52,7 +53,7 @@ public class BubbleStackView extends FrameLayout implements BubbleTouchHandler.F private Point mDisplaySize; private FrameLayout mBubbleContainer; - private FrameLayout mExpandedViewContainer; + private BubbleExpandedViewContainer mExpandedViewContainer; private int mBubbleSize; private int mBubblePadding; @@ -111,7 +112,9 @@ public class BubbleStackView extends FrameLayout implements BubbleTouchHandler.F int padding = res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding); int elevation = res.getDimensionPixelSize(R.dimen.bubble_elevation); - mExpandedViewContainer = new FrameLayout(context); + mExpandedViewContainer = (BubbleExpandedViewContainer) + LayoutInflater.from(context).inflate(R.layout.bubble_expanded_view, + this /* parent */, false /* attachToRoot */); mExpandedViewContainer.setElevation(elevation); mExpandedViewContainer.setPadding(padding, padding, padding, padding); mExpandedViewContainer.setClipChildren(false); @@ -390,16 +393,19 @@ public class BubbleStackView extends FrameLayout implements BubbleTouchHandler.F ExpandableNotificationRow row = mExpandedBubble.getRowView(); if (!row.equals(mExpandedViewContainer.getChildAt(0))) { // Different expanded view than what we have - mExpandedViewContainer.removeAllViews(); + mExpandedViewContainer.setExpandedView(null); } - mExpandedViewContainer.addView(row); + int pointerPosition = mExpandedBubble.getPosition().x + + (mExpandedBubble.getWidth() / 2); + mExpandedViewContainer.setPointerPosition(pointerPosition); + mExpandedViewContainer.setExpandedView(row); } } private void applyCurrentState() { mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE); if (!mIsExpanded) { - mExpandedViewContainer.removeAllViews(); + mExpandedViewContainer.setExpandedView(null); } else { mExpandedViewContainer.setTranslationY(mBubbleContainer.getHeight()); ExpandableNotificationRow row = mExpandedBubble.getRowView();