Android: Programatically Add UI Elements to a View - android

My view is written as follow:
package com.mycompany;
import android.view.View;
import java.util.concurrent.TimeUnit;
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.AttributeSet;
import android.graphics.Paint;
import android.graphics.Point;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.widget.*;
public class GameEngineView extends View implements SensorEventListener {
GameLoop gameloop;
String txt_acc;
float accY;
ArrayList<Point> bugPath;
private SensorManager sensorManager;
private class GameLoop extends Thread {
private volatile boolean running = true;
public void run() {
while (running) {
try {
TimeUnit.MILLISECONDS.sleep(1);
postInvalidate();
pause();
} catch (InterruptedException ex) {
running = false;
}
}
}
public void pause() {
running = false;
}
public void start() {
running = true;
run();
}
public void safeStop() {
running = false;
interrupt();
}
}
public void unload() {
gameloop.safeStop();
}
public GameEngineView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
init(context);
}
public GameEngineView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init(context);
}
public GameEngineView(Context context) {
super(context);
// TODO Auto-generated constructor stub
init(context);
}
private void init(Context context) {
txt_acc = "";
// Adding SENSOR
sensorManager=(SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
// add listener. The listener will be HelloAndroid (this) class
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL);
// Adding UI Elements : How ?
Button btn_camera = new Button(context);
btn_camera.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT));
btn_camera.setClickable(true);
btn_camera.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
System.out.println("clicked the camera.");
}
});
gameloop = new GameLoop();
gameloop.run();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
//super.onMeasure(widthMeasureSpec, heightMeasureSpec);
System.out.println("Width " + widthMeasureSpec);
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
// super.onDraw(canvas);
Paint p = new Paint();
p.setColor(Color.WHITE);
p.setStyle(Paint.Style.FILL);
p.setAntiAlias(true);
p.setTextSize(30);
canvas.drawText("|[ " + txt_acc + " ]|", 50, 500, p);
gameloop.start();
}
public void onAccuracyChanged(Sensor sensor,int accuracy){
}
public void onSensorChanged(SensorEvent event){
if(event.sensor.getType()==Sensor.TYPE_ACCELEROMETER){
//float x=event.values[0];
accY =event.values[1];
//float z=event.values[2];
txt_acc = "" + accY;
}
}
}
I would like to add a Button to the scene, but I don't know how to. Can anybody give me some lights?
UPDATE: Here is my Activity :
public class MyActivity extends Activity {
private GameEngineView gameEngine;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// add Game Engine
gameEngine = new GameEngineView(this);
setContentView(gameEngine);
gameEngine.requestFocus();
}
}
And I am following the this tutorial .

detailListView = (LinearLayout) findViewById(R.id.DetailsLinearLayout); // Find the layout where you want to add button
Button button = new Button(this);
button.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT
,ViewGroup.LayoutParams.WRAP_CONTENT));
detailListView.addView(button);//add view to add

Related

My onDraw() method is never called

My issue is that no matter what I do, no matter how many questions and answers I read through on the internet, I cant get a simple rectangle to draw on my android device screen. Let me rephrase that, it shows up on screen but it wont change. I cant get an animation to update. onDraw() never calls multiple times, just once on startup. why? Here is my view objects code:
package prospect_industries.es;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
public class TestView extends View {
//Variables
public static final int SIZE = 300;
public float TOP = 0.0f;
public float LEFT = 0.0f;
public float RIGHT = 100f;
public float BOTTOM = 100f;
private Paint rectanglePaint;
private RectF rect1;
//Constructors
public TestView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
init();
}
public TestView(final Context context, final AttributeSet attrs) {
super(context, attrs, 0);
init();
}
public TestView(final Context context) {
super(context, null, 0);
init();
}
//View methods
#Override
protected void onDraw(final Canvas canvas){
canvas.drawRect(rect1, rectanglePaint);
Log.i("test1", "in onDraw");
}
#Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
final int chosenWidth = chooseDimension(widthMode, widthSize);
final int chosenHeight = chooseDimension(heightMode, heightSize);
setMeasuredDimension(chosenWidth, chosenHeight);
Log.i("test1", String.valueOf(chosenWidth));
Log.i("test1",String.valueOf(chosenHeight));
}
//Class Methods
private int chooseDimension(final int mode, final int size) {
switch (mode) {
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
return size;
case MeasureSpec.UNSPECIFIED:
default:
return getDefaultDimension();
}
}
private int getDefaultDimension() { return SIZE; }
private void init(){
requestFocus();
rectanglePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
rectanglePaint.setColor(-1);
rectanglePaint.setStyle(Paint.Style.FILL);
rect1 = new RectF(LEFT, TOP, RIGHT, BOTTOM);
}
public void update() {
RIGHT += 10;
BOTTOM += 10;
rect1 = new RectF(LEFT, TOP, RIGHT, BOTTOM);
invalidate();
Log.i("test1", "in update");
}
}
Here is my main class which has a few methods for other things Im working on as well as a timer which calls the update() method inside of my test view object.
package prospect_industries.es;
import android.app.Activity;
import android.content.Context;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
public class MainActivity extends Activity {
private boolean setup = false;
public int waitDelay = 1000; //Milliseconds - currently 1 second
private Timer checkTime;
private TimerTask listen;
private MediaRecorder mRecorder;
//Splashscreen
private Timer splashScreen;
private int waitTime = 3000; //3 seconds
private GaugeView mGaugeView;
private final Random RAND = new Random();
private TestView testview;
private SurfaceHolder surfaceHolder;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_main);
//mGaugeView = (GaugeView) findViewById(R.id.gauge_view);
testview = (TestView) findViewById(R.id.test_view);
}
#Override
public void onStart() {
super.onStart();
//Timers
//1 second wait tick
checkTime = new Timer();
checkTime.schedule(new TimerTask() {
public void run() {
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
//mGaugeView.setTargetValue(RAND.nextInt(101));
testview.update();
}
});
}
}, 0, waitDelay);
//Set splash screen wait timer
splashScreen = new Timer();
splashScreen.schedule(new TimerTask() {
public void run() {
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
setContentView(R.layout.content_main);
}
});
splashScreen.cancel();
}
}, waitTime);
//set welcome screen
setContentView(R.layout.activity_welcome);
}
#Override
public void onStop() {
super.onStop();
if(checkTime != null) {
checkTime.cancel();
stop();
}
}
public void stop() {
if (mRecorder != null) {
mRecorder.stop();
mRecorder.release();
mRecorder = null;
}
}
public double getAmplitude() {
if (mRecorder != null)
return mRecorder.getMaxAmplitude();
else
return 0;
}
public void checkSound(){
if (mRecorder == null) {
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mRecorder.setOutputFile("/dev/null");
try {
mRecorder.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
mRecorder.start();
}
}
private static class MainView extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder surfaceHolder;
public MainView(Context context) {
super(context);
surfaceHolder = getHolder();
surfaceHolder.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) {
// TODO Auto-generated method stub
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
}
}
Lastly, here is the xml layout file which loads in the test view object.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#103681"
tools:context="prospect_industries.es.MainActivity">
<prospect_industries.es.TestView
android:layout_width="200dp"
android:layout_height="200dp"
android:id="#+id/test_view"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
I have been looking all over stackExchange for hours but I cant fix my problem, onDraw is only called once and never again no matter what I do. Right now the rectangle should be expanding out but it isnt being redrawn.
The problem is that you initialize the rectangle to be 1px wide and 1px tall and never resize it. You should be able to see 1 white pixel somewhere in the top left corner of your TestView.
Try changing the rect1 size to 0,0,100,100 and see if the problem persists.
public static final float TOP = 0.0f;
public static final float LEFT = 0.0f;
public static final float RIGHT = 100.0f;
public static final float BOTTOM = 100.0f;

Canvas layout with SurfaceView

I was trying to make the image move. The image does not move and sometimes it flickers.
I wanted to make it Runnable. It uses a Surface Holder and s is the bitmap. The canvas sometimes remain still at i=0 or it flickers. How to make it runnable
package com.smiley;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class SmileyView extends SurfaceView implements SurfaceHolder.Callback {
public SmileyView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
holder = getHolder();
s= BitmapFactory.decodeResource(context.getResources(),R.drawable.smiley);
holder.addCallback(this);
}
#Override
public boolean onKeyUp(int keyCode, KeyEvent msg) {
super.onKeyUp(keyCode, msg);
rv.update();
return true;
}
private int i=0;
private Bitmap s;private SurfaceHolder holder;private RenderView rv ;
boolean grun=true;long t=0;
public void resume()
{
rv=new RenderView();
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder arg0) {
// TODO Auto-generated method stub
grun=true;
if(rv!=null)
rv.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
// TODO Auto-generated method stub
try {
grun =false;
rv.join();
rv=null;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
class RenderView extends Thread {
RenderView(){
super();
}
#Override
public void run()
{
SurfaceHolder h=holder;
while(grun)
{
Canvas ca=null;
try{ca = h.lockCanvas(null);
synchronized (h) {
update(); dodraw(ca);
}
}
finally
{
if(ca!=null)
h.unlockCanvasAndPost(ca);
}
}
}
public void dodraw(Canvas canvas)
{ canvas.drawBitmap(s, i, i , null);
canvas.restore();
}
public void update()
{
if(i==0)
i=100;
}
}
}
I made a tutorial for what it seems like you want to do here. You can check it out here. If I had to guess then it might be an issue with not clearing out the canvas. try changing it to (assuming your background is Bitmap backBG)
public void dodraw(Canvas canvas)
{
canvas.drawBitmap(backBG, 0, 0, null);
canvas.drawBitmap(s, i, i , null);
canvas.restore();
}

cant create Region while drawing on android canvas

I have this code
package com.cerbertek;
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Region;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class PlayGameView extends SurfaceView implements SurfaceHolder.Callback {
private CanvasThread canvasthread;
private Context mContext;
private Region firstRec;
private ArrayList<Region> regions;
private class CanvasThread extends Thread {
private SurfaceHolder _holder;
private boolean _run = false;
public CanvasThread(SurfaceHolder surfaceHolder) {
_holder = surfaceHolder;
}
public void setRunning(boolean run) {
_run = run;
}
#Override
public void run() {
Canvas c;
while (_run) {
c = null;
try {
c = _holder.lockCanvas(null);
synchronized (_holder) {
onDraw(c);
}
} finally {
if (c != null) {
_holder.unlockCanvasAndPost(c);
}
}
}
}
}
public PlayGameView (Context context, AttributeSet attrs) {
super(context, attrs);
SurfaceHolder holder = getHolder();
holder.addCallback(this);
canvasthread = new CanvasThread(getHolder());
setFocusable(true);
}
#Override
public void onDraw(Canvas canvas) {
Paint paint = new Paint ();
Bitmap wrench = BitmapFactory.decodeResource(getResources(), R.drawable.wrench);
canvas.drawColor(Color .BLACK);
for(int i = 0; i < 4; i++) {
for(int j = 0; j < 4; j++) {
int left = canvas.getWidth()/2 - wrench.getWidth()*2 + j*wrench.getWidth();
int top = 0 + i*wrench.getHeight();
canvas.drawBitmap(wrench, left, top, null);
Log.d(i + " " + j, left+ " " + top);
Region reg = new Region(left, top, left + wrench.getWidth(), top + wrench.getHeight());
regions.add(reg);
}
}
}
public ArrayList<Region> getRegions() {
return regions;
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
}
#Override
public void surfaceCreated(SurfaceHolder arg0) {
canvasthread.setRunning(true);
canvasthread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
boolean retry = true;
canvasthread.setRunning(false);
while (retry) {
try {
canvasthread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
}
in onDraw() method I want to create a Region and add it to ArrayList, that returning by getRegions() method.
But it now works!
I saw first image and then NullPoiterExeption on regions.add(reg); line.
Please hlp me
In the constructor put:
regions = new ArrayList<Region>();
You were forgetting to initialize it.

android canvas click

there is class, that draws on canvas some field
package com.cerbertek;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Region;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class PlayGameView extends SurfaceView implements SurfaceHolder.Callback {
private CanvasThread canvasthread;
private Context mContext;
private Region firstRec;
private class CanvasThread extends Thread {
private SurfaceHolder _holder;
private boolean _run = false;
public CanvasThread(SurfaceHolder surfaceHolder) {
_holder = surfaceHolder;
}
public void setRunning(boolean run) {
_run = run;
}
#Override
public void run() {
Canvas c;
while (_run) {
c = null;
try {
c = _holder.lockCanvas(null);
synchronized (_holder) {
onDraw(c);
}
} finally {
if (c != null) {
_holder.unlockCanvasAndPost(c);
}
}
}
}
}
public PlayGameView (Context context, AttributeSet attrs) {
super(context, attrs);
SurfaceHolder holder = getHolder();
holder.addCallback(this);
canvasthread = new CanvasThread(getHolder());
setFocusable(true);
}
#Override
public void onDraw(Canvas canvas) {
Paint paint = new Paint ();
Bitmap wrench = BitmapFactory.decodeResource(getResources(), R.drawable.wrench);
canvas.drawColor(Color .BLACK);
for(int i = 0; i < 4; i++) {
for(int j = 0; j < 4; j++) {
int left = canvas.getWidth()/2 - wrench.getWidth()*2 + j*wrench.getWidth();
int top = 0 + i*wrench.getHeight();
canvas.drawBitmap(wrench, left, top, null);
Log.d(i + " " + j, left+ " " + top);
}
}
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
}
#Override
public void surfaceCreated(SurfaceHolder arg0) {
canvasthread.setRunning(true);
canvasthread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
boolean retry = true;
canvasthread.setRunning(false);
while (retry) {
try {
canvasthread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
}
so i want to detect where i click on(for exemple there is 2 rects and i want to detect what rect i click on). i can set setOnClickListener to my view, but how to get position of click?
then i want to set the regions while drawing( it is right, yeah? or not?) and in activity i'll check is click coordinates contains regions
so
1) how can i get coord of click
2) what is the pretty good way to do do all that stuff, because my ideas are poor often
Look at the setOnTouchListener.
The OnTouchListener implements a method with the following signature:
public boolean onTouch(View v, MotionEvent event)
The MotionEvent has information about where the touch actually happened. (event.getX() and event.getY())

How to make SurfaceView with transparent background?

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

Categories

Resources