Static Methods in Android - java

Im try to create a drawing app. In my main activity I have an XML file which contains a drawing viewview
<app.color.DrawingView
android:layout_width="match_parent"
android:layout_height="200dp"
android:id="#+id/drawing"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:background="#FFFFFFFF"
android:layout_above="#+id/settings"
android:layout_alignParentTop="true" />
This is based on my drawing view class:
package app.color;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class DrawingView extends View {
private Paint paint = new Paint();
private Path path = new Path();
public DrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
paint.setAntiAlias(true);
paint.setStrokeWidth(5f);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawPath(path, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// Get the coordinates of the touch event.
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Set a new starting point
path.moveTo(eventX, return true;
case MotionEvent.ACTION_MOVE:
// Connect the points
path.lineTo(eventX, eventY);
break;
default:
return false;
}
// Makes our view repaint and call onDraw
invalidate();
return true;
}
public void setColor(String newColor){
invalidate();
int paintColor = Color.parseColor(newColor);
paint.setColor(paintColor);
}
}
Then in another activity on a button click I have a method which which I want to be able to call the setColor method in drawingView to change the color. However it wont let me do this because a "non-static method cannot be referenced from a static context"
public void toBlack(View view)
{
DrawingView.setColor("#00000");
Intent intent = new Intent(Colors.this, MainActivity.class);
startActivity(intent);
}

Create a instance of DrawingView.
thats like ,
DrawingView drawingview = new DrawingView();
drawingview.setColor("#00000");
setColor is an instance method, meaning you need an instance of the DrawingView class in order to call it. You're attempting to call it on the DrawingView type itself.
just make your code to
DrawingView dv = new DrawingView();
dv.setColor("#00000");
Intent intent = new Intent(Colors.this, MainActivity.class);
startActivity(intent);
for example you already have
public DrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
paint.setAntiAlias(true);
paint.setStrokeWidth(5f);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
}
you can also have another empty constructor
like
public DrawingView() { }

setColor is not a static method. You need to call it on an instance of DrawingView.

Related

onDraw() Method work only when i creating my object in the onDraw()

I got a problem. I don't know why I can't create a object for example in my iniGame() method. When I create a object from the GameObject class and use the method render() in the onDraw() method that doesn't work. ONLY when I create all relative object in the onDraw() method that works.
My layout XML:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="de.fhflensburg.manichja.barrier51.GameActivity">
<de.fhflensburg.manichja.barrier51.GameView
android:id="#+id/gameView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/gameView"
/>
</RelativeLayout>
My gameactivity:
package de.fhflensburg.manichja.barrier51;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
public class GameActivity extends AppCompatActivity {
private GameView gameView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
gameView = new GameView(this);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_game, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
my GameView
package de.fhflensburg.manichja.barrier51;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.CountDownTimer;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
public class GameView extends View {
private Canvas canvas;
private Context context;
private Paint peter;
private GameObject ball;
public GameView(Context context) {
super(context);
this.context = context;
initGame();
}
public void initGame(){
//ball.setSprite(R.drawable.menu_background);
}
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public GameView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void onDraw(Canvas canvas){
ball = new GameObject(this.context);
this.canvas = canvas;
peter = new Paint();
peter.setColor(Color.BLUE);
canvas.drawRect(100, 100, 200, 200, peter);
ball.render(canvas,peter);
}
}
my GameObject code
package de.fhflensburg.manichja.barrier51;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.util.Size;
public class GameObject {
private Size size; // A color as stated as a resource in the XML file (thus, it is an int)
private Point position; // A color as stated as a resource in the XML file (thus, it is an int)
private int fillColor; // A color as stated as a resource in the XML file (thus, it is an int)
private int strokeColor;// A color as stated as a resource in the XML file (thus, it is an int)
private int sprite;// A color as stated as a resource in the XML file (thus, it is an int)
private Bitmap ourSprite;
private Context conny;
public GameObject(Context context)
{
this.conny = context;
/*Paint myPaint = new Paint();
myPaint.setColor(Color.rgb(0, 0, 0));
myPaint.setStrokeWidth(10);
c.drawRect(100, 100, 200, 200, myPaint);*/
}
/**
* Sets the position of the GameObject on the screen.
* #param position A Point instance with x and y
*/
public void setPosition(Point position)
{
this.position = position;
}
/**
* Sets the fill color of the game object. If it has a Sprite image, the assigned color will be ignored.
* #param color A color resource, defined in the XML file (e.g. R.color.limegreen)
*/
public void setFillColor(int color)
{
this.fillColor = color;
}
/**
* Sets the stroke color of the game object. If it has a Sprite image, the assigned color will be ignored.
* #param color A color resource, defined in the XML file (e.g. R.color.limegreen)
*/
public void setStrokeColor(int color)
{
this.strokeColor = color;
}
/**
* #return Delivers the current size of the GameObject
*/
public Size getSize()
{
return size;
}
/**
* #return Delivers the current position of the GameObject
*/
public Point getPosition()
{
return position;
}
/**
* #return Delivers the current position of the GameObject as stated in the XML file.
*/
public int getFillColor()
{
return fillColor;
}
/**
* #return Delivers the current stroke color of the GameObject as stated in the XML file.
*/
public int getStrokeColor()
{
return strokeColor;
}
/**
* Checks for a collision of this object with another instance of a GameObject.
* #param obj The object to be checked for collision
* #return Returns true if the objects' coordinates overlap at any pixel.
*/
public boolean overlaps(GameObject obj)
{
if (getPosition().x < obj.getPosition().x + obj.getSize().getWidth() &&
getPosition().x + getSize().getWidth() > obj.getPosition().x &&
getPosition().y < obj.getPosition().y + obj.getSize().getHeight() &&
getSize().getHeight() + getPosition().y > obj.getPosition().y)
{
return true;
}
else
{
return false;
}
}
/**
* Sets the sprite image of the GameObject.
* #param sprite A bitmap resource as defined in the XML file.
*/
public void setSprite(int sprite) {
Log.i("Peter", "Inigame get started"+sprite);
this.sprite = sprite;
ourSprite = BitmapFactory.decodeResource(this.conny.getResources(),R.drawable.menu_background);
}
/**
* #return Delivers the sprite resource id as an Integer.
*/
public Bitmap getSprite() {
return ourSprite;
}
/**
* Renders the object with the current attributes on the screen.
*/
public void render(Canvas c,Paint paint)
{
c.drawRect(0,0,120,120,paint);
}
}
You are getting a NullPointerException because your initGame is probably not called. At least not on the Object where onDraw is called.
What I mean is that there are two instances of your GameView. The first instance is the one you create manually using:
gameView = new GameView(this);
The second instance is created from the XML-File, since you are defining:
<de.fhflensburg.manichja.barrier51.GameView
android:id="#+id/gameView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
So this second instance is created automatically by the App. And you don't know at the beginning, which of the three constructors is called. There are two things you should change:
In your activity, replace gameView = new GameView(this); with gameView = (GameView) findViewById(R.id.gameView);. This will give you the correct instance of your GameView. Please refer to the View-Doc for more details.
In your GameView class, add a call to initGame in all three constructors. This ensures that the elements are initialized, no matter what constructor is called.

Canvas not update even I called invalidate()?

I want to create a custom view that animates some lines. so I created a class that extends View class. I called onDraw() & drawn on the canvas.
Here are some codes that I've approached so far.
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
p += 10;
canvas.drawLine(5, 5, p, 5, mPaint);
invalidate();
}
note that p & mPaint are instantiated at the constructor.
but, even I called invalidate() method, it doesn't update the canvas, i.e. doesn't animate the line.
so, how to solve this?
Are you sure it's not drawing? What colour is your Paint object?
I created a blank 4.4 android application, added this class:
package ca.kieve.playground;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
public class AnimView extends View {
private int p = 0;
private Paint mPaint;
public AnimView(Context context) {
super(context);
init();
}
public AnimView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(10);
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
p += 1;
canvas.drawLine(5, 5, p, 5, mPaint);
invalidate();
}
}
and changed the activity_main.xml to this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="ca.kieve.playground.MainActivity" >
<ca.kieve.playground.AnimView
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
This draws with no issues.
remove
invalidate() form onDraw().
use
inavalidate() while you have done with your changes.

How to get a button to work with view in android [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have been trying to add a erase function to this drawing app. I was planning on it just simpily drawing white over where you move your finger. For some reason i cannot get the button to work. If i can get this button to work I will be able to add more colors ect.
(i have not done anything with Mainactivity)
package com.example.draw;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainDrawingView extends View
{
private Paint paint = new Paint();
private boolean erase;
private Path path = new Path();
Button aButton;
public MainDrawingView(Context context, AttributeSet attrs)
{
super(context, attrs);
paint.setAntiAlias(true);
paint.setStrokeWidth(5f);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
aButton = (Button) this.findViewById(R.id.button1);
aButton.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
erase = !erase;
}
});
}
#Override
protected void onDraw(Canvas canvas)
{
canvas.drawPath(path, paint);
}
public boolean onTouchEvent(MotionEvent event)
{
if(erase) paint.setColor(Color.WHITE);
else paint.setColor(Color.BLACK);
// Get the coordinates of the touch event.
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Set a new starting point
path.moveTo(eventX, eventY);
return true;
case MotionEvent.ACTION_MOVE:
// Connect the points
path.lineTo(eventX, eventY);
break;
default:
return false;
}
// Makes our view repaint and call onDraw
invalidate();
return true;
}
}
Activity_main<
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
tools:context="com.example.draw.FullscreenActivity">
<!-- This is the view on which we will draw. -->
<view
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.example.draw.MainDrawingView"
android:id="#+id/single_touch_view"
android:layout_gravity="left|top"
android:background="#ffffff" />
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</FrameLayout>
It seems like your problem is that you're using the wrong types. Your erase variable is of type Paint:
private Paint erase = new Paint();
But in your code you're treating it like an int that represents a boolean.
if(erase != 0) { paint.setColor(Color.BLACK); }
if(erase == 0) { paint.setColor(Color.WHITE); }
...
erase = 1;
Secondly, you're never actually setting the onClickListener for your button. Also, the logic to set the color should all be moved into either your onTouch or the onClick method. You really should have:
public class MainDrawingView extends View
{
private Paint paint = new Paint();
private boolean erase;
private Path path = new Path();
Button aButton;
public MainDrawingView(Context context, AttributeSet attrs)
{
super(context, attrs);
paint.setAntiAlias(true);
paint.setStrokeWidth(5f);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
aButton = (Button) this.findViewById(R.id.button1);
aButton.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
erase = !erase;
}
});
}
#Override
protected void onDraw(Canvas canvas)
{
canvas.drawPath(path, paint);
}
public boolean onTouchEvent(MotionEvent event)
{
if(erase) paint.setColor(Color.WHITE);
else paint.setColor(Color.BLACK);
// Get the coordinates of the touch event.
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Set a new starting point
path.moveTo(eventX, eventY);
return true;
case MotionEvent.ACTION_MOVE:
// Connect the points
path.lineTo(eventX, eventY);
break;
default:
return false;
}
// Makes our view repaint and call onDraw
invalidate();
return true;
}
}
It is possible that your view is not being created with the following constructor
Context context, AttributeSet attrs
It might be using a different default constructor that you have not overridden. Then nothing would get setup and you would not get any click behavior that your expecting from your listener.
It looks like you do not have your onCreate(Bundle savedInstances) method setup to to add the listener correctly.

How can I use getResources from android

I created a class MiOverlay that extends from Overlay.
And it doesn't recognize the getResources method.. What do I have to do. Here the full code of my class
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Point;
import android.location.Location;
import com.google.android.maps.MapView;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.Overlay;
public class MiOverlay extends Overlay {
GeoPoint point;
public MiOverlay(GeoPoint point)
{
super();
this.point = point;
}
#Override
public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when){
super.draw(canvas, mapView, shadow);
Point scrnPoint = new Point();
mapView.getProjection().toPixels(this.point, scrnPoint);
Bitmap marker = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
canvas.drawBitmap(marker, scrnPoint.x - marker.getWidth() / 2, scrnPoint.y - marker.getHeight() /2 , null);
return true;
}
I disagree with Luis Lavieri's answer. Your easiest solution would be to use the MapView's context:
Bitmap marker = BitmapFactory.decodeResource(mapView.getContext().getResources(), R.drawable.ic_launcher);
Easy and no potential memory leaks.
You are in an Non-Activity Class, so you must refer to what is discussed in this question. However, it is not recommended to pass the Context due to a possible memory leaking. Try to implement your resources within your Activity using getResources() or if you are using Fragments, use getActivity().getResources()...
Anyway, your easiest option would be:
private Context context;
public MiOverlay(GeoPoint point, Context _context)
{
super();
this.point = point;
context = _context;
}
#Override
public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when){
super.draw(canvas, mapView, shadow);
Point scrnPoint = new Point();
mapView.getProjection().toPixels(this.point, scrnPoint);
Bitmap marker = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher);
canvas.drawBitmap(marker, scrnPoint.x - marker.getWidth() / 2, scrnPoint.y - marker.getHeight() /2 , null);
return true;
}

Android App Not Working After Pressing Back Button

I created an Android app which draws a small image to the screen and exits if you tap in the bottom 50px of the screen. When I tap there, it exits fine, however, when I press the back (or home) button to exit the application, it exits, but then says, "Unfortunately, Game Development has stopped." I also checked LogCat, and it showed that a Java NullPointerException occurred each time it stopped working. The output from LogCat was:
10-30 01:13:28.280: E/AndroidRuntime(15294): FATAL EXCEPTION: Thread-1718
10-30 01:13:28.280: E/AndroidRuntime(15294): java.lang.NullPointerException
10-30 01:13:28.280: E/AndroidRuntime(15294): at tricrose.gamedev.GameView.onDraw(GameView.java:56)
10-30 01:13:28.280: E/AndroidRuntime(15294): at tricrose.gamedev.GameThread.run(GameThread.java:30)
I have three Java classes: Game.java (the Activity), GameView.java (the SurfaceView), and GameThread.java (the main Thread).
The code is as follows:
Game.java:
package tricrose.gamedev;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.Window;
import android.view.WindowManager;
public class Game extends Activity {
public static final String TAG = Game.class.getSimpleName();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(new GameView(this));
Log.d(TAG, "View added");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_game, menu);
return true;
}
}
GameView.java:
package tricrose.gamedev;
import android.app.Activity;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class GameView extends SurfaceView implements SurfaceHolder.Callback {
public static final String TAG = GameView.class.getSimpleName();
private GameThread thread;
public GameView(Context context) {
super(context);
getHolder().addCallback(this);
thread = new GameThread(getHolder(), this);
setFocusable(true);
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
public void surfaceCreated(SurfaceHolder holder) {
thread.setRunning(true);
thread.start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
while (retry) {
try {
thread.join();
retry = false;
} catch (Exception e) {}
}
}
public boolean onTouchEvent(MotionEvent e) {
if (e.getAction() == MotionEvent.ACTION_DOWN) {
if (e.getY() > getHeight() - 60) {
thread.setRunning(false);
((Activity)getContext()).finish();
}
}
return super.onTouchEvent(e);
}
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.droid_1), 10, 10, null);
}
}
GameThread.java:
package tricrose.gamedev;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
public class GameThread extends Thread {
public static final String TAG = GameThread.class.getSimpleName();
private boolean running;
private SurfaceHolder surfaceHolder;
private GameView gameView;
public GameThread(SurfaceHolder surfaceHolder, GameView gameView) {
super();
this.surfaceHolder = surfaceHolder;
this.gameView = gameView;
}
public void setRunning(boolean running) {
this.running = running;
}
public void run() {
Canvas canvas;
while (running) {
canvas = null;
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
this.gameView.onDraw(canvas);
}
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
I've searched all over the internet for a solution, and I cannot find one which has actually worked, so any help is hugely appreciated.
I finally managed to find the solution! It turned out that I should have checked if the canvas was null before calling onDraw, and if it was null, then quit the application by finishing the activity. I found the solution on JavaCodeGeeks.com, where I was looking at an Android tutorial. Thanks everyone for all your answers!
why you have doing drawing from two places from onDraw and GameThread run method. I think you need to remove onDraw do every drawing from GameThread rlun method only.
This is just a guess, but your app might still be drawing while the app is trying to exit. In you onDraw method you call this line of code (which is probably your cause of problem):
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.droid_1), 10, 10, null);
In that case you might not have resuorces available anymore ;)
You can try to:
1. Put a class private bitmap variable into your GameView Class:
private Bitmap mBitmap;
2. Load the bitmap in your GameView constructor:
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.droid_1);
3. Draw using the (already loaded) bitmap:
canvas.drawBitmap(mBitmap, 10, 10, null);
Hope that helps!

Categories