How to make SurfaceView with transparent backgroun

2019-02-05 03:12发布

问题:

I have simple layout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/RelativeLayout1"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/backgroundtimer"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/TextView1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:text="@string/hello" />

    <com.fmech.zenclock.surface.ZenClockSurface
        android:id="@+id/zenClockSurface1"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"/>

</RelativeLayout>

And a have ZenClockSurface class

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);
                    }
                }
            }
        }
    }
}

And code of activity

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);


    }
}

I want what background color of android picture was tranparent but i get black background.

I have background on RelativeLayout with some picture bu SurfaceView rotate Android icon with no transparent.

How i can do transparent?

回答1:

Yeah, i did it i solve problem

Activity code

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);

    }
}

Surface Code

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);
                    }
                }
            }
        }
    }
}

It's work.



回答2:

In API 3 and 4, you cannot put anything behind a SurfaceView. Quoting Dianne Hackborn:

The surface view is actually BEHIND your window, and a hole punched in the window for you to see it. You thus can put things on top of it in your window, but nothing in your window can appear behind it.

http://groups.google.com/group/android-developers/browse_thread/thread/8d88ef9bb22da574


From API 5 onwards you can use setZOrderOnTop. The trick is that you have to do it in your constructor so it gets called before the view is attached to the window:

public ZenClockSurface(Context context, AttributeSet attrs) {
  super(context, attrs);

  setZOrderOnTop(true);

  SurfaceHolder holder = getHolder();
  holder.setFormat(PixelFormat.TRANSLUCENT);
}