Add window setDecorView API.
Add a Window API for setting a view which will be placed in the decoration area (next to the window control buttons). Change-Id: Ie106cbea653ff95fdba987a2a43506d394600612
This commit is contained in:
@@ -37441,6 +37441,8 @@ package android.view {
|
||||
method public abstract void setContentView(int);
|
||||
method public abstract void setContentView(android.view.View);
|
||||
method public abstract void setContentView(android.view.View, android.view.ViewGroup.LayoutParams);
|
||||
method public abstract void setDecorView(android.view.View);
|
||||
method public abstract void setDecorView(int);
|
||||
method protected void setDefaultWindowFormat(int);
|
||||
method public void setDimAmount(float);
|
||||
method public void setElevation(float);
|
||||
|
||||
@@ -39738,6 +39738,8 @@ package android.view {
|
||||
method public abstract void setContentView(int);
|
||||
method public abstract void setContentView(android.view.View);
|
||||
method public abstract void setContentView(android.view.View, android.view.ViewGroup.LayoutParams);
|
||||
method public abstract void setDecorView(android.view.View);
|
||||
method public abstract void setDecorView(int);
|
||||
method protected void setDefaultWindowFormat(int);
|
||||
method public void setDimAmount(float);
|
||||
method public void setDisableWallpaperTouchEvents(boolean);
|
||||
|
||||
@@ -1155,6 +1155,27 @@ public abstract class Window {
|
||||
*/
|
||||
public abstract void setContentView(View view);
|
||||
|
||||
/**
|
||||
* Install a view in the decoration (title) area, to be shown when
|
||||
* the window is in multi-window mode. This view will be placed
|
||||
* next to the window controls.
|
||||
*
|
||||
* The view may be restored to defaults by passing null.
|
||||
*
|
||||
* @param view The desired view to display in window decorations.
|
||||
*/
|
||||
public abstract void setDecorView(View view);
|
||||
|
||||
/**
|
||||
* Convenience for
|
||||
* {@link #setDecorView(View)}
|
||||
* to set the custom window decoration from a layout resource. The layout will be inflated
|
||||
* adding all top level views to the decoration
|
||||
*
|
||||
* @param layoutResID Resource ID to be inflated.
|
||||
*/
|
||||
public abstract void setDecorView(@LayoutRes int layoutResID);
|
||||
|
||||
/**
|
||||
* Set the screen content to an explicit view. This view is placed
|
||||
* directly into the screen's view hierarchy. It can itself be a complex
|
||||
|
||||
@@ -123,6 +123,7 @@ import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.PopupWindow;
|
||||
import android.widget.ProgressBar;
|
||||
@@ -468,6 +469,30 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDecorView(int layoutResID) {
|
||||
View v = mLayoutInflater.inflate(layoutResID, null);
|
||||
setDecorView(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDecorView(View view) {
|
||||
if (mContentParent == null) {
|
||||
installDecor();
|
||||
}
|
||||
|
||||
LinearLayout clientDecorPlaceholder =
|
||||
(LinearLayout) findViewById(R.id.client_decor_placeholder);
|
||||
|
||||
if (clientDecorPlaceholder != null) {
|
||||
clientDecorPlaceholder.removeAllViews();
|
||||
|
||||
if (view != null) {
|
||||
clientDecorPlaceholder.addView(view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addContentView(View view, ViewGroup.LayoutParams params) {
|
||||
if (mContentParent == null) {
|
||||
|
||||
@@ -428,8 +428,7 @@ public class NonClientDecorView extends LinearLayout
|
||||
|
||||
// The render nodes for the multi threaded renderer.
|
||||
private ThreadedRenderer mRenderer;
|
||||
private RenderNode mFrameNode;
|
||||
private RenderNode mBackdropNode;
|
||||
private RenderNode mFrameAndBackdropNode;
|
||||
|
||||
private final Rect mOldTargetRect = new Rect();
|
||||
private final Rect mNewTargetRect = new Rect();
|
||||
@@ -450,13 +449,11 @@ public class NonClientDecorView extends LinearLayout
|
||||
setName("ResizeFrame");
|
||||
mRenderer = renderer;
|
||||
|
||||
// Create the render nodes for our frame and backdrop which can be resized independently
|
||||
// from the content.
|
||||
mFrameNode = RenderNode.create("FrameNode", null);
|
||||
mBackdropNode = RenderNode.create("BackdropNode", null);
|
||||
// Create a render node for the content and frame backdrop
|
||||
// which can be resized independently from the content.
|
||||
mFrameAndBackdropNode = RenderNode.create("FrameAndBackdropNode", null);
|
||||
|
||||
mRenderer.addRenderNode(mFrameNode, false);
|
||||
mRenderer.addRenderNode(mBackdropNode, true);
|
||||
mRenderer.addRenderNode(mFrameAndBackdropNode, true);
|
||||
|
||||
// Set the initial bounds and draw once so that we do not get a broken frame.
|
||||
mTargetRect.set(initialBounds);
|
||||
@@ -504,10 +501,9 @@ public class NonClientDecorView extends LinearLayout
|
||||
// Invalidate the current content bounds.
|
||||
mRenderer.setContentDrawBounds(0, 0, 0, 0);
|
||||
|
||||
// Remove the render nodes again
|
||||
// Remove the render node again
|
||||
// (see comment above - better to do that only once).
|
||||
mRenderer.removeRenderNode(mFrameNode);
|
||||
mRenderer.removeRenderNode(mBackdropNode);
|
||||
mRenderer.removeRenderNode(mFrameAndBackdropNode);
|
||||
|
||||
mRenderer = null;
|
||||
|
||||
@@ -575,7 +571,7 @@ public class NonClientDecorView extends LinearLayout
|
||||
|
||||
mRenderer.setContentDrawBounds(
|
||||
mLastXOffset,
|
||||
mLastYOffset + mLastCaptionHeight,
|
||||
mLastYOffset,
|
||||
mLastXOffset + mLastContentWidth,
|
||||
mLastYOffset + mLastCaptionHeight + mLastContentHeight);
|
||||
// If this was the first call and changeWindowSizeLocked got already called prior
|
||||
@@ -623,30 +619,20 @@ public class NonClientDecorView extends LinearLayout
|
||||
final int width = newBounds.width();
|
||||
final int height = newBounds.height();
|
||||
|
||||
// Produce the draw calls.
|
||||
// TODO(skuhne): Create a separate caption view which draws this. If the shadow should
|
||||
// be resized while the window resizes, this hierarchy needs to have the elevation.
|
||||
// That said - it is probably no good idea to draw the shadow every time since it costs
|
||||
// a considerable time which we should rather spend for resizing the content and it does
|
||||
// barely show while the entire screen is moving.
|
||||
mFrameNode.setLeftTopRightBottom(left, top, left + width, top + mLastCaptionHeight);
|
||||
DisplayListCanvas canvas = mFrameNode.start(width, height);
|
||||
mFrameAndBackdropNode.setLeftTopRightBottom(left, top, left + width, top + height);
|
||||
|
||||
// Draw the caption and content backdrops in to our render node.
|
||||
DisplayListCanvas canvas = mFrameAndBackdropNode.start(width, height);
|
||||
mCaptionBackgroundDrawable.setBounds(0, 0, left + width, top + mLastCaptionHeight);
|
||||
mCaptionBackgroundDrawable.draw(canvas);
|
||||
mFrameNode.end(canvas);
|
||||
|
||||
mBackdropNode.setLeftTopRightBottom(left, top + mLastCaptionHeight, left + width,
|
||||
top + height);
|
||||
|
||||
// The backdrop: clear everything with the background. Clipping is done elsewhere.
|
||||
canvas = mBackdropNode.start(width, height - mLastCaptionHeight);
|
||||
mResizingBackgroundDrawable.setBounds(0, 0, left + width, top + height);
|
||||
mResizingBackgroundDrawable.setBounds(0, mLastCaptionHeight, left + width, top + height);
|
||||
mResizingBackgroundDrawable.draw(canvas);
|
||||
mBackdropNode.end(canvas);
|
||||
mFrameAndBackdropNode.end(canvas);
|
||||
|
||||
// We need to render both rendered nodes explicitly.
|
||||
mRenderer.drawRenderNode(mFrameNode);
|
||||
mRenderer.drawRenderNode(mBackdropNode);
|
||||
// We need to render the node explicitly
|
||||
mRenderer.drawRenderNode(mFrameAndBackdropNode);
|
||||
|
||||
reportDrawIfNeeded();
|
||||
}
|
||||
|
||||
@@ -29,10 +29,11 @@
|
||||
android:background="@drawable/non_client_decor_title"
|
||||
android:focusable="false"
|
||||
android:descendantFocusability="blocksDescendants" >
|
||||
<TextView
|
||||
<LinearLayout
|
||||
android:id="@+id/client_decor_placeholder"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1" />
|
||||
android:layout_weight="1"/>
|
||||
<Button
|
||||
android:id="@+id/maximize_window"
|
||||
android:layout_width="32dp"
|
||||
|
||||
@@ -29,10 +29,11 @@
|
||||
android:background="@drawable/non_client_decor_title"
|
||||
android:focusable="false"
|
||||
android:descendantFocusability="blocksDescendants" >
|
||||
<TextView
|
||||
<LinearLayout
|
||||
android:id="@+id/client_decor_placeholder"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1" />
|
||||
android:layout_weight="1"/>
|
||||
<Button
|
||||
android:id="@+id/maximize_window"
|
||||
android:layout_width="32dp"
|
||||
|
||||
@@ -1956,6 +1956,7 @@
|
||||
<java-symbol type="bool" name="config_built_in_sip_phone" />
|
||||
<java-symbol type="id" name="maximize_window" />
|
||||
<java-symbol type="id" name="close_window" />
|
||||
<java-symbol type="id" name="client_decor_placeholder" />
|
||||
<java-symbol type="layout" name="non_client_decor_light" />
|
||||
<java-symbol type="layout" name="non_client_decor_dark" />
|
||||
<java-symbol type="drawable" name="non_client_decor_title_focused" />
|
||||
|
||||
@@ -332,22 +332,24 @@ void CanvasContext::draw() {
|
||||
dirty.fLeft, dirty.fTop, dirty.fRight, dirty.fBottom, mOpaque);
|
||||
|
||||
Rect outBounds;
|
||||
// It there are multiple render nodes, they are as follows:
|
||||
// #0 - backdrop
|
||||
// It there are multiple render nodes, they are laid out as follows:
|
||||
// #0 - backdrop (content + caption)
|
||||
// #1 - content (positioned at (0,0) and clipped to - its bounds mContentDrawBounds)
|
||||
// #2 - frame
|
||||
// #2 - additional overlay nodes
|
||||
// Usually the backdrop cannot be seen since it will be entirely covered by the content. While
|
||||
// resizing however it might become partially visible. The following render loop will crop the
|
||||
// backdrop against the content and draw the remaining part of it. It will then crop the content
|
||||
// against the backdrop (since that indicates a shrinking of the window) and then the frame
|
||||
// around everything.
|
||||
// backdrop against the content and draw the remaining part of it. It will then draw the content
|
||||
// cropped to the backdrop (since that indicates a shrinking of the window).
|
||||
//
|
||||
// Additional nodes will be drawn on top with no particular clipping semantics.
|
||||
|
||||
// The bounds of the backdrop against which the content should be clipped.
|
||||
Rect backdropBounds = mContentDrawBounds;
|
||||
// Usually the contents bounds should be mContentDrawBounds - however - we will
|
||||
// move it towards the fixed edge to give it a more stable appearance (for the moment).
|
||||
Rect contentBounds;
|
||||
// If there is no content bounds we ignore the layering as stated above and start with 2.
|
||||
int layer = (mContentDrawBounds.isEmpty() || mRenderNodes.size() <= 2) ? 2 : 0;
|
||||
int layer = (mContentDrawBounds.isEmpty() || mRenderNodes.size() == 1) ? 2 : 0;
|
||||
// Draw all render nodes. Note that
|
||||
for (const sp<RenderNode>& node : mRenderNodes) {
|
||||
if (layer == 0) { // Backdrop.
|
||||
@@ -424,6 +426,7 @@ void CanvasContext::draw() {
|
||||
const float dy = backdropBounds.top - top;
|
||||
const float width = backdropBounds.getWidth();
|
||||
const float height = backdropBounds.getHeight();
|
||||
|
||||
mCanvas->translate(dx, dy);
|
||||
if (mCanvas->clipRect(left, top, left + width, top + height, SkRegion::kIntersect_Op)) {
|
||||
mCanvas->drawRenderNode(node.get(), outBounds);
|
||||
|
||||
Reference in New Issue
Block a user