Question

I want to move an image on the screen and I am able to do that, but not properly. The image goes downward fine and I want it to start going upward in another direction once it has moved to the bottom of the screen.

Here is what I have tried. In the code below, margenMaXX is the width of screen and margenmaxy is height of screen

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // setContentView(R.layout.activity_main);
Thread myThread = new Thread(new UpdateThread());
        myThread.start();

public class UpdateThread implements Runnable {

            @Override
            public void run() {
                //... code to manipulate position
                while (i<margenMaxX){
                    if(j<margenmaxy) {
                    try {
                        runOnUiThread(new Runnable() {

                            @Override
                            public void run() {
                                /*mDrawable.setBounds(i, j ,i+ width, i+ height);
                                 mDrawable.draw(cc);
                                 invalidate();*/
                            }
                        });
                       Thread.sleep(200);
                        i=i+10;
                        j=j+10;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }else if(j>=margenmaxy-height){
                    try {
                        runOnUiThread(new Runnable() {

                            @Override
                            public void run() {
                                /*mDrawable.setBounds(i, j ,i+ width, i+ height);
                                 mDrawable.draw(cc);
                                 invalidate();*/
                            }
                        });
                       Thread.sleep(200);
                        i=i-10;
                        j=j-10;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                }               
                }
            }

public class AnimatedView extends ImageView {



        public AnimatedView(Context context) {
            super(context);
            // TODO Auto-generated constructor stub


            mDrawable =  new ShapeDrawable(new OvalShape());
            mDrawable.getPaint().setColor(0xffffAC23);


        }
         protected void onDraw(final Canvas cc) {
            final Context context = null;

            mDrawable.setBounds(i, j ,i+ width, i+ height);
            mDrawable.draw(cc);
            invalidate();
                    }
    }

Update 1:

Using this code, the ball is going upwards and to another side after it hits the ground. Now, I want the ball to come back when it hits the right boundary. I did coding for that but it is not coming back. My final goal is to develop a game in which the ball must come from either left or right. It must hit the ground and go in the opposite direction, hit the wall and come back. The ball must do this work as long as the game is going on.

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // setContentView(R.layout.activity_main);
    Thread myThread = new Thread(new UpdateThread());
        myThread.start();

    public class UpdateThread implements Runnable {
    boolean mMoveDown=false;
    boolean mMoveUp = false;
        @Override
        public void run() {
            while(!mMoveUp) {
                // Move the image down and right.
                try {
                    runOnUiThread(new Runnable() {

                        @Override
                        public void run() {

                        }
                    });
                   Thread.sleep(200);
                    i=i+10;
                    j=j+10;

                // Try posting a runnable to the UI thread to update the view.


                } catch (InterruptedException e) {
                    e.printStackTrace();
                }if(j >= margenmaxy)
                {
                    // Change to moving up phase.
                    mMoveUp = true;
              }

            }

            while(mMoveUp){
                try {

                runOnUiThread(new Runnable() {

                    @Override
                    public void run() {

                    }
                });
                Thread.sleep(200);
                i=i + 10;
                j=j - 10;
            } catch (InterruptedException e) {
                e.printStackTrace();
            } if(i >= margenMaxX)
                {
                    // Change to moving up phase.
                    mMoveDown = true;
              } 
        }while(mMoveDown){
            try {

                runOnUiThread(new Runnable() {

                    @Override
                    public void run() {

                    }
                });
                Thread.sleep(200);
                i=i - 10;
                j=j + 10;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        }
}

public class AnimatedView extends ImageView {



        public AnimatedView(Context context) {
            super(context);
            // TODO Auto-generated constructor stub


            mDrawable =  new ShapeDrawable(new OvalShape());
            mDrawable.getPaint().setColor(0xffffAC23);


        }
         protected void onDraw(final Canvas cc) {
            final Context context = null;

            mDrawable.setBounds(i, j ,i+ width, j+ height);
            mDrawable.draw(cc);
            invalidate();
        }
}
Was it helpful?

Solution

This code has two conditional statements that overlap. However, the second one is checked only if the first fails. The second condition is:

(j >= margenmaxy - height)

This automatically implies (j < margenmaxy) Because margenmaxy, and height are both positive. When you check the condition like this:

if(j<margenmaxy) {
    // Do downward animation.

} else if(j>=margenmaxy-height){
    // Do upward animation.
}

What happens is that what you expect will happen for the phase where the image moves down. But as soon as you try move the image up, the (j < margenmaxy) condition is satisfied again, and the code tries to move the image down. The moment you move it down, the first condition is no longer valid. Since you have this construct inside a loop, it results in a "bouncing" behaviour.

To sort this problem out, you need to change the logic. One simple way to do this is to have a boolean hold the state of the animation. This state variable is changed depending on whether the image has hit the screen's bottom or not.

public class UpdateThread implements Runnable {

    // Variable to store the animation state.
    boolean mMoveUp = false;
    @Override
    public void run() {

        //... code to manipulate position
        while (i<margenMaxX) {
            // IF the animation is in the moving down phase
            if(!mMoveUp) {
                // Move the image down and right.
                i += 10;
                j += 10;

                // Try posting a runnable to the UI thread to update the view.
                try {
                    runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                            /*mDrawable.setBounds(i, j ,i+ width, i+ height);
                             mDrawable.draw(cc);
                             invalidate();*/
                    }
                    });
                    Thread.sleep(200);

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } 
            // We're moving upwards.
            else {
                // Move up and left
                i -= 10;
                j -= 10;

                try {
                    runOnUiThread(new Runnable() {

                        @Override
                        public void run() {
                            /*mDrawable.setBounds(i, j ,i+ width, i+ height);
                             mDrawable.draw(cc);
                             invalidate();*/
                        }
                    });
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } // Catch!
            } // Else! 

            // Check to see if we've hit the bottom of the screen
            if(j >= margenmaxy - height)
            {
                  // Change to moving up phase.
                  mMoveUp = true;
            }
            // Note, you can use an altered form of this to switch back and forth
            // between moving up and down.
        } // while(i < margenmaxx)!               
    } // run()!
} // UpdateThread!

As an added note, since you are moving the ball left and right, you might end up hitting those boundaries as well. You really should implement better checking for that. As a second note, this is probably not the best way to accomplish a moving image in Android. And finally, a more general solution is to use Android Property Animation with the interpolator you want. If you just want to do this once, View Animation may also suffice.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top