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;
}
}
Related
I am trying to understand using surfaceview. I want an image to move from left to right using surfaceview. Currently image is drawn but I am unable to make it move. Where should I call the variables x1 and y1. Also how could I call the invalidate() method, I want to make the image move from left to right repeatedly. Thanks
public class GameBoardTwo extends SurfaceView {
private Bitmap bitmap1;
private SurfaceHolder holder;
int x1, y1;
public GameBoardTwo(Context context) {
super(context);
holder = getHolder();
bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.blueball);
init();
holder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
Canvas c = holder.lockCanvas(null);
drawSomething(c);
holder.unlockCanvasAndPost(c);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
}
private void init(){
x1 = 0;
y1 = 100;
}
protected void drawSomething(Canvas canvas) {
canvas.drawColor(Color.WHITE);
if(x1 < canvas.getWidth()){
x1 += 5;
}
else{
x1 = 0;
}
canvas.drawBitmap(bitmap1, x1, y1, null);
}
}
You need to use thread/runnable inteface and override run(). Something like this:
#Override
protected void run(){
while(true){
drawSomething(c);//c is your locked canvas
try{
Thread.sleep(50)
} catch(Exception e){}
}
}
I have a SurfaceView on wich am drawing a small circle periodically with a special thread
but i want to when i press the surfaceView the thread stops drawing the circle and when i repress it the thread resume drawing the circle again.
I tried with thread methods and i can stop temporarily it with its sleep() method but i did not understand how to use wait and notify and i even found some exemples but did not get help from them
My code is :
public class GameView extends SurfaceView implements SurfaceHolder.Callback {
private float x = 100;
private float y = 100;
private int radius = 20;
private Paint paint;
private SurfaceHolder mSurfaceHolder;
private DrawingThread mTh ead;
private Context myContext;
public GameView(Context context) {
super(context);
this.myContext = context;
setWillNotDraw(false);
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.GREEN);
paint.setStyle(Paint.Style.STROKE);
paint.setTextAlign(Paint.Align.LEFT);
mSurfaceHolder = getHolder();
mSurfaceHolder.addCallback(this);
}
public void onDraw(Canvas canvas){
canvas.drawCircle(x, y, radius, paint);
}
public boolean onTouchEvent(MotionEvent event) {
int eventaction = event.getAction();
int X = (int)event.getX();
int Y = (int)event.getY();
switch (eventaction ) {
case MotionEvent.ACTION_DOWN:
// I want to do my job here
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
break;
}
invalidate();
return true;
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
mThread = new DrawingThread(mSurfaceHolder, myContext);
mThread.mRun = true;
mThread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
public final class DrawingThread extends Thread {
public boolean att = true;
public long delaiAttente = 1000;
boolean mRun;
Canvas mcanvas;
SurfaceHolder surfaceHolder;
Context context;
public DrawingThread(SurfaceHolder sholder, Context ctx)
{
surfaceHolder = sholder;
context = ctx;
mRun = false;
}
void setRunning(boolean bRun)
{
mRun = bRun;
}
boolean keepDrawing = true;
#Override
public void run() {
while (keepDrawing) {
Canvas canvas = null;
try {
canvas = mSurfaceHolder.lockCanvas();
synchronized (mSurfaceHolder) {
draw(canvas);
}
}
catch(Exception e){
}
finally {
if (canvas != null)
mSurfaceHolder.unlockCanvasAndPost(canvas);
}
waitThreaed();
}
}
public void waitThreaed() {
try {
x = (float) (getWidth()*Math.random());
y = (float) (getHeight()*Math.random());
this.sleep(1000);
postInvalidate();
} catch (InterruptedException e) {
}
}
}
}
Can't you just use something like this:
Timer drawTimer = new Timer("draw");
updateTimer.schedule(new TimerTask() {
public void run() {
draw();
}
}, 0, 1000);
private void draw() {
runOnUiThread(new Runnable() {
public void run() { ...}}}
I don't see why you need to subclass Thread.
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
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.
I am trying to draw on a surface view, but I get a black screen. My xml layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<com.example.surfaceview.MySurface android:id="#+id/padview"
android:layout_width="match_parent" android:layout_height="match_parent" />
</FrameLayout>
Important parts of my code: MySurface.java
public class MySurface extends SurfaceView implements SurfaceHolder.Callback {
public DrawingThread thread;
public MySurface(Context context, AttributeSet attrs) {
super(context, attrs);
SurfaceHolder surfaceholder = getHolder();
surfaceholder.addCallback(this);
thread = new DrawingThread(surfaceholder, context, new Handler() {
#Override
public void handleMessage(Message m) {
// Do some handle thing
}
});
setFocusable(true);
}
#Override
public void surfaceChanged(SurfaceHolder tholder, int format, int width, int height) {
thread.setSurfaceSize(width, height);
thread.holder = tholder;
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
thread.running = true;
thread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
thread.running = false;
while(retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
public Thread getThread() {
return thread;
}
public class DrawingThread extends Thread {
private SurfaceHolder holder;
private Context context;
private Handler handle;
private Paint background;
private Rect blank;
public boolean running;
public boolean created;
public int canvasheight;
public int canvaswidth;
public PadThread(SurfaceHolder tholder, Context tcontext, Handler thandler) {
holder = tholder;
context = tcontext;
handle = thandler;
// Temporary canvas dimentions
canvaswidth = 1;
canvasheight = 1;
running = false;
created = false;
background = new Paint();
background.setColor(R.color.white);
blank = new Rect(0, 0, canvaswidth, canvasheight);
}
#Override
public void run() {
Log.d("SurfaceView Test", "Drawing thread run");
while(running) {
Canvas canvas = null;
try {
canvas = holder.lockCanvas();
synchronized(holder) {
// update object states
// get user input gestures
drawing(canvas);
}
} finally {
if(canvas != null) {
holder.unlockCanvasAndPost(canvas);
}
}
}
}
private void drawing(Canvas canvas) {
// Clear screen
canvas.drawRect(blank, background);
// Draw Things
}
public void setSurfaceSize(int width, int height) {
synchronized(holder) {
canvaswidth = width;
canvasheight = height;
// New background rect
blank.set(0, 0, canvaswidth, canvasheight);
}
}
}
}
The code is based off of Google's Lunar Landar SurfaceView example at http://developer.android.com/resources/samples/LunarLander/index.html
I know that all of the code is being reached through logging.
change drawing function
background.setColor(Color.RED);
canvas.drawRect(new Rect(10, 10, 100, 100), background);
(There are test values for colors and rect)