Programming

Android: Hello Circle

Note: This article is really old. It is here for posterity only. You should really find a more current tutorial.

I’ve been a little frustrated by the lack of Android tutorials. I got a Hello world going, and found that most of the few tutorials I could find were WAY more complicated than what I want to start with. GPS, map overlays, to-do lists, etc, which is great and all but I want to start simple and work up from that. So I set out to build “Hello Circle,” a program which drew a dot on the screen wherever you touched it. After about 12 hours of beating my head against Eclipse, the Android SDK, and the frequently incorrect Android documentation I got it working. So here’s a tutorial.

Setting up the environment I’m going to assume you already successfully completed the Hello World tutorial. Which means you’ve got yourself an IDE (probably Eclipse), the Android SDK, and the ADK (Android Development Kit) which is a plugin for Eclipse to help keep things in order. If  you haven’t done that yet follow these instructions and pray everything works as planned. I’ll see you in a few hours. Create a project just like you did for Hello World. Creating the ViewGroup In order for anything to display on the screen you need to create a view. In the Hello World tutorial you created a TextView. We’re going to use the XML setup for creating our view, and rather than creating a TextView we’re going to use a FrameLayout, which is acutlaly a view group. Open up /res/layout/main.xml and plop in this fine code (obliterating anything that may be there):



This, when it’s called in our code, will create a FrameLayout view with an id of “main view,” a width/height that fills the screen, and a neon green background. The hex color code for the background includes the alpha channel (the first to FFs). Setting the contentView to our XML Head over to your main class and call setContentView on your layout. Your code should look something vaguely like this:

import android.app.Activity;
import android.os.Bundle;

public class RoboTown extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
}

If you run your code at this point you should get a big green background which does nothing. Hooray! Creating the Ball class Now we want to create a circle. Actually we want to create a lot of circles. So the first step is to create a new class called Ball. Right click on your project’s main class in the Package Explorer (on the left) and click New > Class. Give it the name Ball and click Finish. Our ball is actually going to be another view. What? Yeah. It’s a view. All of our Ball views will eventually go into our FrameLayout, but we’ll worry about that later. So first, modify your Ball class so that it extends View, since it’s a new type of View, and while you’re at it go ahead and import some of the things we’ll need for drawing:

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.View;

public class Ball extends View {

}

In order to draw a ball we need a handful of things: a Canvas to draw them on, x and y coordinates to place the center of the ball, the radius, and Paint to give it color. So we’ll start by establishing those (I hid the imports for the sake of clarity, you should leave yours there):

public class Ball extends View {
    private final float x;
    private final float y;
    private final int r;
    private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
}

In the last line we create a new Paint object, creatively called mPaint. A Paint contains information like colors, text sizes, etc, which affect the appearance of the drawing. So far we haven’t assigned any of those things to the Paint, we’ve just created it. Now we need to write the Ball constructor, which is the method to be called whenever we create a new ball:

    private final int r;
    private final Paint mPaint = new    Paint(Paint.ANTI_ALIAS_FLAG);

    public Ball(Context context, float x, float y, int r) {
        super(context);
        mPaint.setColor(0xFFFF0000);
        this.x = x;
        this.y = y;
        this.r = r;
    }
}

Our constructor takes a Context, x, y, and radius r. We pass these arguments in when we instantiate the object and assign them to the object properties. And lastly, the method which actually draws the circle, onDraw:

public Ball(Context context, float x, float y, int r) {
    super(context);
    mPaint.setColor(0xFFFF0000);
    this.x = x;
    this.y = y;
    this.r = r;
}

 @Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawCircle(x, y, r, mPaint);
}

Ok, our Ball class is done. Save it and head back over to the main class. Drawing a Ball on the screen At this point we haven’t actually drawn anything. We’ve just created Ball which we *could* draw if we so desired. In order to draw it on the screen we first have to get a hold of our FrameLayout. Since we created it via XML we’ll need to find it again using findViewById():

  setContentView(R.layout.main);

   FrameLayout main = (FrameLayout) findViewById(R.id.main_view);

Now we can use the addView method to attach a new Ball to our main view:

    FrameLayout main = (FrameLayout) findViewById(R.id.main_view);
    main.addView(new Ball(this,50,50,25));

Run your code now and, if all goes well, you’ll have a circle with a radius of 25 pixels in the upper left corner of the screen. Yay! Take some time to play around with Paint options, positioning, etc with the various methods outlined in the documentation. Now all we have to do is add a touch listener to react when the screen is touched. Which is thankfully pretty easy. We’re going to create a new touch listener and attach it to our main view all in one fell swoop:

main.addView(new Ball(this,50,50,25));

main.setOnTouchListener(new View.OnTouchListener() {
    public boolean onTouch(View v, MotionEvent e) {

    }
});

The onTouch() method is a callback function which will be hit whenever you touch the screen. Android will send it a View (v) and a MotionEvent (e). We already know what a view is, and a MotionEvent is an object containing information about the touch. All we care about are the X and Y coordinates, which are accessible via the getX() and getY() methods.

main.addView(new Ball(this,50,50,25));

main.setOnTouchListener(new View.OnTouchListener() {
    public boolean onTouch(View v, MotionEvent e) {
        float x = e.getX();
	float y = e.getY();
    }
});

The last thing we have to do before we can start drawing is to cast the view we were sent as a FrameLayout, so we can use the addView() method with it. Then we can instantiate a new Ball at the coordinates sent in the Motion Event:

main.addView(new Ball(this,50,50,25));

main.setOnTouchListener(new View.OnTouchListener() {
    public boolean onTouch(View v, MotionEvent e) {
        float x = e.getX();
	float y = e.getY();
        FrameLayout flView = (FrameLayout) v;
	flView.addView(new Ball(getParent(), x,y,25));
    }
});

The getParent() call sets the context for the Ball to the main Activity. I only vaguely understand why it has to be done this way. So now, the moment of truth! You should have all the code you need to run the app in your emulator or even on a real phone. Touching the screen will place a dot where you touched. Amazing! Hopefully you now have enough of an idea of how all this stuff plays together that you can forge your way to making something vaguely useful (which this isn’t).

104 thoughts on “Android: Hello Circle”

  1. Thank you so much for the clear tutorial! The touch listener is now working properly. I wish the android were as clear as this guide…

  2. Thanks for this tutorial. It works great.

    I have a couple of questions though. I’m just trying to add a button to it that when clicked, if will show a ball at a different location. I changed the layout to a relative layout and added a button at the bottom. I added an OnClickListener and used copied in the code from the OnTouchListnener. It runs, but when I click my button, it bombs out. Here is what I added

    button.setOnClickListener(new View.OnClickListener() {
    public void onClick(View view)
    {
    float x = 100;
    float y = 100;
    RelativeLayout flView = (RelativeLayout)view;
    flView.addView(new Ball(parent,x,y,25));
    }
    });

    Would it be this simple to add something like this, or is that something entirely different?

  3. Hello

    I am also facing issue with getParent().

    After replacing it with “this”
    or
    flView.addView(new Ball(findViewById(R.id.main_view).getContext(), x, y, 25));

    works without any exception but the newly circle drawn is not at the correct position.

    Testing it with emulator and whenever mouse is down and moved, newly circle drawn is few pixels below the mouse cursor. The number of pixel drawn below the cursor is equal to the height of the header.

    Is anybody facing similar issue or any solution for same.

  4. – code 1:1 copied
    – main.xml edited
    – no errors in eclipse

    =

    – does not start in my emuiator
    – does not start on external devices

    -> plz help??

  5. Thank you , your article is quite useful cause it is clear and goes direct to the point without trying to teach everything at the same time like others.

    I could not make it work with “getParent()” in line 19 because it blowed with first “touch” but it worked fine with “flviev.getContext()” instead.
    Hope this comment can help others with same problem.

  6. I would like some help.

    I am making a game that uses baisic 2d graphics.
    I want to draw a circle and make it select-able for movement.
    I would be glad to get any help.

  7. Hi, I am just trying to draw 6 balls on the screen using this code.
    I am doing this:
    mainLayout.addView(new Ball(this,50,50,25,0));
    mainLayout.addView(new Ball(this,100,50,25,1));
    mainLayout.addView(new Ball(this,150,50,25,2));
    mainLayout.addView(new Ball(this,200,50,25,3));
    mainLayout.addView(new Ball(this,250,50,25,4));
    mainLayout.addView(new Ball(this,300,50,25,5));

    but it only adds the first ball and not the others. If I comment out the first one, then only the 2nd will be drawn, and so on.
    Any idea why this is happening??

  8. Very good tutorial! I changed a bit in order to have a for loop set up a series of circles. I need each circle to have a onClickListener. Any help would be appreciated.

  9. How can I interact with the ball?
    My problem is:
    I draw some balls by code and then I want to detect a click on it. I think that the same as John problem

  10. Hey its really nice tutorial with clear ideas.
    I need some help. Can you please tell me the way to access the coordinates of the center of the circle and edge of the circle.
    I want to create pie chart.
    Thank you. 🙂

  11. its a great tutorial.but while i run the program the ball show on the screen.but when i touch the ball an error occour with notification is”The application RoboTown (process com.robo.town)has stopped unexpectedly.please try again”

  12. This is the working code with 4.03. Ball.java and main.xml were ok

    package hello.tasdf;

    import android.app.Activity;
    import android.os.Bundle;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.FrameLayout;

    public class HelloActivity extends Activity {
    /** Called when the activity is first created. */

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    FrameLayout main = (FrameLayout) findViewById(R.id.main_view);
    main.addView(new Ball(this,50,50,25));

    main.addView(new Ball(this,50,50,25));

    main.setOnTouchListener(new View.OnTouchListener() {
    public boolean onTouch(View v, MotionEvent e) {
    float x = e.getX();
    float y = e.getY();
    FrameLayout flView = (FrameLayout) v;
    flView.addView(new Ball(flView.getContext(), x,y,25));
    return true;}
    });
    }
    }

  13. hi,

    I am getting an error at this line “FrameLayout main = (FrameLayout) findViewById(R.id.main_view);” It says FrameLayout cannot be resolved to a type. Can anyone help me out of this ?

  14. Great tutorial, thanks!

    I have a similar question to those above…is there a way to keep track of the each ball, so you can make them clickable?

  15. Thank for posting this simple and lovely code. but i have one question how to erase the ploated point is it possible to making an array of ploating point.
    Thanks………… 🙂

  16. Thanks! This was very useful, the Android Dev’s guide had earlier left me totally confused.

  17. Appreciate the tutorial. After seeing this I was able to eventually mold it into a simple particle simulator, my first android app. 🙂

    There’s no doubt this is the tutorial that got the ball rolling.

  18. Hey, thanks for the tutorial. I had to make the following changes in to the MainActivity.java to get the code work:

    @Override
    public boolean onTouch(View v, MotionEvent e) {

    float x = e.getX();
    float y = e.getY();

    FrameLayout flView = (FrameLayout) v;

    System.out.println(getActivity() == null);

    flView.addView(new Ball(getActivity(), x, y, 25));

    return true;
    }

    private MainActivity getActivity() {
    return this;
    }

    As you can see I _replaced getParent() with getActivity()_ to be able to get the hosting activity and _added return true_ to the end of the file, else the program will crash when either painting dots or starting up, respectively. Hope someone gets use from these.

    -Irro

  19. Hi

    Don’t know if this is just a problem for me. I can’t see the xml-code you wrote inside the -tag. I can see it inside the sourcecode, but not on the Webpage (tested with opera and ie10)

    copy of the code

    thanks for the effort with the tutorial

    1. It’s not just you, apparently the latest version of WordPress is hell bent on devouring my code snippets. I’ll see if I can beat it back into submission.

Leave a Reply

Your email address will not be published. Required fields are marked *