如何使 SurfaceView 具有透明背景?
Posted
技术标签:
【中文标题】如何使 SurfaceView 具有透明背景?【英文标题】:How to make SurfaceView with transparent background? 【发布时间】:2012-01-13 12:46:33 【问题描述】:我有简单的布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/RelativeLayout1"
android:layout_
android:layout_
android:background="@drawable/backgroundtimer"
android:orientation="vertical" >
<TextView
android:id="@+id/TextView1"
android:layout_
android:layout_
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="@string/hello" />
<com.fmech.zenclock.surface.ZenClockSurface
android:id="@+id/zenClockSurface1"
android:layout_
android:layout_
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"/>
</RelativeLayout>
还有一个 ZenClockSurface 类
package com.fmech.zenclock.surface;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.PixelFormat;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class ZenClockSurface extends SurfaceView implements SurfaceHolder.Callback
private DrawClock drawClock;
public ZenClockSurface(Context context, AttributeSet attrs, int defStyle)
super(context, attrs, defStyle);
this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
getHolder().addCallback(this);
public ZenClockSurface(Context context)
super(context);
this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
getHolder().addCallback(this);
public ZenClockSurface(Context context, AttributeSet attrs)
super(context, attrs);
this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
getHolder().addCallback(this);
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height)
// TODO Auto-generated method stub
@Override
public void surfaceCreated(SurfaceHolder holder)
//this.getHolder().setFormat(PixelFormat.TRANSPARENT);
drawClock = new DrawClock(getHolder(), getResources());
drawClock.setRunning(true);
drawClock.start();
@Override
public void surfaceDestroyed(SurfaceHolder holder)
boolean retry = true;
// завершаем работу потока
drawClock.setRunning(false);
while (retry)
try
drawClock.join();
retry = false;
catch (InterruptedException e)
class DrawClock extends Thread
private boolean runFlag = false;
private SurfaceHolder surfaceHolder;
private Bitmap picture;
private Matrix matrix;
private long prevTime;
private Paint painter;
public DrawClock(SurfaceHolder surfaceHolder, Resources resources)
this.surfaceHolder = surfaceHolder;
this.surfaceHolder.setFormat(PixelFormat.TRANSLUCENT);
picture = BitmapFactory.decodeResource(resources, R.drawable.ic_launcher);
matrix = new Matrix();
this.painter=new Paint();
this.painter.setStyle(Paint.Style.FILL);
public void setRunning(boolean run)
runFlag = run;
@Override
public void run()
Canvas canvas;
while (runFlag)
matrix.preRotate(1.0f, picture.getWidth() / 2, picture.getHeight() / 2);
canvas = null;
try
//surfaceHolder.getSurface().setAlpha(0.5f);
canvas = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder)
canvas.drawColor(Color.TRANSPARENT);
canvas.drawBitmap(picture, matrix, this.painter);
finally
if (canvas != null)
surfaceHolder.unlockCanvasAndPost(canvas);
活动代码
package com.fmech.zenclock.surface;
import android.app.Activity;
import android.graphics.PixelFormat;
import android.os.Bundle;
public class ZenClockSurfaceActivity extends Activity
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
setContentView(R.layout.main);
我想要 android 图片的背景颜色是透明的,但我得到黑色背景。
我在 RelativeLayout 上有一些图片,但 SurfaceView 旋转 Android 图标不透明。
我怎样才能做到透明?
【问题讨论】:
我忘了在两个构造函数中都添加 this.getHolder().setFormat(PixelFormat.TRANSLUCENT); 【参考方案1】:是的,我做到了,我解决了问题
活动代码
package com.fmech.zenclock.surface;
import android.app.Activity;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class ZenClockSurfaceActivity extends Activity
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ZenClockSurface sfvTrack = (ZenClockSurface)findViewById(R.id.zenClockSurface1);
sfvTrack.setZOrderOnTop(true); // necessary
SurfaceHolder sfhTrack = sfvTrack.getHolder();
sfhTrack.setFormat(PixelFormat.TRANSLUCENT);
表面代码
package com.fmech.zenclock.surface;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.PixelFormat;
import android.graphics.Region;
import android.util.AttributeSet;
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class ZenClockSurface extends SurfaceView implements
SurfaceHolder.Callback
private DrawClock drawClock;
public ZenClockSurface(Context context, AttributeSet attrs, int defStyle)
super(context, attrs, defStyle);
getHolder().addCallback(this);
public ZenClockSurface(Context context)
super(context);
getHolder().addCallback(this);
public ZenClockSurface(Context context, AttributeSet attrs)
super(context, attrs);
getHolder().addCallback(this);
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height)
@Override
public void surfaceCreated(SurfaceHolder holder)
drawClock = new DrawClock(getHolder(), getResources());
drawClock.setRunning(true);
drawClock.start();
@Override
public void surfaceDestroyed(SurfaceHolder holder)
boolean retry = true;
drawClock.setRunning(false);
while (retry)
try
drawClock.join();
retry = false;
catch (InterruptedException e)
class DrawClock extends Thread
private boolean runFlag = false;
private SurfaceHolder surfaceHolder;
private Bitmap picture;
private Matrix matrix;
private Paint painter;
public DrawClock(SurfaceHolder surfaceHolder, Resources resources)
this.surfaceHolder = surfaceHolder;
picture = BitmapFactory.decodeResource(resources,
R.drawable.ic_launcher);
matrix = new Matrix();
this.painter = new Paint();
this.painter.setStyle(Paint.Style.FILL);
this.painter.setAntiAlias(true);
this.painter.setFilterBitmap(true);
public void setRunning(boolean run)
runFlag = run;
@Override
public void run()
Canvas canvas;
while (runFlag)
matrix.preRotate(1.0f, picture.getWidth() / 2,
picture.getHeight() / 2);
canvas = null;
try
canvas = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder)
canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
canvas.drawBitmap(picture, matrix, this.painter);
catch (IllegalArgumentException e)
// TODO Auto-generated catch block
e.printStackTrace();
finally
if (canvas != null)
surfaceHolder.unlockCanvasAndPost(canvas);
成功了。
【讨论】:
drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);非常感谢,我已经找了好几个小时了!!我以为 drawColor(Color.TRANSPARENT);会工作....但它没有,你的解决方案救了我..! 它对我不起作用。我已将布局的背景设置为颜色#f0f0f0,但表面视图的背景仍然是黑色。 @Dmitry Nelepov:我尝试了相同的代码。但对我没有用。 surfaceview 的颜色仍然是黑色。 我得到的只是一个黑色的表面,没有别的,有什么帮助吗?【参考方案2】:在 API 3 和 4 中,您不能在 SurfaceView
后面添加任何内容。引用 Dianne Hackborn:
表面视图实际上是在您的窗户后面,并且在窗户上打了一个洞让您看到它。因此,您可以将东西放在窗口中,但窗口中的任何内容都不会出现在它后面。
http://groups.google.com/group/android-developers/browse_thread/thread/8d88ef9bb22da574
从 API 5 开始,您可以使用 setZOrderOnTop
。诀窍是您必须在构造函数中执行此操作,以便在视图附加到窗口之前调用它:
public ZenClockSurface(Context context, AttributeSet attrs)
super(context, attrs);
setZOrderOnTop(true);
SurfaceHolder holder = getHolder();
holder.setFormat(PixelFormat.TRANSLUCENT);
【讨论】:
我不正确。活动的下一个变化使 SorfaceView 透明 public void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState);设置内容视图(R.layout.main); ZenClockSurface sfvTrack = (ZenClockSurface)findViewById(R.id.zenClockSurface1); sfvTrack.setZOrderOnTop(true); // 必要的 SurfaceHolder sfhTrack = sfvTrack.getHolder(); sfhTrack.setFormat(PixelFormat.TRANSLUCENT); 但我还是有问题,现在轮到我了 - 图片是黑色的网站。 感谢您指出setZOrderOnTop
,Rainwork!我已经编辑了我的答案。让我知道它是否适合您。
setZOrderOnTop - 它解决了问题,但并不完全。然后图像变成黑色“幽灵”背景。我回答了我的问题,并提供了完整的代码,这对我来说很好。
我建议使用 setZOrderMediaOverlay(true);而不是 setZOrderOnTop(true);因为 setZOrderMediaOverlay 使它像一个普通视图一样工作,它可以在任何视图的后面和上面。以上是关于如何使 SurfaceView 具有透明背景?的主要内容,如果未能解决你的问题,请参考以下文章
如何使 Android BottomNavigationView 背景透明?