implement canvas android - android

I am trying to implement the canvas feature in ios for android. The ios canvas has a property known as drawChildren that is basically an array that manages drawing objects that can be added/removed by the canvas controller.
Is there a way anyone can help me achieve this feat? I am aware that the Canvas class should be used however, I am not sure how to arrange it in as array.

I don't know if this will work for you, or if you solved this but I made this approach:
Activity.class
//Create an activity to hold everything
public class GameActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
Rel_main_game = (RelativeLayout) findViewById(R.id.rlt_main);
DisplayMetrics dm = new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getMetrics(dm);
final int heightS = dm.heightPixels;
final int widthS = dm.widthPixels;
//this is the SurfaceView that will do the magic
game_panel = new GamePanel(getApplicationContext(),this,widthS, heightS);
Rel_main_game.addView(game_panel);
}
SurfaceView
public class GamePanel extends SurfaceView implements SurfaceHolder.Callback {
public MainThread thread;
public int ScreenWidth;
public int Screenheigt;
public GameActivity game;
public GamePanel(Context context, GameActivity game, int width , int height) {
super(context);
getHolder().addCallback(this);
this.game = game;
this.ScreenWidth=width;
this.Screenheigt=height;
thread = new MainThread(getHolder(),this);
ship = new Ship(BitmapFactory.decodeResource(getResources(), R.drawable.player), 100, 0, ScreenWidth, Screenheigt);
}
void Draw(Canvas canvas){
if (canvas!=null)
{
ship.draw(canvas);
}
}
void Update(float dt){
ship.udpdate(dt);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
thread.setRunning(true);
thread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
boolean retry = true;
while (retry)
{
try
{
thread.join();
retry=false;
}
catch (InterruptedException e)
{
}
}
}
}
and you add children classes that have draw and update methods:
public class Ship {
public Bitmap bitmap;
public int x;
private int y;
private int Speed;
private int inc;
private int ScreenWidth;
private int ScreenHeight;
public int direction=0;
boolean death;
float animTime=0;
float totalAnimTime = 1;
float numFrames;
public Ship(Bitmap decodeResource, int x, int y, int screenWidth, int screenheight) {
this.bitmap = decodeResource;
this.x =screenWidth/2 - bitmap.getWidth()/2;
this.y = screenheight - bitmap.getHeight();
Speed=1;
inc=0;
death=false;
ScreenWidth =screenWidth;
ScreenHeight =screenheight;
}
public void draw(Canvas canvas){
if (!death)
{
canvas.drawBitmap(bitmap, x, y - bitmap.getHeight() / 2, null);
}
}
public void update(float dt){
if (death)
{
animTime += dt;
}
else
{
float movement =ScreenWidth/2*dt;
if (x - (bitmap.getWidth()/ 2)<ScreenWidth || x > - bitmap.getWidth()/ 2)
switch(direction)
{
case(1):
{
x+=8;//movement*dt;
break;
}
case(2):
{
x-=8;//movement*dt;
break;
}
}
}
}
and so on.

Related

How to change attributes of the second Activity from Main activity?

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.

SurfaceView not showing animation

I want to draw an animated picture in my MainActivity
My MainActivity code is as follows :
public class LaozhangActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
Ch0_1 view=new Ch0_1(this);
super.onCreate(savedInstanceState);
setContentView(view);
}
}
and I have defined a class that extends SurfaceView in order to show an animated picture;
The code is like this:
public class Ch0_1 extends SurfaceView implements Callback, Runnable
{
SurfaceHolder surfaceHolder;
private boolean isThreadRunning = true;
Canvas canvas;
float r = 10;
public Ch0_1(Context context)
{
super(context);
surfaceHolder = this.getHolder();
surfaceHolder.addCallback(this);
canvas=new Canvas();
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height)
{
}
public void surfaceCreated(SurfaceHolder holder)
{
new Thread(this).start();
}
public void surfaceDestroyed(SurfaceHolder holder)
{
}
private void Method(int x,int y)
{
Paint pen=new Paint();
pen.setColor(Color.GREEN);
canvas=surfaceHolder.lockCanvas();
canvas.drawLine(0, 0, x, y, pen);
surfaceHolder.unlockCanvasAndPost(canvas);
}
public void run()
{
while (isThreadRunning)
{
int x=0,y=0;
Method(x,y);
try
{
Thread.sleep(100);
} catch (Exception e)
{
e.printStackTrace();
}
x+=10;
y+=10;
if(x>400)break;
}
}
}
When running, the MainActivity is black, it didn't show the picture.
Where is the problem?
With your code, x and y are reset to 0 at each iteration...
You must move the initialization of x and y outside of the while loop:
public void run() {
int x = 0, y = 0;
while (isThreadRunning) {
Method(x, y);
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
x += 10;
y += 10;
if (x > 400)
break;
}
}

How to move a circular image(png) using touch in android depending upon the touch

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

How I can move an image from left to right and right to left in android?

I'm new in android. I want to move an image from left to right and right to left.When user touch right side image of the image it will move right side.Same thing will happen when user will touch right side of the image.But image will move predefine point across x-axis.
For example: Image will move p1(100,100), p2(150,100), p3(200,100), p4(250,100) across those points sequentially. If user touch left side of p1, it will remain current position.Same thing will occurs at p4. I can move image from p1 to p2 and p2 to p1. when I add p3 and p4 it's not working as I expected.
Here is my GameView class.
public class GameView extends SurfaceView{
private Bitmap BG_image;
private SurfaceHolder holder;
//private GameLoopThread gameLoopThread;
int x;
int y;
private int srcX=100;
private int srcY=100;
int replaceX=0,areaThreshold=50;
int distance=50;
public GameView(Context context) {
super(context);
//gameLoopThread = new GameLoopThread(this);
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
/* boolean retry = true;
gameLoopThread.setRunning(false);
while (retry) {
try {
gameLoopThread.join();
retry = false;
} catch (InterruptedException e) {
}
}*/
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
/* gameLoopThread.setRunning(true);
gameLoopThread.start();*/
Canvas c = holder.lockCanvas(null);
onDraw(c);
holder.unlockCanvasAndPost(c);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
BG_image = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
Bitmap.createScaledBitmap(BG_image, BG_image.getWidth(), BG_image.getHeight(), false);
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
// x = (int) ev.getX();
// y = (int) ev.getY();
updateX(srcX);
replaceX=(int)ev.getX();
int StartX=0, EndX=0;
StartX=replaceX-areaThreshold;
EndX=replaceX+areaThreshold;
if(StartX<=100){
SurfaceHolder holder=getHolder();
Canvas myCanvas=holder.lockCanvas(null);
onDraw(myCanvas);
holder.unlockCanvasAndPost(myCanvas);
srcX=100;
}
else if(StartX>100 && StartX<250){
SurfaceHolder holder=getHolder();
Canvas myCanvas=holder.lockCanvas(null);
onDraw(myCanvas);
holder.unlockCanvasAndPost(myCanvas);
srcX=srcX+distance;
}
if(EndX>100 && EndX<250){
SurfaceHolder holder=getHolder();
Canvas myCanvas=holder.lockCanvas(null);
onDraw(myCanvas);
holder.unlockCanvasAndPost(myCanvas);
srcX=srcX-distance;
}
else if(EndX>250){
SurfaceHolder holder=getHolder();
Canvas myCanvas=holder.lockCanvas(null);
onDraw(myCanvas);
holder.unlockCanvasAndPost(myCanvas);
srcX=250;
}
return super.onTouchEvent(ev);
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
updateX(srcX);
Paint paint = new Paint();
canvas.drawColor(Color.BLACK);
canvas.drawRect(new Rect(0,0,getWidth(),getHeight()),paint);
canvas.drawBitmap(BG_image, srcX, srcY, null);
}
private int updateX(int srcX){
this.srcX =srcX;
return srcX ;
}
}
Please review my code and give your valuable advice to solve my problem.
Hopefully, I will get a reply soon!
This is very easy with Android TranslateAnimation
ImageView img_animation = (ImageView) findViewById(R.id.img_animation);
TranslateAnimation animation = new TranslateAnimation(0.0f, 400.0f,
0.0f, 0.0f); // new TranslateAnimation(xFrom,xTo, yFrom,yTo)
animation.setDuration(5000); // animation duration
animation.setRepeatCount(5); // animation repeat count
animation.setRepeatMode(2); // repeat animation (left to right, right to left )
//animation.setFillAfter(true);
img_animation.startAnimation(animation); // start animation
find more details from here move an image from left to right and right to left in android
Now, I understand my problem. Thank you very much to give your suggestion.
Here is my updated code.
public class GameView extends SurfaceView{
private Bitmap BG_image;
private SurfaceHolder holder;
int x=100;
private int srcX=100;
private int srcY=100;
int distance=50;
public GameView(Context context) {
super(context);
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
Canvas c = holder.lockCanvas(null);
onDraw(c);
holder.unlockCanvasAndPost(c);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
BG_image = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
Bitmap.createScaledBitmap(BG_image, BG_image.getWidth(), BG_image.getHeight(), false);
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
x = (int) ev.getX();
if(x-srcX>0)
srcX += distance;
else if(x-srcX<0)
srcX -= distance;
if(srcX<=100)
srcX = 100;
else if(srcX>250)
srcX = 250;
Log.w("ev.getX : srcX",x+" : "+srcX);
SurfaceHolder holder=getHolder();
Canvas myCanvas=holder.lockCanvas(null);
onDraw(myCanvas);
holder.unlockCanvasAndPost(myCanvas);
return super.onTouchEvent(ev);
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
Paint paint = new Paint();
canvas.drawColor(Color.BLACK);
canvas.drawRect(new Rect(0,0,getWidth(),getHeight()),paint);
canvas.drawBitmap(BG_image, srcX-BG_image.getWidth()/2, srcY, null);
}
}

Surfaceview flickering

I have a problem with the flickering.
Here is my code.
public class Tutorial2D3 extends Activity {
Panel panel;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
panel = new Panel(this);
setContentView(panel);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(1, 1, 1, "Clean Canvas");
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
panel.cleanCanvas();
return true;
}
class Panel extends SurfaceView implements SurfaceHolder.Callback {
TutorialThread thread;
Bitmap icon;
int iconWidth;
int iconHeight;
int touchX;
int touchY;
int mCount = 0;
public Panel(Context context) {
super(context);
icon = BitmapFactory
.decodeResource(getResources(), R.drawable.icon);
iconWidth = icon.getWidth();
iconHeight = icon.getHeight();
getHolder().addCallback(this);
thread = new TutorialThread(getHolder(), this);
setFocusable(true);
}
#Override
protected void onDraw(Canvas canvas) {
int x = touchX - (iconWidth / 2);
int y = touchY - (iconHeight / 2);
if(mCount>0) {
canvas.drawColor(Color.BLACK);
mCount--;
}
canvas.drawBitmap(icon, (x > 0 ? x : 0), (y > 0 ? y : 0), null);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
thread.setRunning(true);
thread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
thread.setRunning(false);
do {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (retry);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchX = (int) event.getX();
touchY = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
touchX = (int) event.getX();
touchY = (int) event.getY();
break;
case MotionEvent.ACTION_UP:
break;
default:
break;
}
return true;
}
private void cleanCanvas() {
mCount = 2;
}
}
class TutorialThread extends Thread {
private SurfaceHolder _surfaceHolder;
private Panel _panel;
private boolean _run = false;
public TutorialThread(SurfaceHolder surfaceHolder, Panel panel) {
_surfaceHolder = surfaceHolder;
_panel = panel;
}
public void setRunning(boolean run) {
_run = run;
}
#Override
public void run() {
Canvas c;
while (_run) {
c = null;
try {
c = _surfaceHolder.lockCanvas(null);
synchronized (_surfaceHolder) {
_panel.onDraw(c);
}
} finally {
if (c != null) {
_surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
}
The drawn image flickers.
It looks like the bitmap that is drawn at one point is drawn on one surface and not the other so it looks like flickering, the bitmap that is drawn when we touch action_up is done, that is a solid image and does not flickers. Could someone please help me with this one.
Thanks
When you are drawing in the Canvas of a SurfaceView, you must always draw every pixel of the surface.
Here you are not always clearing the Canvas in onDraw(), hence the flickering.
One thing you could do to mitigate that (and to kinda contradict Guillaume :)) is to use surfaceholder.lockCanvas(rectangle), where it is only the specified rectangle part of the canvas which is then drawn (but you must draw every pixel of that rect). Here it is, ripped from the LunarLandar sample:
#Override
public void run() {
while (mRun) {
Canvas c = null;
try {
c = mSurfaceHolder.lockCanvas(Rectangle);
synchronized (mSurfaceHolder) {
if (mMode == STATE_RUNNING) updatePhysics();
doDraw(c);
}
} finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
I didn't read through all of your code, but I think this article will help.
The essence of the article is that flickering is due to double buffering and can be eliminated by drawing not to the argument Canvas but to a bitmap used as the canvas and then drawing that bitmap to the arg Canvas:
int myCanvas_w, myCanvas_h;
Bitmap myCanvasBitmap = null;
Canvas myCanvas = null;
Matrix identityMatrix;
#Override
public void surfaceCreated(SurfaceHolder holder) {
myCanvas_w = getWidth();
myCanvas_h = getHeight();
myCanvasBitmap = Bitmap.createBitmap(myCanvas_w, myCanvas_h, Bitmap.Config.ARGB_8888);
myCanvas = new Canvas();
myCanvas.setBitmap(myCanvasBitmap);
identityMatrix = new Matrix();
}
#Override
protected void onDraw(Canvas canvas) {
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3);
//int w = myCanvas.getWidth();
//int h = myCanvas.getHeight();
int x = random.nextInt(myCanvas_w-1);
int y = random.nextInt(myCanvas_h-1);
int r = random.nextInt(255);
int g = random.nextInt(255);
int b = random.nextInt(255);
paint.setColor(0xff000000 + (r << 16) + (g << 8) + b);
myCanvas.drawPoint(x, y, paint); // <--------- Here's where you draw on your bitmap
canvas.drawBitmap(myCanvasBitmap, identityMatrix, null);
// ^---------- And here's where you draw that bitmap to the canvas
}

Categories

Resources