Revert "Support alpha for SurfaceView"

Revert submission 19562144-surfaceview-alpha

Reason for revert: Presubmit breakage b/245651921
Reverted Changes:
I7510a3a6c:Add CTS for applying alpha for SurfaceView
Ibc14b18f1:Support alpha for SurfaceView

Change-Id: I498c98951a53e6bb1c1251dceb9d150311b07cc8
This commit is contained in:
Samiul Islam
2022-09-08 14:15:33 +00:00
parent 914e750867
commit 3fde6cee3c
14 changed files with 94 additions and 273 deletions

View File

@@ -107,14 +107,6 @@ import java.util.function.Consumer;
* and scaling a SurfaceView on screen will not cause rendering artifacts. Such
* artifacts may occur on previous versions of the platform when its window is
* positioned asynchronously.</p>
*
* <p class="note"><strong>Note:</strong> Starting in platform version
* {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, SurfaceView will support arbitrary
* alpha blending. Prior platform versions ignored alpha values on the SurfaceView if they were
* between 0 and 1. If the SurfaceView is configured with Z-above, then the alpha is applied
* directly to the Surface. If the SurfaceView is configured with Z-below, then the alpha is
* applied to the hole punch directly. Note that when using Z-below, overlapping SurfaceViews
* may not blend properly as a consequence of not applying alpha to the surface content directly.
*/
public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCallback {
private static final String TAG = "SurfaceView";
@@ -154,7 +146,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
Paint mRoundedViewportPaint;
int mSubLayer = APPLICATION_MEDIA_SUBLAYER;
int mRequestedSubLayer = APPLICATION_MEDIA_SUBLAYER;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
boolean mIsCreating = false;
@@ -186,7 +177,8 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
@UnsupportedAppUsage
int mRequestedFormat = PixelFormat.RGB_565;
float mAlpha = 1f;
boolean mUseAlpha = false;
float mSurfaceAlpha = 1f;
boolean mClipSurfaceToBounds;
int mBackgroundColor = Color.BLACK;
@@ -343,25 +335,58 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
* @hide
*/
public void setUseAlpha() {
// TODO(b/241474646): Remove me
return;
if (!mUseAlpha) {
mUseAlpha = true;
updateSurfaceAlpha();
}
}
@Override
public void setAlpha(float alpha) {
// Sets the opacity of the view to a value, where 0 means the view is completely transparent
// and 1 means the view is completely opaque.
//
// Note: Alpha value of this view is ignored by default. To enable alpha blending, you need
// to call setUseAlpha() as well.
// This view doesn't support translucent opacity if the view is located z-below, since the
// logic to punch a hole in the view hierarchy cannot handle such case. See also
// #clearSurfaceViewPort(Canvas)
if (DEBUG) {
Log.d(TAG, System.identityHashCode(this)
+ " setAlpha: alpha=" + alpha);
+ " setAlpha: mUseAlpha = " + mUseAlpha + " alpha=" + alpha);
}
super.setAlpha(alpha);
updateSurfaceAlpha();
}
@Override
protected boolean onSetAlpha(int alpha) {
if (Math.round(mAlpha * 255) != alpha) {
updateSurface();
private float getFixedAlpha() {
// Compute alpha value to be set on the underlying surface.
final float alpha = getAlpha();
return mUseAlpha && (mSubLayer > 0 || alpha == 0f) ? alpha : 1f;
}
private void updateSurfaceAlpha() {
if (!mUseAlpha || !mHaveFrame || mSurfaceControl == null) {
return;
}
final float viewAlpha = getAlpha();
if (mSubLayer < 0 && 0f < viewAlpha && viewAlpha < 1f) {
Log.w(TAG, System.identityHashCode(this)
+ " updateSurfaceAlpha:"
+ " translucent color is not supported for a surface placed z-below.");
}
final ViewRootImpl viewRoot = getViewRootImpl();
if (viewRoot == null) {
return;
}
final float alpha = getFixedAlpha();
if (alpha != mSurfaceAlpha) {
final Transaction transaction = new Transaction();
transaction.setAlpha(mSurfaceControl, alpha);
viewRoot.applyTransactionOnDraw(transaction);
damageInParent();
mSurfaceAlpha = alpha;
}
return true;
}
private void performDrawFinished() {
@@ -509,15 +534,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
invalidate();
}
@Override
public boolean hasOverlappingRendering() {
// SurfaceViews only alpha composite by modulating the Surface alpha for Z-above, or
// applying alpha on the hole punch for Z-below - no deferral to a layer is necessary.
return false;
}
private void clearSurfaceViewPort(Canvas canvas) {
final float alpha = getAlpha();
if (mCornerRadius > 0f) {
canvas.getClipBounds(mTmpRect);
if (mClipSurfaceToBounds && mClipBounds != null) {
@@ -529,11 +546,10 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
mTmpRect.right,
mTmpRect.bottom,
mCornerRadius,
mCornerRadius,
alpha
mCornerRadius
);
} else {
canvas.punchHole(0f, 0f, getWidth(), getHeight(), 0f, 0f, alpha);
canvas.punchHole(0f, 0f, getWidth(), getHeight(), 0f, 0f);
}
}
@@ -636,10 +652,10 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
} else {
subLayer = APPLICATION_MEDIA_SUBLAYER;
}
if (mRequestedSubLayer == subLayer) {
if (mSubLayer == subLayer) {
return false;
}
mRequestedSubLayer = subLayer;
mSubLayer = subLayer;
if (!allowDynamicChange) {
return false;
@@ -651,8 +667,9 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
if (viewRoot == null) {
return true;
}
updateSurface();
final Transaction transaction = new SurfaceControl.Transaction();
updateRelativeZ(transaction);
viewRoot.applyTransactionOnDraw(transaction);
invalidate();
return true;
}
@@ -705,7 +722,8 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
}
private void releaseSurfaces(boolean releaseSurfacePackage) {
mAlpha = 1f;
mSurfaceAlpha = 1f;
synchronized (mSurfaceControlLock) {
mSurface.destroy();
if (mBlastBufferQueue != null) {
@@ -752,7 +770,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
}
private boolean performSurfaceTransaction(ViewRootImpl viewRoot, Translator translator,
boolean creating, boolean sizeChanged, boolean hintChanged, boolean relativeZChanged,
boolean creating, boolean sizeChanged, boolean hintChanged,
Transaction surfaceUpdateTransaction) {
boolean realSizeChanged = false;
@@ -782,20 +800,14 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
surfaceUpdateTransaction.hide(mSurfaceControl);
}
updateBackgroundVisibility(surfaceUpdateTransaction);
updateBackgroundColor(surfaceUpdateTransaction);
if (isAboveParent()) {
float alpha = getAlpha();
if (mUseAlpha) {
float alpha = getFixedAlpha();
surfaceUpdateTransaction.setAlpha(mSurfaceControl, alpha);
}
if (relativeZChanged) {
if (!isAboveParent()) {
// If we're moving from z-above to z-below, then restore the surface alpha back to 1
// and let the holepunch drive visibility and blending.
surfaceUpdateTransaction.setAlpha(mSurfaceControl, 1.f);
}
updateRelativeZ(surfaceUpdateTransaction);
mSurfaceAlpha = alpha;
}
surfaceUpdateTransaction.setCornerRadius(mSurfaceControl, mCornerRadius);
@@ -861,7 +873,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
} finally {
mSurfaceLock.unlock();
}
return realSizeChanged;
}
@@ -895,10 +906,10 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
int myHeight = mRequestedHeight;
if (myHeight <= 0) myHeight = getHeight();
final float alpha = getAlpha();
final float alpha = getFixedAlpha();
final boolean formatChanged = mFormat != mRequestedFormat;
final boolean visibleChanged = mVisible != mRequestedVisible;
final boolean alphaChanged = mAlpha != alpha;
final boolean alphaChanged = mSurfaceAlpha != alpha;
final boolean creating = (mSurfaceControl == null || formatChanged || visibleChanged)
&& mRequestedVisible;
final boolean sizeChanged = mSurfaceWidth != myWidth || mSurfaceHeight != myHeight;
@@ -910,17 +921,17 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|| getHeight() != mScreenRect.height();
final boolean hintChanged = (viewRoot.getBufferTransformHint() != mTransformHint)
&& mRequestedVisible;
final boolean relativeZChanged = mSubLayer != mRequestedSubLayer;
if (creating || formatChanged || sizeChanged || visibleChanged
|| alphaChanged || windowVisibleChanged || positionChanged
|| layoutSizeChanged || hintChanged || relativeZChanged) {
if (creating || formatChanged || sizeChanged || visibleChanged ||
(mUseAlpha && alphaChanged) || windowVisibleChanged ||
positionChanged || layoutSizeChanged || hintChanged) {
if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
+ "Changes: creating=" + creating
+ " format=" + formatChanged + " size=" + sizeChanged
+ " visible=" + visibleChanged + " alpha=" + alphaChanged
+ " hint=" + hintChanged
+ " mUseAlpha=" + mUseAlpha
+ " visible=" + visibleChanged
+ " left=" + (mWindowSpaceLeft != mLocation[0])
+ " top=" + (mWindowSpaceTop != mLocation[1]));
@@ -932,10 +943,8 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
mSurfaceWidth = myWidth;
mSurfaceHeight = myHeight;
mFormat = mRequestedFormat;
mAlpha = alpha;
mLastWindowVisibility = mWindowVisibility;
mTransformHint = viewRoot.getBufferTransformHint();
mSubLayer = mRequestedSubLayer;
mScreenRect.left = mWindowSpaceLeft;
mScreenRect.top = mWindowSpaceTop;
@@ -959,7 +968,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
}
final boolean redrawNeeded = sizeChanged || creating || hintChanged
|| (mVisible && !mDrawFinished) || alphaChanged || relativeZChanged;
|| (mVisible && !mDrawFinished);
boolean shouldSyncBuffer =
redrawNeeded && viewRoot.wasRelayoutRequested() && viewRoot.isInLocalSync();
SyncBufferTransactionCallback syncBufferTransactionCallback = null;
@@ -970,9 +979,8 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
syncBufferTransactionCallback::onTransactionReady);
}
final boolean realSizeChanged = performSurfaceTransaction(viewRoot, translator,
creating, sizeChanged, hintChanged, relativeZChanged,
surfaceUpdateTransaction);
final boolean realSizeChanged = performSurfaceTransaction(viewRoot,
translator, creating, sizeChanged, hintChanged, surfaceUpdateTransaction);
try {
SurfaceHolder.Callback[] callbacks = null;

View File

@@ -670,9 +670,8 @@ public abstract class BaseCanvas {
/**
* @hide
*/
public void punchHole(float left, float top, float right, float bottom, float rx, float ry,
float alpha) {
nPunchHole(mNativeCanvasWrapper, left, top, right, bottom, rx, ry, alpha);
public void punchHole(float left, float top, float right, float bottom, float rx, float ry) {
nPunchHole(mNativeCanvasWrapper, left, top, right, bottom, rx, ry);
}
/**
@@ -824,5 +823,5 @@ public abstract class BaseCanvas {
float hOffset, float vOffset, int flags, long nativePaint);
private static native void nPunchHole(long renderer, float left, float top, float right,
float bottom, float rx, float ry, float alpha);
float bottom, float rx, float ry);
}

View File

@@ -610,9 +610,8 @@ public class BaseRecordingCanvas extends Canvas {
* @hide
*/
@Override
public void punchHole(float left, float top, float right, float bottom, float rx, float ry,
float alpha) {
nPunchHole(mNativeCanvasWrapper, left, top, right, bottom, rx, ry, alpha);
public void punchHole(float left, float top, float right, float bottom, float rx, float ry) {
nPunchHole(mNativeCanvasWrapper, left, top, right, bottom, rx, ry);
}
@FastNative
@@ -743,5 +742,5 @@ public class BaseRecordingCanvas extends Canvas {
@FastNative
private static native void nPunchHole(long renderer, float left, float top, float right,
float bottom, float rx, float ry, float alpha);
float bottom, float rx, float ry);
}

View File

@@ -18,7 +18,6 @@
#include "CanvasProperty.h"
#include "NinePatchUtils.h"
#include "SkBlendMode.h"
#include "VectorDrawable.h"
#include "hwui/Bitmap.h"
#include "hwui/MinikinUtils.h"
@@ -252,11 +251,10 @@ const SkiaCanvas::SaveRec* SkiaCanvas::currentSaveRec() const {
return (rec && rec->saveCount == currentSaveCount) ? rec : nullptr;
}
void SkiaCanvas::punchHole(const SkRRect& rect, float alpha) {
void SkiaCanvas::punchHole(const SkRRect& rect) {
SkPaint paint = SkPaint();
paint.setColor(SkColors::kBlack);
paint.setAlphaf(alpha);
paint.setBlendMode(SkBlendMode::kDstOut);
paint.setColor(0);
paint.setBlendMode(SkBlendMode::kClear);
mCanvas->drawRRect(rect, paint);
}

View File

@@ -65,7 +65,7 @@ public:
LOG_ALWAYS_FATAL("SkiaCanvas does not support enableZ");
}
virtual void punchHole(const SkRRect& rect, float alpha) override;
virtual void punchHole(const SkRRect& rect) override;
virtual void setBitmap(const SkBitmap& bitmap) override;

View File

@@ -152,7 +152,7 @@ public:
LOG_ALWAYS_FATAL("Not supported");
}
virtual void punchHole(const SkRRect& rect, float alpha) = 0;
virtual void punchHole(const SkRRect& rect) = 0;
// ----------------------------------------------------------------------------
// Canvas state operations

View File

@@ -713,10 +713,9 @@ static void setCompatibilityVersion(JNIEnv* env, jobject, jint apiLevel) {
}
static void punchHole(JNIEnv* env, jobject, jlong canvasPtr, jfloat left, jfloat top, jfloat right,
jfloat bottom, jfloat rx, jfloat ry, jfloat alpha) {
jfloat bottom, jfloat rx, jfloat ry) {
auto canvas = reinterpret_cast<Canvas*>(canvasPtr);
canvas->punchHole(SkRRect::MakeRectXY(SkRect::MakeLTRB(left, top, right, bottom), rx, ry),
alpha);
canvas->punchHole(SkRRect::MakeRectXY(SkRect::MakeLTRB(left, top, right, bottom), rx, ry));
}
}; // namespace CanvasJNI
@@ -791,7 +790,7 @@ static const JNINativeMethod gDrawMethods[] = {
{"nDrawTextRun","(JLjava/lang/String;IIIIFFZJ)V", (void*) CanvasJNI::drawTextRunString},
{"nDrawTextOnPath","(J[CIIJFFIJ)V", (void*) CanvasJNI::drawTextOnPathChars},
{"nDrawTextOnPath","(JLjava/lang/String;JFFIJ)V", (void*) CanvasJNI::drawTextOnPathString},
{"nPunchHole", "(JFFFFFFF)V", (void*) CanvasJNI::punchHole}
{"nPunchHole", "(JFFFFFF)V", (void*) CanvasJNI::punchHole}
};
int register_android_graphics_Canvas(JNIEnv* env) {

View File

@@ -201,7 +201,6 @@ protected:
paint.setAlpha((uint8_t)paint.getAlpha() * mAlpha);
return true;
}
void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override {
// We unroll the drawable using "this" canvas, so that draw calls contained inside will
// get their alpha applied. The default SkPaintFilterCanvas::onDrawDrawable does not unroll.
@@ -293,7 +292,7 @@ void RenderNodeDrawable::drawContent(SkCanvas* canvas) const {
// with the same canvas transformation + clip into the target
// canvas then draw the layer on top
if (renderNode->hasHolePunches()) {
TransformCanvas transformCanvas(canvas, SkBlendMode::kDstOut);
TransformCanvas transformCanvas(canvas, SkBlendMode::kClear);
displayList->draw(&transformCanvas);
}
canvas->drawImageRect(snapshotImage, SkRect::Make(srcBounds),

View File

@@ -69,22 +69,20 @@ void SkiaRecordingCanvas::initDisplayList(uirenderer::RenderNode* renderNode, in
mDisplayList->setHasHolePunches(false);
}
void SkiaRecordingCanvas::punchHole(const SkRRect& rect, float alpha) {
// Add the marker annotation to allow HWUI to determine the current
// clip/transformation and alpha should be applied
void SkiaRecordingCanvas::punchHole(const SkRRect& rect) {
// Add the marker annotation to allow HWUI to determine where the current
// clip/transformation should be applied
SkVector vector = rect.getSimpleRadii();
float data[3];
float data[2];
data[0] = vector.x();
data[1] = vector.y();
data[2] = alpha;
mRecorder.drawAnnotation(rect.rect(), HOLE_PUNCH_ANNOTATION.c_str(),
SkData::MakeWithCopy(data, sizeof(data)));
SkData::MakeWithCopy(data, 2 * sizeof(float)));
// Clear the current rect within the layer itself
SkPaint paint = SkPaint();
paint.setColor(SkColors::kBlack);
paint.setAlphaf(alpha);
paint.setBlendMode(SkBlendMode::kDstOut);
paint.setColor(0);
paint.setBlendMode(SkBlendMode::kClear);
mRecorder.drawRRect(rect, paint);
mDisplayList->setHasHolePunches(true);

View File

@@ -50,7 +50,7 @@ public:
initDisplayList(renderNode, width, height);
}
virtual void punchHole(const SkRRect& rect, float alpha) override;
virtual void punchHole(const SkRRect& rect) override;
virtual void finishRecording(uirenderer::RenderNode* destination) override;
std::unique_ptr<SkiaDisplayList> finishRecording();

View File

@@ -29,15 +29,13 @@ using namespace android::uirenderer::skiapipeline;
void TransformCanvas::onDrawAnnotation(const SkRect& rect, const char* key, SkData* value) {
if (HOLE_PUNCH_ANNOTATION == key) {
auto* rectParams = reinterpret_cast<const float*>(value->data());
const float radiusX = rectParams[0];
const float radiusY = rectParams[1];
const float alpha = rectParams[2];
float radiusX = rectParams[0];
float radiusY = rectParams[1];
SkRRect roundRect = SkRRect::MakeRectXY(rect, radiusX, radiusY);
SkPaint paint;
paint.setColor(SkColors::kBlack);
paint.setBlendMode(mHolePunchBlendMode);
paint.setAlphaf(alpha);
mWrappedCanvas->drawRRect(roundRect, paint);
}
}

View File

@@ -138,7 +138,7 @@ private:
roundRectPaint.setColor(Color::White);
if (addHolePunch) {
// Punch a hole but then cover it up, we don't want to actually see it
canvas.punchHole(SkRRect::MakeRect(SkRect::MakeWH(itemWidth, itemHeight)), 1.f);
canvas.punchHole(SkRRect::MakeRect(SkRect::MakeWH(itemWidth, itemHeight)));
}
canvas.drawRoundRect(0, 0, itemWidth, itemHeight, dp(6), dp(6), roundRectPaint);
@@ -235,4 +235,4 @@ class StretchyUniformLayerListViewHolePunch : public StretchyListViewAnimation {
StretchEffectBehavior stretchBehavior() override { return StretchEffectBehavior::UniformScale; }
bool haveHolePunch() override { return true; }
bool forceLayer() override { return true; }
};
};

View File

@@ -436,15 +436,6 @@
</intent-filter>
</activity>
<activity android:name="SurfaceViewAlphaActivity"
android:label="SurfaceView/SurfaceView with Alpha"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="com.android.test.hwui.TEST"/>
</intent-filter>
</activity>
<activity android:name=".PenStylusActivity"
android:label="Pen/Draw"
android:exported="true">

View File

@@ -1,168 +0,0 @@
/*
* Copyright 2022 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.test.hwui;
import android.app.Activity;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
public class SurfaceViewAlphaActivity extends Activity implements Callback {
SurfaceView mSurfaceView;
private enum ZOrder {
ABOVE,
BELOW
}
private float mAlpha = 127f / 255f;
private ZOrder mZOrder = ZOrder.BELOW;
private String getAlphaText() {
return "Alpha: " + mAlpha;
}
private void toggleZOrder() {
if (ZOrder.ABOVE.equals(mZOrder)) {
mZOrder = ZOrder.BELOW;
} else {
mZOrder = ZOrder.ABOVE;
}
}
// Overlaps a blue view on the left, then the SurfaceView in the center, then a blue view on the
// right.
private void overlapViews(SurfaceView view, LinearLayout parent) {
float density = getResources().getDisplayMetrics().density;
int surfaceViewSize = (int) (200 * density);
int blueViewSize = (int) (surfaceViewSize * 2 / 3f);
int totalSize = (int) (surfaceViewSize * 5 / 3f);
RelativeLayout overlapLayout = new RelativeLayout(this);
RelativeLayout.LayoutParams leftViewLayoutParams = new RelativeLayout.LayoutParams(
blueViewSize, surfaceViewSize);
leftViewLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
View leftBlueView = new View(this);
leftBlueView.setBackgroundColor(Color.BLUE);
overlapLayout.addView(leftBlueView, leftViewLayoutParams);
RelativeLayout.LayoutParams sVLayoutParams = new RelativeLayout.LayoutParams(
surfaceViewSize, surfaceViewSize);
sVLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
overlapLayout.addView(view, sVLayoutParams);
RelativeLayout.LayoutParams rightViewLayoutParams = new RelativeLayout.LayoutParams(
blueViewSize, surfaceViewSize);
rightViewLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
View rightBlueView = new View(this);
rightBlueView.setBackgroundColor(Color.BLUE);
overlapLayout.addView(rightBlueView, rightViewLayoutParams);
parent.addView(overlapLayout, new LinearLayout.LayoutParams(
totalSize, surfaceViewSize));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSurfaceView = new SurfaceView(this);
mSurfaceView.getHolder().addCallback(this);
mSurfaceView.setAlpha(mAlpha);
LinearLayout content = new LinearLayout(this);
content.setOrientation(LinearLayout.VERTICAL);
TextView alphaText = new TextView(this);
alphaText.setText(getAlphaText());
SeekBar alphaToggle = new SeekBar(this);
alphaToggle.setMin(0);
alphaToggle.setMax(255);
alphaToggle.setProgress(Math.round(mAlpha * 255));
alphaToggle.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
mAlpha = progress / 255f;
alphaText.setText(getAlphaText());
mSurfaceView.setAlpha(mAlpha);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
content.addView(alphaText, new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
content.addView(alphaToggle, new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
Button button = new Button(this);
button.setText("Z " + mZOrder.toString());
button.setOnClickListener(v -> {
toggleZOrder();
mSurfaceView.setZOrderOnTop(ZOrder.ABOVE.equals(mZOrder));
button.setText("Z " + mZOrder.toString());
});
content.addView(button, new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
overlapViews(mSurfaceView, content);
setContentView(content);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Canvas canvas = holder.lockCanvas();
canvas.drawColor(Color.RED);
holder.unlockCanvasAndPost(canvas);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}