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();
}
}
Related
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 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);
}
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);
}
}
So basically I have some image views drawn over my canvas, but when I try to set up onclick listeners and try to handle events, it doesn't work.
public class DrawView extends View implements OnClickListener{
Paint paint = new Paint();
RectF rf = new RectF(30, 30, 80, 80);
BallView ball = new BallView(getContext());
Bitmap bmp = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.ic_launcher);
public DrawView(Context context) {
super(context);
}
#Override
public void onDraw(Canvas canvas) {
ball.setOnClickListener(this);
ball.draw(canvas);
canvas.drawBitmap(bmp, 110, 10, paint);
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(getContext(), "Mock", Toast.LENGTH_SHORT).show();
}
}
BallView.java
public class BallView extends ImageView {
Paint b = new Paint();
public BallView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public void onDraw(Canvas c){
b.setColor(Color.BLUE);
c.drawCircle(50, 50, 40, b);
}
}
Basically the answer is: Your view is not receiving touch events, because it's not in views hierarchy, so click callback is also not called. Actually, view should be in View hierarchy (in other words, added to some upper level view and finally, to the window) in order to participate is user interactions.
So, if You want to implement somthing covering Your view, then it should be ViewGroup or shouldn't be related to view at all and be some abstract container.
E.g. using the way below click works without any issues (but You will need second view or modify BallView to draw bmp):
DrawView:
public class DrawView extends FrameLayout implements View.OnClickListener {
BallView ball = new BallView(getContext());
public DrawView(Context context) {
this(context, null, 0);
}
public DrawView(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
public DrawView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
addView(ball);
ball.setOnClickListener(this);
}
#Override
public void onClick(View v) {
Toast.makeText(getContext(), "Mock", Toast.LENGTH_SHORT).show();
}
}
BallView class stays the same.
Layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.ruinalst.performance.tests.views.DrawView
android:id="#+id/oscillator"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true" />
</RelativeLayout>
I'm working on a Livewallpaper with a Thread Painting all Objects and Custom Objects extended from View. The Problem is that my custom view doesn't fire on click....
Here are the Code Snippeds:
in my WallpaperService Class the OnTouch ist given to my Painting Thread:
#Override
public void onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
painting.doTouchEvent(event);
}
Then in the constructor of my PaintingThread I'm creating instances of my custom view:
public LiveWallpaperPainting(SurfaceHolder surfaceHolder, Context context) {
for(int i = 0; i < numberOfObj;i++ ){
obj.add(new Obj(context,objBitmap, objBitmap2, mCanvasWidth, mCanvasHeight, 32, 32 , 20, 10));
}
Then in the Constructor of my Obj:
super(context);
this.context = context;
this.setEnabled(true);
this.setFocusable(true);
this.setFocusableInTouchMode(true);
this.setClickable(true);
this.setOnClickListener(this);
The Class implements OnClickListener.
But when I'm logging the onClick nothing happens....:
#Override
public void onClick(View v) {
Log.d(TAG, "clicked");
}
I'm getting crazy because I tried so much, but nothing worked... :( Please help me.
I think the OnClick is catched before my Obj can react?? But don't know why....
I hope I gave you all details needed...
Yumi
The following code works. Have you on the Activity a other OnClickListener?
public class CustomView extends View implements OnClickListener {
Paint paint;
public CustomView(Context context) {
this(context, null);
}
public CustomView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint = new Paint();
paint.setColor(Color.BLUE);
canvas.drawRect(0.f, 0.f, 240.f, 240.f, paint);
this.setOnClickListener(this);
}
#Override
public void onClick(View v) {
Log.d("CustomView", "Click");
}}
main.xml
<com.examples.view.CustomView
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />