In the main activity I have a handler to exchange messages with the bluetooth service. This works fine.
Now, I want launch second activity (SurfaceViewAnimation). I do this with:
startActivity (new Intent (this, SurfaceViewAnimation.class));
but I want change some attributes of SufaceViewAnimation class from main activity when it receives a command for bluetooth.
How I can do this?
The code of SufaceViewAnimation class is:
class BouncingBallView extends SurfaceView implements SurfaceHolder.Callback {
private BouncingBallAnimationThread bbThread = null;
private int xPosition = getWidth()/2;
private int yPosition = getHeight()/2;
private int xDirection = 20;
private int yDirection = 40;
private static int radius = 20;
private static int ballColor = Color.RED;
public BouncingBallView(Context ctx, AttributeSet attrs, int defStyle) {
super(ctx, attrs, defStyle);
getHolder().addCallback(this);
}
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
canvas.drawRect(0,0,getWidth(),getHeight(), paint);
paint.setColor(ballColor);
canvas.drawCircle(xPosition, yPosition, radius, paint);
}
public void surfaceCreated(SurfaceHolder holder) {
if (bbThread!=null) return;
bbThread = new BouncingBallAnimationThread(getHolder());
bbThread.start();
}
public void surfaceChanged(SurfaceHolder holder,int format, int width, int height) { }
public void surfaceDestroyed(SurfaceHolder holder) {
bbThread.stop = true;
}
private class BouncingBallAnimationThread extends Thread {
public boolean stop = false;
private SurfaceHolder surfaceHolder;
public BouncingBallAnimationThread(SurfaceHolder surfaceHolder) {
this.surfaceHolder = surfaceHolder;
}
public void run() {
while (!stop) {
xPosition += xDirection;
yPosition += yDirection;
if (xPosition<0) {
xDirection = -xDirection;
xPosition = radius; }
if (xPosition>getWidth()-radius) {
xDirection = -xDirection;
xPosition = getWidth()-radius; }
if (yPosition<0) {
yDirection = -yDirection;
yPosition = radius; }
if (yPosition>getHeight()-radius) {
yDirection = -yDirection;
yPosition = getHeight()-radius-1; }
Canvas c = null;
try {
c = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder) {
onDraw(c);
}
} finally {
if (c != null) surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() != MotionEvent.ACTION_DOWN) return false;
if (xDirection!=0 || yDirection!=0)
xDirection = yDirection = 0;
else {
xDirection = (int) event.getX() - xPosition;
yDirection = (int) event.getY() - yPosition;
}
if(ballColor==Color.RED)
ballColor=Color.GREEN;
else
ballColor=Color.RED;
return true;
}
public void setxDirection(int xDirection) {
this.xDirection = xDirection;
}
public void setyDirection(int yDirection) {
this.yDirection = yDirection;
}
public void setballColor(int ballColor) {
this.ballColor = ballColor;
}
public void setradius(int radius) {
this.radius = radius;
}
}
public class SurfaceViewAnimation extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new BouncingBallView(this,null,0));
}
}
If you want to change the data in SurfaceViewAnimation while SurfaceViewAnimation is running, you're best off with creating an own handler.
Besides that you can fall back to basic Inter(Process/Activity)Communication using Handlers, static variables or the Observer pattern.
Related
I made an infinite background for an Android 2D game but the background scrolls only one time and doesn't loop. How can I fix this?
Another question: How do I make this same background fall from the top to bottom? For a game
.
This is my class (code):
public class GameView extends View implements Runnable {
private static final int INTERVAL = 10;
private boolean running = true;
private int y;
private Paint paint;
private int z = 0;
int sx;
Bitmap background;
public GameView(Context context){
super(context);
paint = new Paint();
background = BitmapFactory.decodeResource(getResources(), R.drawable.back);
Thread myThread = new Thread(this);
myThread.setPriority(Thread.MIN_PRIORITY);
myThread.start();
}
#Override
public void run() {
while (running) {
try {
Thread.sleep(INTERVAL);
} catch (InterruptedException e) {
Log.e("Game", "Gameloop finished!");
}
update();
}
}
private void update() {
if (y < getHeight()) {
y += 5;
} else {
y = 0;
}
postInvalidate();
}
public void draw(Canvas canvas) {
super.draw(canvas);
z = z-10;
if(z == -sx) {
z = 0;
canvas.drawBitmap(background, z, 0, null);
} else {
canvas.drawBitmap(background, z, 0, null);
}
}
public void release() {
running = false;
}
}
I made a rotating knob ,but I want to stop the knob at specific angles for 2 seconds. I want to stop it on 260f and -20f.
Can anyone suggest how to do it ?
This is the code from a blog. I made many changes according to my requirements.
public class RotatoryKnobView extends ImageView {
private float angle = -20f;
private float theta_old=0f;
private RotaryKnobListener listener;
public interface RotaryKnobListener {
public void onKnobChanged(float arg);
}
public void setKnobListener(RotaryKnobListener l )
{
listener = l;
}
public RotatoryKnobView(Context context) {
super(context);
initialize();
}
public RotatoryKnobView(Context context, AttributeSet attrs)
{
super(context, attrs);
initialize();
}
public RotatoryKnobView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
initialize();
}
private float getTheta(float x, float y)
{
float sx = x - (getWidth() / 2.0f);
float sy = y - (getHeight() / 2.0f);
float length = (float)Math.sqrt( sx*sx + sy*sy);
float nx = sx / length;
float ny = sy / length;
float theta = (float)Math.atan2( ny, nx );
final float rad2deg = (float)(180.0/Math.PI);
float thetaDeg = theta*rad2deg;
return (thetaDeg < 0) ? thetaDeg + 360.0f : thetaDeg;
}
public void initialize()
{
this.setImageResource(R.drawable.rotoron);
setOnTouchListener(new OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event) {
float x = event.getX(0);
float y = event.getY(0);
float theta = getTheta(x,y);
switch(event.getAction() & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_POINTER_DOWN:
theta_old = theta;
break;
case MotionEvent.ACTION_MOVE:
invalidate();
float delta_theta = theta - theta_old;
theta_old = theta;
int direction = (delta_theta > 0) ? 1 : -1;
angle += 5*direction;
notifyListener(angle+20);
break;
}
return true;
}
});
}
private void notifyListener(float arg)
{
if (null!=listener)
listener.onKnobChanged(arg);
}
protected void onDraw(Canvas c)
{if(angle==257f){
try {
synchronized (c) {
c.wait(5000);
angle=260f;
}
} catch (InterruptedException e) {
}
}
else if(angle==-16f)
{
try {
synchronized (c) {
c.wait(5000);
angle=-20f;
}
} catch (InterruptedException e) {
}
}
else
if(angle>260f)
{
angle=-20f;
}
else if(angle<-20f)
{
angle=260f;
}
else{
c.rotate(angle,getWidth()/2,getHeight()/2);
}
super.onDraw(c);
}
}
You may set a fixed angle and use postDelayed to clear it after 2 seconds.
public class RotatoryKnobView extends ImageView {
private float angle = -20f;
private float theta_old=0f;
private RotaryKnobListener listener;
private Float fixedAngle;
private float settleAngle;
private Runnable unsetFixedAngle = new Runnable() {
#Override
public void run() {
angle = settleAngle;
fixedAngle = null;
invalidate();
}
};
public interface RotaryKnobListener {
public void onKnobChanged(float arg);
}
public void setKnobListener(RotaryKnobListener l )
{
listener = l;
}
public RotatoryKnobView(Context context) {
super(context);
initialize();
}
public RotatoryKnobView(Context context, AttributeSet attrs)
{
super(context, attrs);
initialize();
}
public RotatoryKnobView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
initialize();
}
private float getTheta(float x, float y)
{
float sx = x - (getWidth() / 2.0f);
float sy = y - (getHeight() / 2.0f);
float length = (float)Math.sqrt( sx*sx + sy*sy);
float nx = sx / length;
float ny = sy / length;
float theta = (float)Math.atan2( ny, nx );
final float rad2deg = (float)(180.0/Math.PI);
float thetaDeg = theta*rad2deg;
return (thetaDeg < 0) ? thetaDeg + 360.0f : thetaDeg;
}
public void initialize()
{
this.setImageResource(R.drawable.rotoron);
setOnTouchListener(new OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event) {
float x = event.getX(0);
float y = event.getY(0);
float theta = getTheta(x,y);
switch(event.getAction() & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_POINTER_DOWN:
theta_old = theta;
break;
case MotionEvent.ACTION_MOVE:
invalidate();
float delta_theta = theta - theta_old;
theta_old = theta;
int direction = (delta_theta > 0) ? 1 : -1;
angle += 5*direction;
notifyListener(angle+20);
break;
}
return true;
}
});
}
private void notifyListener(float arg)
{
if (null!=listener)
listener.onKnobChanged(arg);
}
void setFixedAngle(float angle, float settleAngle) {
fixedAngle = angle;
this.settleAngle = settleAngle;
postDelayed(unsetFixedAngle, 2000);
}
protected void onDraw(Canvas c)
{
if(fixedAngle==null) {
if (angle > 270) {
setFixedAngle(270, -15);
} else if (angle < -20f) {
setFixedAngle(-20, 260);
}
}
Log.d("angle", "angle: " + angle + " fixed angle: " + fixedAngle);
c.rotate(fixedAngle == null ? angle : fixedAngle,getWidth()/2,getHeight()/2);
super.onDraw(c);
}
}
`
I think the ultimate answer here is to implement your own class by extending SurfaceView and then overriding onDraw( Canvas canvas )
You can then use the Canvas routines to render your control.
There are a lot of good examples out there if you google.
To get started initialize the surface view:
// So things actually render
setDrawingCacheEnabled(true);
setWillNotDraw(false);
setZOrderOnTop(true);
// Controls the drawing thread.
getHolder().addCallback(new CallbackSurfaceView());
Override onDraw and add your rendering routines. You can layer them
as you go.
public void onDraw(Canvas canvas) {
// Always Draw
super.onDraw(canvas);
drawBackground(canvas);
drawKnobIndentWell(canvas);
drawKnob(canvas);
drawKnobLED( canvas ); //etc....
}
An example of a Callback and an update thread:
/**
* This is the drawing callback.
* It handles the creation and destruction of the drawing thread when the
* surface for drawing is created and destroyed.
*/
class CallbackSurfaceView implements SurfaceHolder.Callback {
Thread threadIndeterminant;
RunnableProgressUpdater runnableUpdater;
boolean done = false;
/**
* Kills the running thread.
*/
public void done() {
done = true;
if (null != runnableUpdater) {
runnableUpdater.done();
}
}
/**
* Causes the UI to render once.
*/
public void needRedraw() {
if (runnableUpdater != null) {
runnableUpdater.needRedraw();
}
}
/**
* When the surface is created start the drawing thread.
* #param holder
*/
#Override
public void surfaceCreated(SurfaceHolder holder) {
if (!done) {
threadIndeterminant = new Thread(runnableUpdater = new RunnableProgressUpdater());
threadIndeterminant.start();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
/**
* When the surface is destroyed stop the drawing thread.
* #param holder
*/
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (null != runnableUpdater) {
runnableUpdater.done();
threadIndeterminant = null;
runnableUpdater = null;
}
}
}
/**
* This is the runnable for the drawing operations. It is started and stopped by the callback class.
*/
class RunnableProgressUpdater implements Runnable {
boolean surfaceExists = true;
boolean needRedraw = false;
public void done() {
surfaceExists = false;
}
public void needRedraw() {
needRedraw = true;
}
#Override
public void run() {
canvasDrawAndPost();
while (surfaceExists) {
// Renders continuously during a download operation.
// Otherwise only renders when requested.
// Necessary so that progress bar and cirlce activity update.
if (syncContext.isRunning()) {
canvasDrawAndPost();
needRedraw = true;
} else if (needRedraw) {
canvasDrawAndPost();
needRedraw = false;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// Don't care
}
}
// One final update
canvasDrawAndPost();
}
/**
* Routine the redraws the controls on each loop.
*/
private synchronized void canvasDrawAndPost() {
Canvas canvas = getHolder().lockCanvas();
if (canvas != null) {
try {
draw(canvas);
} finally {
getHolder().unlockCanvasAndPost(canvas);
}
}
}
}
If you decide to go this route you can customize your control from XML using
custom values.
<com.killerknob.graphics.MultimeterVolumeControl
android:id="#+id/volume_control"
android:layout_below="#id/divider_one"
android:background="#android:color/white"
android:layout_width="match_parent"
android:layout_height="60dp"
android:minHeight="60dp"
custom:ledShadow="#357BBB"
custom:ledColor="#357BBB"
custom:knobBackground="#color/gray_level_13"
custom:knobColor="#android:color/black"
/>
When you create a custom control you reference it by its package name.
You create custom variable in a resource file under /values and then reference
them in your class.
More details here:
http://developer.android.com/training/custom-views/create-view.html
This may be more work then you want to do, but I think you will end up with a more professional looking control and the animations will be smoother.
At any rate, looks like a fun project. Good Luck.
I'm making a simple rotating animation of 2 images, one on top of another (each with a different speed). I know there is already an Animation API, but I need to use this one instead.
It works well, but from time to time, the animations stop for a very short time and then continue, making it "jumpy" (stays on some frames much more than on the others).
Why does it occur? because of GC? What can I do to avoid it? I intend to do some background operations, so it might get even slower.
I know that using sleep() doesn't really mean the thread will wake up right after the given time, but this is too much and it's very noticeable .
Are there any tricks to make it smoother? maybe use a better alternative?
Here's the code (of the view that does it) :
public class AnimView extends SurfaceView implements SurfaceHolder.Callback
{
int _angle;
private final Bitmap _bitmap;
private final Paint _paint =new Paint();
private AnimationThread _animationThread;
private Matrix _matrix;
private int _width;
private int _height;
public AnimView(final Context context)
{
super(context);
_bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
_paint.setAntiAlias(true);
getHolder().addCallback(this);
}
public AnimView(final Context context,final AttributeSet attrs)
{
super(context,attrs);
_bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
_paint.setAntiAlias(true);
getHolder().addCallback(this);
}
public AnimView(final Context context,final AttributeSet attrs,final int defStyle)
{
super(context,attrs,defStyle);
_bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
_paint.setAntiAlias(true);
getHolder().addCallback(this);
}
#Override
public void surfaceChanged(final SurfaceHolder holder,final int format,final int width,final int height)
{
_width=width;
_height=height;
}
#Override
public void surfaceCreated(final SurfaceHolder holder)
{
if(isInEditMode())
return;
_matrix=new Matrix();
setWillNotDraw(false);
_animationThread=new AnimationThread();
_animationThread.start();
}
#Override
public void surfaceDestroyed(final SurfaceHolder holder)
{
_animationThread.cancelAnimation();
}
#Override
protected void onDraw(final Canvas canvas)
{
if(isInEditMode())
{
canvas.drawColor(0xffff0000);
return;
}
_paint.setAntiAlias(true);
_matrix.reset();
_matrix.postScale(_width/_bitmap.getWidth(),_height/_bitmap.getHeight());
_matrix.postRotate(_angle,_width/2,_height/2);
canvas.drawBitmap(_bitmap,_matrix,_paint);
_matrix.reset();
_matrix.postScale(_width/_bitmap.getWidth(),_height/_bitmap.getHeight());
_matrix.postRotate(_angle*2,_width/2,_height/2);
canvas.drawBitmap(_bitmap,_matrix,_paint);
}
private class AnimationThread extends Thread
{
private boolean _isRunning =true;
public AnimationThread()
{}
public void cancelAnimation()
{
_isRunning=false;
}
#Override
public void run()
{
while(_isRunning)
{
postInvalidate();
refreshDrawableState();
try
{
sleep(5);
}
catch(final InterruptedException e)
{
e.printStackTrace();
}
_angle=(_angle+1)%360;
}
}
}
}
Try something like this
#Override
public void run()
{
long last = System.currentTimeMillis();
long currentTime = last;
long frameTime = 40;
while(_isRunning)
{
currentTime = System.currentTimeMillis();
if(currentTime - last > frameTime){
postInvalidate();
refreshDrawableState();
//I FORGOT THIS
last = currentTime;
}
try
{
sleep(5);
}
catch(final InterruptedException e)
{
e.printStackTrace();
}
_angle=(_angle+1)%360;
}
}
}
This way you refresh your screen every 40ms and update your position every 5ms. Also this is just one part, you can set your matrix update and calculations also out of the drawing part, and this will increase your speed too. The less calculations you do on actuall draw time the faster it will be.
EDIT: Take a look at this
public class AnimView extends SurfaceView implements SurfaceHolder.Callback {
int _angle;
private final Bitmap _bitmap;
private final Paint _paint = new Paint();
private AnimationThread _animationThread;
private Matrix _matrix;
private int _width = 100;
private int _height = 100;
private Bitmap backBitmap;
private Canvas backCanvas;
public AnimView(final Context context) {
super(context);
_bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher);
_paint.setAntiAlias(true);
getHolder().addCallback(this);
}
public AnimView(final Context context, final AttributeSet attrs) {
super(context, attrs);
_bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher);
_paint.setAntiAlias(true);
getHolder().addCallback(this);
}
public AnimView(final Context context, final AttributeSet attrs,
final int defStyle) {
super(context, attrs, defStyle);
_bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher);
_paint.setAntiAlias(true);
getHolder().addCallback(this);
}
#Override
public void surfaceChanged(final SurfaceHolder holder, final int format,
final int width, final int height) {
_width = width;
_height = height;
createImage();
}
#Override
public void surfaceCreated(final SurfaceHolder holder) {
if (isInEditMode())
return;
_matrix = new Matrix();
setWillNotDraw(false);
_animationThread = new AnimationThread();
_animationThread.start();
}
#Override
public void surfaceDestroyed(final SurfaceHolder holder) {
_animationThread.cancelAnimation();
}
#Override
protected void onDraw(final Canvas canvas) {
if (isInEditMode() || backBitmap == null) {
canvas.drawColor(0xffff0000);
return;
}
canvas.drawBitmap(backBitmap, 0, 0, _paint);
}
private class AnimationThread extends Thread {
private boolean _isRunning = true;
public AnimationThread() {
}
public void cancelAnimation() {
_isRunning = false;
}
#Override
public void run() {
long last = System.currentTimeMillis();
long currentTime = last;
long frameTime = 40;
long updateTime = 20;
boolean updated = false;
while (_isRunning) {
currentTime = System.currentTimeMillis();
if (currentTime - last > frameTime) {
postInvalidate();
refreshDrawableState();
last = currentTime;
updated = false;
}
else if(currentTime - last > updateTime){
if(!updated){
drawImage();
updated = true;
}
}
try {
sleep(5);
} catch (final InterruptedException e) {
e.printStackTrace();
}
_angle = (_angle + 1) % 360;
}
}
}
private void createImage(){
backBitmap = Bitmap.createBitmap(_width, _height, Config.ARGB_8888);
backCanvas = new Canvas();
backCanvas.setBitmap(backBitmap);
}
private void drawImage(){
backCanvas.drawRGB(0, 0, 0);
_paint.setAntiAlias(true);
_matrix.reset();
_matrix.postScale(_width / _bitmap.getWidth(),
_height / _bitmap.getHeight());
_matrix.postRotate(_angle, _width / 2, _height / 2);
backCanvas.drawBitmap(_bitmap, _matrix, _paint);
_matrix.reset();
_matrix.postScale(_width / _bitmap.getWidth(),
_height / _bitmap.getHeight());
_matrix.postRotate(_angle * 2, _width / 2, _height / 2);
backCanvas.drawBitmap(_bitmap, _matrix, _paint);
}
}
Hope this helps and enjoy your work
I have custom SurfaceView that containt a circle. I want to rotate this circle via touch events. Everything good except I can't pause run() method of SurfaveView when touch finished.
Here my view and thread
public class CircleSurfaceView extends SurfaceView implements
SurfaceHolder.Callback {
private Circle mCircle;
private DrawThread thread;
private float mRotation = 0;
long mLastMillis = 0L;
Paint clearPaint = new Paint();
public CircleSurfaceView(Context context) {
super(context);
mCircle = new Circle(0, 200, 200);
getHolder().addCallback(this);
this.setZOrderOnTop(true);
this.getHolder().setFormat(PixelFormat.TRANSPARENT);
clearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
public void startDrawing() {
if (thread == null) {
thread = new DrawThread(this);
thread.startThread();
}
}
public void stopDrawing() {
if (thread != null) {
thread.stopThread();
// Waiting for the thread to die by calling thread.join,
// repeatedly if necessary
boolean retry = true;
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
}
}
thread = null;
}
}
#Override
protected void onDraw(final Canvas canvas) {
canvas.drawPaint(clearPaint);
mCircle.init();
mCircle.draw(canvas);
super.onDraw(canvas);
}
float degrees;
public void rotateCircle() {
mCircle.rotate(mRotation);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float currentX = event.getX();
float currentY = event.getY();
float deltaX, deltaY;
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
// Modify rotational angles according to movement
deltaX = currentX - previousX;
deltaY = currentY - previousY;
mRotation += deltaX + deltaY;
}
// Save current x, y
previousX = currentX;
previousY = currentY;
rotateCircle();
return true; // Event handled
}
private float previousX;
private float previousY;
private static int SEG_COUNT = 62;
private static float SEG_IN_GRAD = (float) 360 / SEG_COUNT;
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder arg0) {
startDrawing();
}
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
stopDrawing();
}
public class DrawThread extends Thread {
private boolean mRun = false;
private SurfaceHolder surfaceHolder = null;
private CircleSurfaceView circleSurfaceView = null;
public DrawThread(CircleSurfaceView circleSurfaceView) {
this.circleSurfaceView = circleSurfaceView;
this.surfaceHolder = circleSurfaceView.getHolder();
}
public void startThread() {
if (mRun == false) {
mRun = true;
super.start();
}
}
public void stopThread() {
if (mRun == true) {
mRun = false;
}
}
#Override
public void run() {
Canvas c = null;
while (mRun) {
c = null;
try {
c = surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
if (c != null) {
Log.i("run", "run");
circleSurfaceView.rotateCircle();
circleSurfaceView.onDraw(c);
}
}
} finally {
// do this in a finally so that if an exception is thrown
// we don't leave the Surface in an inconsistent state
if (c != null) {
surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
i want to rotate an image(png) in android depending upon the intensity of touch.
Any Idea?
public class GetmouseActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new Panel(this));
}
public class Panel extends SurfaceView implements SurfaceHolder.Callback {
private Bitmap mBitmap;
private ViewThread mThread;
private int mX;
private int mY;
public Panel(Context context) {
super(context);
mBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.icon);
getHolder().addCallback(this);
mThread = new ViewThread(this);
}
public void doDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
Paint paint = new Paint();
paint.setStrokeWidth(25);
for (int y = 30, alpha = 255; alpha > 2; alpha >>= 1, y += 10) {
paint.setAlpha(alpha);
canvas.drawLine(0, y, 100, y, paint);
}
canvas.drawBitmap(mBitmap, mX, mY, null);
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder) {
if (!mThread.isAlive()) {
mThread = new ViewThread(this);
mThread.setRunning(true);
mThread.start();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
if (mThread.isAlive()) {
mThread.setRunning(false);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
mX = (int) event.getX() - mBitmap.getWidth() / 2;
mY = (int) event.getY() - mBitmap.getHeight() / 2;
return super.onTouchEvent(event);
}
}
public class ViewThread extends Thread {
private Panel mPanel;
private SurfaceHolder mHolder;
private boolean mRun = false;
public ViewThread(Panel panel) {
mPanel = panel;
mHolder = mPanel.getHolder();
}
public void setRunning(boolean run) {
mRun = run;
}
#Override
public void run() {
Canvas canvas = null;
while (mRun) {
canvas = mHolder.lockCanvas();
if (canvas != null) {
mPanel.doDraw(canvas);
mHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
try this