EDIT: I took a look at the LogCat, and it said that it couldn't inflate com.example.playground. I then realized that it needed to me com.game.myapp.Playground. It worked after I changed it.
I recently asked why gravity wasn't working in my Android app (link) and I still have trouble with it. I changed the view to class "Playground" but now it just force closes. What am I doing wrong?
package com.game.myapp;
import android.app.Activity;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Bundle;
public class InGame extends Activity{
Playground v;
private int radius;
private int xPosition;
private int yPosition;
private Paint paint;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Rewrite this, it sucks. Seriously.
super.onCreate(savedInstanceState);
v = new Playground(this);
setContentView(v);
}
public InGame(int x, int y, int radius, int color)
{
this.xPosition = x; this.yPosition = y; this.radius = radius;
paint = new Paint(color);
}
void moveBall(int x, int y){
xPosition = x; yPosition =y;
}
void onDraw(Canvas canvas){
canvas.drawCircle(xPosition, yPosition, radius, paint);
}
}
Playground class:
package com.game.myapp;
import android.content.Context;
import android.graphics.Canvas;
import android.view.View;
public class Playground extends View{
public static InGame ball;
public Playground(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
public void onDraw(Canvas canvas)
{
super.onDraw(canvas);
if (ball != null ){
ball.onDraw(canvas);
}
}
}
Heres the LogCat:
11-04 16:36:33.945: D/dalvikvm(13177): newInstance failed: no <init>()
11-04 16:36:33.949: D/AndroidRuntime(13177): Shutting down VM
11-04 16:36:33.949: W/dalvikvm(13177): threadid=1: thread exiting with uncaught exception (group=0x4001e578)
11-04 16:36:33.953: E/AndroidRuntime(13177): FATAL EXCEPTION: main
11-04 16:36:33.953: E/AndroidRuntime(13177): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.game.myapp/com.game.myapp.InGame}: java.lang.InstantiationException: com.game.myapp.InGame
11-04 16:36:33.953: E/AndroidRuntime(13177): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1573)
11-04 16:36:33.953: E/AndroidRuntime(13177): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667)
11-04 16:36:33.953: E/AndroidRuntime(13177): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
11-04 16:36:33.953: E/AndroidRuntime(13177): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
11-04 16:36:33.953: E/AndroidRuntime(13177): at android.os.Handler.dispatchMessage(Handler.java:99)
11-04 16:36:33.953: E/AndroidRuntime(13177): at android.os.Looper.loop(Looper.java:130)
11-04 16:36:33.953: E/AndroidRuntime(13177): at android.app.ActivityThread.main(ActivityThread.java:3687)
11-04 16:36:33.953: E/AndroidRuntime(13177): at java.lang.reflect.Method.invokeNative(Native Method)
11-04 16:36:33.953: E/AndroidRuntime(13177): at java.lang.reflect.Method.invoke(Method.java:507)
11-04 16:36:33.953: E/AndroidRuntime(13177): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
11-04 16:36:33.953: E/AndroidRuntime(13177): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
11-04 16:36:33.953: E/AndroidRuntime(13177): at dalvik.system.NativeStart.main(Native Method)
11-04 16:36:33.953: E/AndroidRuntime(13177): Caused by: java.lang.InstantiationException: com.game.myapp.InGame
11-04 16:36:33.953: E/AndroidRuntime(13177): at java.lang.Class.newInstanceImpl(Native Method)
11-04 16:36:33.953: E/AndroidRuntime(13177): at java.lang.Class.newInstance(Class.java:1409)
11-04 16:36:33.953: E/AndroidRuntime(13177): at android.app.Instrumentation.newActivity(Instrumentation.java:1021)
11-04 16:36:33.953: E/AndroidRuntime(13177): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1565)
11-04 16:36:33.953: E/AndroidRuntime(13177): ... 11 more
Here's the complete code. I just wrote this and tested it. It works. I added a timer to the activity to move the ball right and down by 10 pixels every second. Please study it, learn from it and adapt it to your needs.
Ball class.
package com.example;
import android.graphics.Canvas;
import android.graphics.Paint;
public class Ball{
private int radius;
private int xPosition;
private int yPosition;
private int color;
private Paint paint;
public Ball(int x, int y, int radius, int color)
{
this.xPosition = x; this.yPosition = y; this.radius = radius;
paint = new Paint();
paint.setColor(color);
}
int getX(){return this.xPosition;}
int getY(){return this.yPosition;}
void moveBall(int x, int y){
xPosition = x; yPosition =y;
}
void onDraw(Canvas canvas){
canvas.drawCircle(xPosition, yPosition, radius, paint);
}
}
Playground class
package com.example;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.widget.ImageView;
public class Playground extends ImageView {
private Ball ball;
public Playground(Context context) {
this(context,null);
}
public Playground(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public Playground(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setBall(Ball ball){
this.ball = ball;
}
@Override
public void onDraw(Canvas canvas)
{
super.onDraw(canvas);
if (ball != null ){
ball.onDraw(canvas);
}
}
}
Activity class
package com.example;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import java.util.Timer;
import java.util.TimerTask;
public class MyActivity extends Activity {
/**
* Called when the activity is first created.
*/
Playground playground;
Ball ball;
Timer myTimer;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
playground = (Playground) findViewById(R.id.playground);
ball = new Ball(100, 100, 20, Color.RED);
playground.setBall(ball);
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
@Override
public void run() {
Update();
}
}, 0, 1000);
}
private void Update() {
this.runOnUiThread(moveBall);
}
private Runnable moveBall = new Runnable() {
public void run() {
ball.moveBall(ball.getX() + 10, ball.getY() + 10);
playground.invalidate();
}
};
}
[EDIT] The XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.example.Playground
android:id="@+id/playground"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</LinearLayout>
Key points for OOP.
The Ball has no knowledge of the Playground or the activity. It has a method that might get called by something asking it do draw on a canvas but for all it knows, it might be an invisible canvas, or a canvas of a button, or a canvas of a bitmap - it doesn't know or need to know. It's the job of whatever calls the method to worry about that.
The Playground has no knowledge of the activity or the Ball. It knows it might have an instance of a Ball class and if it has, it should call it's onDraw method but it has no idea what the ball is or what it draws. The Ball worries about that.
The activity has no knowledge of the Ball or the Playground other than it has one of each and calls the Ball move method then tells the Playground to redraw itself.
The point is, you could change the draw methods, the move methods and everything else without recoding (OK, in general). For example, you could change the onDraw in the Ball class to draw a rectangle. Of course, the name of the class is now a bad choice but you get the idea...
You have no default constructor in your InGame Activity, which is necessary for Android to be able to instantiate it.
The presence of an explicit constructor will cause no implicit no-arg constructor to be defined. You may need to provide your own no-arg constructor that initializes its members to default values.
I would delete the explicit constructor and put the initialization into the onCreate(Bundle) method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With