From d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7e Mon Sep 17 00:00:00 2001 From: Alan Newberger Date: Mon, 9 Feb 2015 20:53:03 -0800 Subject: [PATCH] Remove app background and reduce 1 layer of overdraw Set the app background to null. This saves one full layer of overdraw in the filmstrip. The capture UI is more dependent on the window background, both for gaps in the preview and screen edges, and behind the shutter button when it is made transparent when the mode list is open. The preview is a large portion of screen and to remove one overdraw, we instead fill gaps around the preview with a MarginDrawable overlay. This CL leaves a background behind the shutter button when opaque, to allow for it becoming transparent during mode list view. Bug: 18596159 Change-Id: I2a9083a2413944c6244e2f0528164e8852ae3d8e --- src/com/android/camera/CameraActivity.java | 10 ++- src/com/android/camera/app/CameraAppUI.java | 29 +++++++-- src/com/android/camera/ui/BottomBar.java | 18 ++++++ src/com/android/camera/ui/MarginDrawable.java | 88 +++++++++++++++++++++++++++ 4 files changed, 139 insertions(+), 6 deletions(-) create mode 100644 src/com/android/camera/ui/MarginDrawable.java diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java index 4c308798a..f7c33d265 100644 --- a/src/com/android/camera/CameraActivity.java +++ b/src/com/android/camera/CameraActivity.java @@ -1432,9 +1432,15 @@ public class CameraActivity extends QuickActivity if (ApiHelper.isLOrHigher()) { getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); } - // We set a background drawable for startup background, reset to black - getWindow().setBackgroundDrawableResource(android.R.color.black); setContentView(R.layout.activity_main); + // A window background is set in styles.xml for the system to show a + // drawable background with gray color and camera icon before the + // activity is created. We set the background to null here to prevent + // overdraw, all views must take care of drawing backgrounds if + // necessary. This call to setBackgroundDrawable must occur after + // setContentView, otherwise a background may be set again from the + // style. + getWindow().setBackgroundDrawable(null); mActionBar = getActionBar(); // set actionbar background to 100% or 50% transparent diff --git a/src/com/android/camera/app/CameraAppUI.java b/src/com/android/camera/app/CameraAppUI.java index 217f8e243..fd998bbbf 100644 --- a/src/com/android/camera/app/CameraAppUI.java +++ b/src/com/android/camera/app/CameraAppUI.java @@ -20,6 +20,7 @@ import android.accessibilityservice.AccessibilityServiceInfo; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Matrix; import android.graphics.RectF; import android.graphics.SurfaceTexture; @@ -51,6 +52,7 @@ import com.android.camera.ui.BottomBar; import com.android.camera.ui.CaptureAnimationOverlay; import com.android.camera.ui.GridLines; import com.android.camera.ui.MainActivityLayout; +import com.android.camera.ui.MarginDrawable; import com.android.camera.ui.ModeListView; import com.android.camera.ui.ModeTransitionView; import com.android.camera.ui.PreviewOverlay; @@ -1078,17 +1080,19 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener, } /** - * Call to stop the preview from being rendered. + * Call to stop the preview from being rendered. Sets the entire capture + * root view to invisible which includes the preview plus focus indicator + * and any other auxiliary views for capture modes. */ public void pausePreviewRendering() { - mTextureView.setVisibility(View.INVISIBLE); + mCameraRootView.setVisibility(View.INVISIBLE); } /** - * Call to begin rendering the preview again. + * Call to begin rendering the preview and auxiliary views again. */ public void resumePreviewRendering() { - mTextureView.setVisibility(View.VISIBLE); + mCameraRootView.setVisibility(View.VISIBLE); } /** @@ -1284,6 +1288,23 @@ public class CameraAppUI implements ModeListView.ModeSwitchListener, } } ); + + // The camera root view may show gaps between the preview and the screen + // if the aspect ratio of the capture doesn't match the screen. We keep + // the window background null and fill in the edges with this overlay + // rather than paint a background behind the entire preview. + final MarginDrawable margins = new MarginDrawable(Color.BLACK); + mCameraRootView.getOverlay().add(margins); + mTextureViewHelper.addAspectRatioChangedListener( + new PreviewStatusListener.PreviewAspectRatioChangedListener() { + @Override + public void onPreviewAspectRatioChanged(float aspectRatio) { + RectF screenArea = mCaptureLayoutHelper.getPreviewRect(); + screenArea.union(mCaptureLayoutHelper.getBottomBarRect()); + margins.setScreen(screenArea); + } + } + ); } /** diff --git a/src/com/android/camera/ui/BottomBar.java b/src/com/android/camera/ui/BottomBar.java index d5fdbf620..0d8250123 100644 --- a/src/com/android/camera/ui/BottomBar.java +++ b/src/com/android/camera/ui/BottomBar.java @@ -304,14 +304,32 @@ public class BottomBar extends FrameLayout { ((ImageButton) findViewById(R.id.retake_button)).setImageLevel(level); } + /** + * Configure the bottom bar to either overlay a live preview, or render off + * the preview. If overlaying the preview, ensure contained drawables have + * reduced opacity and that the bottom bar itself has no background to allow + * the preview to render through. If not overlaying the preview, set + * contained drawables to opaque and ensure that the bottom bar itself has + * a view background, so that varying alpha (i.e. mode list transitions) are + * based upon that background instead of an underlying preview. + * + * @param overlay if true, treat bottom bar as overlaying the preview + */ private void setOverlayBottomBar(boolean overlay) { mOverLayBottomBar = overlay; if (overlay) { setBackgroundAlpha(mBackgroundAlphaOverlay); setButtonImageLevels(1); + // clear background on the containing bottom bar, rather than the + // contained drawables + super.setBackground(null); } else { setBackgroundAlpha(mBackgroundAlphaDefault); setButtonImageLevels(0); + // setBackgroundColor is overridden and delegates to contained + // drawables, call super to set the containing background color in + // this mode. + super.setBackgroundColor(mBackgroundColor); } } diff --git a/src/com/android/camera/ui/MarginDrawable.java b/src/com/android/camera/ui/MarginDrawable.java new file mode 100644 index 000000000..6891bd22d --- /dev/null +++ b/src/com/android/camera/ui/MarginDrawable.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2015 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.camera.ui; + +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; + +/** + * Drawable that takes a {@link RectF} as a screen, and draws around that + * screen to fill margins between the screen and the edge of the {@link Canvas} + * when drawing. + */ +public class MarginDrawable extends Drawable { + + private RectF mScreen = new RectF(0, 0, 0, 0); + private final Paint mPaint; + + public MarginDrawable(int color) { + super(); + + mPaint = new Paint(); + mPaint.setAntiAlias(true); + mPaint.setColor(color); + } + + /** + * Set the screen around which will be drawn margins. If the screen rect + * has no area (zero width or height), no margins will be drawn. + * + * @param screen A {@link RectF} describing the screen dimensions + */ + public void setScreen(RectF screen) { + mScreen.set(screen); + invalidateSelf(); + } + + @Override + public void draw(Canvas canvas) { + RectF s = mScreen; + if (s.top < s.bottom && s.left < s.right) { + Rect cb = canvas.getClipBounds(); + if (s.top > 0) { + canvas.drawRect(0, 0, cb.right, s.top + 1, mPaint); + } + if (s.left > 0) { + canvas.drawRect(0, s.top, s.left + 1, s.bottom, mPaint); + } + if (s.right < cb.right) { + canvas.drawRect(s.right - 1, s.top, cb.right, s.bottom, mPaint); + } + if (s.bottom < cb.bottom) { + canvas.drawRect(0, s.bottom - 1, cb.right, cb.bottom, mPaint); + } + } + } + + @Override + public void setAlpha(int alpha) { + } + + @Override + public void setColorFilter(ColorFilter cf) { + } + + @Override + public int getOpacity() { + return PixelFormat.OPAQUE; + } +} -- 2.11.0