0

I'm developing an application in android studio. I currently have two parts, a MainActivity and a DrawingView. In the DrawingView is both a Canvas and a Button.

<com.jerem.simpledraw.DrawingView
    android:id="@+id/DrawingView"
    android:layout_width="wrap_content"
    android:layout_height="554dp"
    android:background="#ffffff"
    android:paddingBottom="40dp"
    android:paddingLeft="20dp"
    app:exampleColor="#33b5e5"
    app:exampleDimension="24sp"
    app:exampleDrawable="@android:drawable/ic_menu_add"
    app:exampleString="Hello, DrawingView" />

<Button
    android:text="Refresh"
    android:layout_height="wrap_content"
    android:id="@+id/buttonRefresh"
    android:layout_width="match_parent"
    android:layout_alignParentBottom="true"
    android:layout_alignParentStart="true"
    android:onClick="refreshCallback"/>

Above is the layout file for the drawing view. I want the button, when pressed, to call the method "refreshCallback", which is in the class DrawingView.

However, this warns me that it cannot find the method in the MainActivity.

I want to call a method in the DrawingView, not in the Main Activity. How can I fix this?

EDIT: I am updating to include the entire DrawingView class. I want to refresh the page.

package com.jerem.simpledraw;

import android.content.Context;
import android.graphics.Bitmap;
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;
import android.widget.Button;
import android.view.View.OnClickListener;

public class DrawingView extends View
{
//Constant
private int Colour = 0xFF000000;
private int screen_width;
private int screen_height;

//Drawing Var
private Canvas drawCanvas;
private Bitmap canvasBitmap;
private Path drawPath;
private Paint drawPaint;
private Paint canvasPaint;

public DrawingView(Context context, AttributeSet attributeSet){
    super(context, attributeSet);
    setupDrawing();
    setupUI();
}

private void setupUI() {

}

private void setupDrawing() {
    drawPath = new Path();
    drawPaint = new Paint();

    drawPaint.setColor(Colour);

    drawPaint.setAntiAlias(true);
    drawPaint.setStrokeWidth(20);
    drawPaint.setStyle(Paint.Style.STROKE);
    drawPaint.setStrokeJoin(Paint.Join.ROUND);
    drawPaint.setStrokeCap(Paint.Cap.ROUND);

    canvasPaint = new Paint(Paint.DITHER_FLAG);
}

@Override
protected void onDraw(Canvas canvas){
    canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
    canvas.drawPath(drawPath, drawPaint);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh){
    super.onSizeChanged(w, h, oldw, oldh);
    canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    drawCanvas = new Canvas(canvasBitmap);
}

private void handelAction(int action, int x, int y){
    switch(action) {
        case 0:
            drawPath.moveTo(x, y);
            break;
        case 2:
            drawPath.lineTo(x, y);
            break;
        case 1:
            drawCanvas.drawPath(drawPath, drawPaint);
            break;
    }
    {
        invalidate();
    }
}

@Override
public boolean onTouchEvent(MotionEvent event){
    float x = event.getX();
    float y = event.getY();

    System.out.println(event.getAction());
    handelAction(event.getAction(), (int) x, (int) y);
    return true;
}

public void refreshCallback(View v){
    System.out.println("Refresh Command Sent");
    this.setupDrawing();
}

}
Haem
  • 929
  • 6
  • 15
  • 31
jezza
  • 111
  • 1
  • 1
  • 10

3 Answers3

0

You can only call the activity's methods through the xml onClick. Therefore, you need a method in your MainActivity to pass the function call to the sibling view. If you're wondering why this is, consider this: How should the runtime decide which of the current views' methods should be called when the user clicks the button?

EDIT: Today I learned that it is in fact possible to refer to a static method in your activity class through onClick. If you intent to use non-static methods of your activity, you shouldn't declare the method as static, (and vice versa, I suppose).

Haem
  • 929
  • 6
  • 15
  • 31
  • Okay, thanks. Is there any way to get the CURRENT INSTANCE of the Drawing View in the main activity? findViewbyId seems to just return a static reference – jezza Feb 06 '17 at 13:21
  • Do you change the current instance somewhere? If you do, you should either give the new instance the same id as the old instance, or save the reference to the new instance. If not, findViewById should be enough. – Haem Feb 06 '17 at 13:23
  • It is created through the code setContentView(R.layout.sample_drawing_view); When I use findViewByID, I cannot access variables or use any method that is not static – jezza Feb 06 '17 at 13:26
  • The variables are marked as private, so that explains why you can't access them. How exactly are you trying to access the methods, and which of them are you trying to access? I'd think the instance returned by findViewById would be the one where you can access the non-static methods. – Haem Feb 06 '17 at 13:30
  • Try with this.getParent().findViewById(...) – Valentino Feb 06 '17 at 13:31
  • I made the variables public, and tried drawing WHITE over the canvas. I get this error http://i.imgur.com/h72hYwF.png – jezza Feb 06 '17 at 13:38
  • This is an error related to calling from a static context – jezza Feb 06 '17 at 13:39
  • So it's not just that you used the British spelling for ```drawColor```? Also, did you declare the ```MainWindow ```'s ```refreshCallback``` as static? – Haem Feb 06 '17 at 13:42
  • It's not, but thanks for pointing out the typo. Now it has no error, but the function doesn't do anything. Also, no I didn't - why would I? – jezza Feb 06 '17 at 13:52
  • This seems to be turning into an [XY Problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). You might want to make a separate question about what you're struggling with now. – Haem Feb 06 '17 at 19:17
0

The fact is onclick only tries to find the method that the current class is in which is using it. You can do this if you want, follow the steps :-

MainActivity:

public void callRefreshCallback(View v){
   (new DesignView()).refreshCallback(v);
}

DesignView:

public static void refreshCallback(View v){
//dosomething.
}

MainActivity.xml:

android:onClick="callRefreshCallback" 
jack jay
  • 2,493
  • 1
  • 14
  • 27
  • Please, is there any way to do this where refershCallback is not static? I cannot do what I want with a static method – jezza Feb 06 '17 at 13:23
  • simple `new DrawingView().refreshCallback()`, if you dont have any instance of `DrawingView` in `MainActivity`. – jack jay Feb 06 '17 at 13:25
  • Drawing view is already created through the code setContentView(R.layout.sample_drawing_view); If I create a new DrawingView, will that not mess things up? – jezza Feb 06 '17 at 13:25
  • Using Drawing view object you can call that method. – Mayur Gangurde Feb 06 '17 at 13:27
  • Its not producing instance of `DrawingView` its just setting your `sample_drawing_view.xml` to `MainActivity`. – jack jay Feb 06 '17 at 13:28
  • Hey, if I create it in this way what do I pass to the (Context context, AttributeSet attributeSet), parameters? – jezza Feb 06 '17 at 13:29
  • define one more constructor in `DrawingView` as `public DrawingView(Context context)` and then write `(new DesignView(getApplication.context())).refreshCallback(v);` – jack jay Feb 06 '17 at 13:35
0

Try this code in Activity class.

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sample_drawing_view);
        DrawingView drawingView = (DrawingView) findViewById(R.id.DrawingView);
        Button buttonRefresh = (Button) findViewById(R.id.buttonRefresh);
        buttonRefresh.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                drawingView.refreshCallback(view);
            }
        });
}
Mayur Gangurde
  • 1,552
  • 12
  • 22