I am currently writing an Android game app using GPS features of the device. I have come in contact with some problems.
Here is my Player class
public class Player {
private int xCor;
private int yCor;
public Player(int xCor, int yCor)
{
this.xCor = xCor;
this.yCor = yCor;
}
}
Here is my GameSurface View
public class GameSurface extends View{
private ArrayList<Ghost> ghostList;
private Paint paint;
public GameSurface(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public GameSurface(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public GameSurface(Context context) {
super(context);
init();
}
public void init() {
paint = new Paint();
paint.setColor(0xff00ff00); // single int in hex (Green)
// first ff = opaque; first 00 = no red
// second ff = green all the way on; second 00 = no blue
// could also do: paint.setColor(Color.GREEN);
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(3);
}
#Override
public void onDraw(Canvas c) {
}`
And here's my AsyncTask class
public class UpdateLocation extends AsyncTask<GameSurface,GameSurface, Integer>{
#Override
protected Integer doInBackground(GameSurface... params) {
}
#Override
protected void onPreExecute()
{
}
#Override
protected void onProgressUpdate(GameSurface... params)
{
}
`
I would like to get the GPS coordinates in the AsyncTask and use those coordinates to update the location of a circle (Player) in the View. How can I do that?
You can send the context (Activity that controls the view) to the AsyncTask:
public class AsyncTask {
protected void execute(Context context, HashMap<String, String>... params) {
...
Then in the onPostExecute method of the AsyncTask, you can call a method of the activity to update the view.
#Override
protected void onPostExecute(HashMap<String, String> result) {
((MyActivity) context).updateView(result);
}
Related
I have a customview:
public class GalleryView extends View implements View.OnClickListener {
private CallBackHandler callBackHandler;
Paint myPaint = new Paint();
public GalleryView(Context context, CallBackHandler callBackHandler) {
super(context);
this.callBackHandler = callBackHandler;
}
public GalleryView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
myPaint.setColor(Color.RED);
canvas.drawPaint(myPaint);
}
#Override
public void onClick(View view) {
System.out.println("clicked !");
callBackHandler.do();
}
}
I am adding this to my linearLayout of my main activity:
linearLayout.addView(galleryView);
And I set that layout to my contantview:
setContentView(linearLayout);
I can see the view red, but clicking is not triggered.
What is wrong here ?
You need to add this line inside on create :
yourView.setOnClickListener(this);
Basically, when you add this line You assign OnClickListener to your view using setOnClickListener(this) and that's how inside onClick, the onClick of the assigned OnClickListener is called.
You can do it by simply setting OnClickListener as below:
public class GalleryView extends View implements View.OnClickListener {
Paint myPaint = new Paint();
private CallBackHandler callBackHandler;
public GalleryView(Context context, CallBackHandler callBackHandler) {
this(context, null, callBackHandler);
}
public GalleryView(Context context, AttributeSet attributeSet, CallBackHandler callbackHandler) {
super(context, attributeSet);
this.callBackHandler = callbackHandler;
initialize();
}
private void initialize() {
setOnClickListener(this);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
myPaint.setColor(Color.RED);
canvas.drawPaint(myPaint);
}
#Override
public void onClick(View view) {
System.out.println("clicked !");
callBackHandler.do();
}
}
I want to make a custom class based on ImageButton. Also, determine the action when click the button. But I regret to say the method onClick does not work in the class. What could be the problem?
public class CircleButton extends ImageButton implements View.OnClickListener{
private boolean checked;
public CircleButton(Context context) {
super(context);
init(context);
}
public CircleButton(Context context, AttributeSet set) {
super(context, set);
init(context);
}
public CircleButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
#Override
public void onClick(View v) {
//setChecked(!isChecked());
Log.d("CircleButton", "setBackground()");
setBackground();
}
private void init (Context context) {
setOnClickListener(this);
}
public boolean isChecked() {
return checked;
}
public void setChecked(boolean checked) {
this.checked = checked;
setBackground();
}
private void setBackground() {
setBackgroundResource(R.drawable.ic_about);
}
protected void onDraw(Canvas canvas) {
}
}
I have this code in activity:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final MyNumberPicker np = new MyNumberPicker(this);
np.setOnScrollListener(new NumberPicker.OnScrollListener() {
#Override
public void onScrollStateChange(NumberPicker view, int scrollState) {
if (scrollState == NumberPicker.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL){
np.setBottomFadingEdgeStrength(0.9f);
np.setBottomFadingEdgeStrength(0.9f);
} else if (scrollState == NumberPicker.OnScrollListener.SCROLL_STATE_IDLE){
np.setBottomFadingEdgeStrength(1.0f);
np.setBottomFadingEdgeStrength(1.0f);
}
//also you can handle SCROLL_STATE_FLING if you want
}
});
}
}
And this code for my custom class:
public class MyNumberPicker extends NumberPicker {
private float bottomFadingEdgeStrength = 1.0f;
private float topFadingEdgeStrength = 1.0f;
public MyNumberPicker(Context context) {
super(context);
}
public MyNumberPicker(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyNumberPicker(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected float getBottomFadingEdgeStrength() {
return bottomFadingEdgeStrength;
}
#Override
protected float getTopFadingEdgeStrength() {
return topFadingEdgeStrength;
}
void setTopFadingEdgeStrength(float strength){
topFadingEdgeStrength = strength;
}
void setBottomFadingEdgeStrength(float strength){
bottomFadingEdgeStrength = strength;
}
}
The thing is that I don't know how to add this number picker into activity. In other words, I can't get it to work in my program. So how should I change my code in activity to do this.
As far as I can tell, I can't use findViewById(R.id.numberpicker1). Please help.
In your layout, instead using adding a NumberPicker like you normally would:
<NumberPicker android:id="#+id/numberpicker1" ... />
You would use a tag that points to your custom class.
<your.path.to.MyNumberPicker android:id="#+id/numberpicker1" ... />
So, if you added this to your activity_main layout, you could initialize it using View.findViewById:
setContentView(R.layout.activity_main);
final MyNumberPicker np = (MyNumberPicker) findViewById(R.id.numberpicker1);
SOLVED: Solution below as answer.
I have a custom view with a TransitionDrawable and when I draw it in the onDraw() method it scales automatically to fill the whole parent layout, even when it's set in the xml to wrap_content. The picture is in mdpi and hdpi and my testing device (samsung galaxy s) I think it's no more than hdpi.
package com.adyrsoft.pronunciationtrainer;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.TransitionDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
public class RecordButton extends View {
private static final String TAG = "RecordButton";
private TransitionDrawable mDrawable;
private boolean mActivated;
private OnClickListener mOnClickListenerInternal = new OnClickListener() {
#Override
public void onClick(View v) {
toggleState();
if(mOnClickListener != null) {
mOnClickListener.onClick(v);
}
}
};
private OnClickListener mOnClickListener = null;
public RecordButton(Context context) {
super(context);
init();
}
public RecordButton(Context context, AttributeSet attrib) {
super(context, attrib);
init();
}
public RecordButton(Context context, AttributeSet attrib, int defStyle) {
super(context, attrib, defStyle);
init();
}
public void setState(boolean activated) {
mActivated = activated;
if(mActivated){
mDrawable.startTransition(300);
}
else {
mDrawable.reverseTransition(300);
}
}
public void toggleState() {
if(mActivated) {
setState(false);
}
else {
setState(true);
}
}
#SuppressWarnings("deprecation")
private void init() {
mActivated = false;
mDrawable = (TransitionDrawable) getResources().getDrawable(R.drawable.btnrecord);
Log.d(TAG, "Drawable intrinsic width and height are: " +
Integer.toString(mDrawable.getIntrinsicWidth()) + " " +
Integer.toString(mDrawable.getIntrinsicHeight()));
mDrawable.setBounds(0,0,mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight());
Log.d(TAG, "The bounds for the button are: "+mDrawable.getBounds().flattenToString());
super.setBackgroundDrawable(mDrawable);
setClickable(true);
super.setOnClickListener(mOnClickListenerInternal);
invalidate();
}
public void setOnClickListener(View.OnClickListener listener) {
mOnClickListener = listener;
}
protected void onDraw (Canvas canvas) {
super.onDraw(canvas);
}
}
What am I doing wrong?
Thanks.
After hours trying to understand how I should use the drawables in a custom view in order to be displayed in its original size, I've figured out how to do it.
First a few things that I didn't know but are a must is:
The background drawable should be left to the parent class to be
drawn when using View as the parent. If not, the TransitionDrawable can't be seen fading between pictures.
Only if I am going to draw on the background drawable I should override onDraw() and do the drawing there.
And the last but not less important is that I should override onMeasure() to specify the size of the view. If I don't do it, it will fill all the free space in the parent layout, as it was happening to me.
I've passed the TransitionDrawable to the parent class with setBackgroundDrawable() and since I wasn't drawing in the background drawable, I've removed the onDraw() method. Also I've implemented onMeasure() with a quick and dirty solution specifying the size of the picture I am drawing.
This is the final result:
public class RecordButton extends View {
private static final String TAG = "RecordButton";
private static final int DESIRED_WIDTH = 180;
private static final int DESIRED_HEIGHT = 66;
private TransitionDrawable mDrawable;
private Rect mViewRect;
private boolean mActivated;
private OnClickListener mOnClickListenerInternal = new OnClickListener() {
#Override
public void onClick(View v) {
toggleState();
if(mOnClickListener != null) {
mOnClickListener.onClick(v);
}
}
};
private OnClickListener mOnClickListener = null;
public RecordButton(Context context) {
this(context, null, 0);
}
public RecordButton(Context context, AttributeSet attrib) {
this(context, attrib, 0);
}
public RecordButton(Context context, AttributeSet attrib, int defStyle) {
super(context, attrib, defStyle);
init();
}
public void setState(boolean activated) {
mActivated = activated;
if(mActivated){
mDrawable.startTransition(300);
}
else {
mDrawable.reverseTransition(300);
}
}
public void toggleState() {
if(mActivated) {
setState(false);
}
else {
setState(true);
}
}
#SuppressWarnings("deprecation")
private void init() {
mActivated = false;
mDrawable = (TransitionDrawable) getResources().getDrawable(R.drawable.btnrecord);
setBackgroundDrawable(mDrawable);
setClickable(true);
super.setOnClickListener(mOnClickListenerInternal);
invalidate();
}
public void setOnClickListener(View.OnClickListener listener) {
mOnClickListener = listener;
}
#Override
protected void onMeasure(int m, int n) {
setMeasuredDimension(DESIRED_WIDTH, DESIRED_HEIGHT);
}
}
I am learning how to code with Android but I am still confused bby the way it works, I am able to create simple draws like circles and stuff but now i want to paint the circle multiple times with a delay of 2 seconds.. I would appreciatge if you experts can help me improve my code and to put the stuff in the correct place
public class ColorChanges extends Activity {
DrawCircle dc;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
drawCircleToCanvas()
}
void drawCircleToCanvas()
{
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
dc.postInvalidate();
}
};
Thread updateUI = new Thread()
{
public void run() {
dc = new DrawCircle(this); //this line does not work
dc.setBackgroundColor(Color.WHITE);
setContentView(dc);
handler.sendEmptyMessage(0);
}
};
updateUI.start();
}
}
public class DrawCircle extends View {
Paint p1 = new Paint();
Paint p2 = new Paint();
Paint p3 = new Paint();
Paint pAll[] = new Paint[3];
public DrawCircle(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public DrawCircle(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public DrawCircle(Context context) {
super(context);
p1.setStyle(Paint.Style.STROKE);
p1.setColor(Color.GREEN);
p1.setStyle(Paint.Style.FILL);
p2.setStyle(Paint.Style.STROKE);
p2.setColor(Color.BLUE);
p2.setStyle(Paint.Style.FILL);
p3.setStyle(Paint.Style.STROKE);
p3.setColor(Color.YELLOW);
p3.setStyle(Paint.Style.FILL);
pAll[1] = p1;
pAll[2] = p2;
pAll[3] = p3;
// TODO Auto-generated constructor stub
}
#Override
public void onDraw(Canvas canvas)
{
for (int i = 0; i < pAll.length;i++)
{
canvas.drawCircle(200, 200, 100, pAll[i]);
}
}
}
If you want to draw the same circle with its color changing over the time (each 2 seconds as you mentionned) you should use an Handler
in order to create a timer and to switch the paint at each time it is called.
Do not forget to call the invalidate function inside your custom view, as this function ask the system to redraw the screen.