简体   繁体   中英

RuntimeException: Unable to start activity(MainActivity cannot be cast to android.view.View$OnClickListener)

I am working on a drawing app and following the online tutorial here: http://mobile.tutsplus.com/tutorials/android/android-sdk-create-a-drawing-app-essential-functionality/

There are no problem until the last part (as above). Then, I have tried to Clean and import the project again (virtual device was restarted everytime), but the problem still exists.

Would you mind help me to take a look at this?
Thanks in advance!!

PS I am using Eclipse ADT

Here is the error log:

09-01 03:27:25.144: E/AndroidRuntime(788): FATAL EXCEPTION: main
09-01 03:27:25.144: E/AndroidRuntime(788): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.earth0102.luckydraw/com.earth0102.luckydraw.MainActivity}: java.lang.ClassCastException: com.earth0102.luckydraw.MainActivity cannot be cast to android.view.View$OnClickListener
09-01 03:27:25.144: E/AndroidRuntime(788):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
09-01 03:27:25.144: E/AndroidRuntime(788):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
09-01 03:27:25.144: E/AndroidRuntime(788):  at android.app.ActivityThread.access$600(ActivityThread.java:141)
09-01 03:27:25.144: E/AndroidRuntime(788):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
09-01 03:27:25.144: E/AndroidRuntime(788):  at android.os.Handler.dispatchMessage(Handler.java:99)
09-01 03:27:25.144: E/AndroidRuntime(788):  at android.os.Looper.loop(Looper.java:137)
09-01 03:27:25.144: E/AndroidRuntime(788):  at android.app.ActivityThread.main(ActivityThread.java:5041)
09-01 03:27:25.144: E/AndroidRuntime(788):  at java.lang.reflect.Method.invokeNative(Native Method)
09-01 03:27:25.144: E/AndroidRuntime(788):  at java.lang.reflect.Method.invoke(Method.java:511)
09-01 03:27:25.144: E/AndroidRuntime(788):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
09-01 03:27:25.144: E/AndroidRuntime(788):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
09-01 03:27:25.144: E/AndroidRuntime(788):  at dalvik.system.NativeStart.main(Native Method)
09-01 03:27:25.144: E/AndroidRuntime(788): Caused by: java.lang.ClassCastException: com.earth0102.luckydraw.MainActivity cannot be cast to android.view.View$OnClickListener
09-01 03:27:25.144: E/AndroidRuntime(788):  at com.earth0102.luckydraw.MainActivity.onCreate(MainActivity.java:56)
09-01 03:27:25.144: E/AndroidRuntime(788):  at android.app.Activity.performCreate(Activity.java:5104)
09-01 03:27:25.144: E/AndroidRuntime(788):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
09-01 03:27:25.144: E/AndroidRuntime(788):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
09-01 03:27:25.144: E/AndroidRuntime(788):  ... 11 more

AndroidManifest.xml :

 <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="17" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/CustomTheme" > <activity android:name="com.earth0102.luckydraw.MainActivity" android:label="@string/app_name" android:screenOrientation="portrait"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> 

MainActivity.java

package com.earth0102.luckydraw;

import android.os.Bundle;
import android.app.Activity;
import android.app.Dialog;
import android.view.Menu;
//implement the ability for the user to choose colors
import android.view.View;
import android.widget.ImageButton;
import android.widget.LinearLayout;

//other features
import java.util.UUID;
import android.provider.MediaStore;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.view.View.OnClickListener;
import android.widget.Toast;


public class MainActivity extends Activity implements onClickListener
{
    //let user to choose colors from the palette
    private DrawingView drawView;

    //variable to represent the paint color button in the palette
    private ImageButton currPaint, drawBtn, eraseBtn, newBtn, saveBtn;

    //variable in three dimension
    private float smallBrush,mediumBrush,largeBrush;



    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        drawView=(DrawingView)findViewById(R.id.drawing);

        //1. retrieve the first paint color button in the palette area, which is initially going to be selected.
        LinearLayout paintLayout = (LinearLayout) findViewById(R.id.paint_colors);
        //2. get the first button and store it as the instance variable.
        currPaint = (ImageButton) paintLayout.getChildAt(0);
        //3. we use a different drawable image on the button to show that it is currently selected:
        currPaint.setImageDrawable(getResources().getDrawable(R.drawable.paint_pressed));

        smallBrush=getResources().getInteger(R.integer.small_size);
        mediumBrush=getResources().getInteger(R.integer.medium_size);
        largeBrush=getResources().getInteger(R.integer.large_size);

        //draw button
        drawBtn = (ImageButton)findViewById(R.id.draw_btn);
        drawBtn.setOnClickListener((OnClickListener)this);

        //erase button
        eraseBtn = (ImageButton)findViewById(R.id.erase_btn);
        eraseBtn.setOnClickListener((OnClickListener)this);

        //new painting
        newBtn = (ImageButton)findViewById(R.id.new_btn);
        newBtn.setOnClickListener((OnClickListener)this);

        //new painting
        saveBtn = (ImageButton)findViewById(R.id.save_btn);
        saveBtn.setOnClickListener((OnClickListener)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.main, menu);
        return true;
    }

    public void paintClicked(View view)
    {
        drawView.setBrushSize(drawView.getLastBrushSize());
        //use chosen color
        //1. check that the user has clicked a paint color

        if(view!=currPaint)
        {
            //update color
            ImageButton imgView = (ImageButton)view;
            String color = view.getTag().toString();
            drawView.setColor(color);

            //update the UI to reflect the new chosen paint and set the previous one back to normal
            imgView.setImageDrawable(getResources().getDrawable(R.drawable.paint_pressed));
            currPaint.setImageDrawable(getResources().getDrawable(R.drawable.paint));
            currPaint=(ImageButton)view;
        }

    }

    @Override
    public void onClick(View view) {
        // TODO Auto-generated method stub
        if(view.getId()==R.id.draw_btn)
        {
            //draw button clicked
            final Dialog brushDialog = new Dialog(this);
            brushDialog.setTitle("Brush size");

            brushDialog.setContentView(R.layout.brush_chooser);

            //listen for clicks on size buttons - small, medium, large
            ImageButton smallBtn = (ImageButton)brushDialog.findViewById(R.id.small_brush);
            smallBtn.setOnClickListener(new OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    drawView.setBrushSize(smallBrush);
                    drawView.setLastBrushSize(smallBrush);
                    brushDialog.dismiss();
                }
            });

            ImageButton mediumBtn = (ImageButton)brushDialog.findViewById(R.id.medium_brush);
            mediumBtn.setOnClickListener(new OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    drawView.setBrushSize(mediumBrush);
                    drawView.setLastBrushSize(mediumBrush);
                    brushDialog.dismiss();
                }
            });
            ImageButton largeBtn = (ImageButton)brushDialog.findViewById(R.id.large_brush);
            largeBtn.setOnClickListener(new OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    drawView.setBrushSize(largeBrush);
                    drawView.setLastBrushSize(largeBrush);
                    brushDialog.dismiss();
                }
            });

            brushDialog.show();

        }//end of draw button
        else if (view.getId()==R.id.erase_btn)
        {
            //switch to erase - choose size
            final Dialog brushDialog = new Dialog(this);
            brushDialog.setTitle("Eraser size:");
            brushDialog.setContentView(R.layout.brush_chooser);

            //cancel - listen for clicks on size buttons
            ImageButton smallBtn = (ImageButton)brushDialog.findViewById(R.id.small_brush);
            smallBtn.setOnClickListener(new OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    drawView.setBrushSize(smallBrush);
                    drawView.setLastBrushSize(smallBrush);
                    drawView.setErase(false);
                    brushDialog.dismiss();
                }
            });

            ImageButton mediumBtn = (ImageButton)brushDialog.findViewById(R.id.medium_brush);
            mediumBtn.setOnClickListener(new OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    drawView.setBrushSize(mediumBrush);
                    drawView.setLastBrushSize(mediumBrush);
                    drawView.setErase(false);
                    brushDialog.dismiss();
                }
            });

            //listen for clicks on size buttons
            ImageButton largeBtn = (ImageButton)brushDialog.findViewById(R.id.large_brush);
            largeBtn.setOnClickListener(new OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    drawView.setBrushSize(largeBrush);
                    drawView.setLastBrushSize(largeBrush);
                    drawView.setErase(false);
                    brushDialog.dismiss();
                }
            });

            brushDialog.show();

        }//end of erase button
        else if (view.getId()==R.id.new_btn)
        {
            String cancel = "Cancel";

            //new button
            AlertDialog.Builder newDialog = new AlertDialog.Builder(this);
            newDialog.setTitle("New drawing");
            newDialog.setMessage("Start new drawing (you will lose the current drawing)?");
            newDialog.setPositiveButton("Yes",new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    // TODO Auto-generated method stub
                    drawView.startNew();
                    dialog.dismiss();
                }
            });
                newDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener(){

                    public void onClick(DialogInterface dialog, int which){
                        dialog.cancel();
                    }
                });
                newDialog.show();

        }//end of new button
        else if (view.getId()==R.id.save_btn)
        {
            AlertDialog.Builder saveDialog = new AlertDialog.Builder(this);
            saveDialog.setTitle("Save drawing");
            saveDialog.setMessage("Save drawing to device Gallery?");
            saveDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener(){
                public void onClick(DialogInterface dialog, int which)
                {
                    //save drawing-use insertImage to attempt to write the image to the media store
                    //for images on the device, which should save it to the user gallery.
                    //We pass the content resolver, drawing cache for the displayed View, a randomly generated
                    //UUID string for the filename with JPG extension and a short description.
                    drawView.setDrawingCacheEnabled(true);
                    String imgSaved=MediaStore.Images.Media.insertImage(
                            getContentResolver(),drawView.getDrawingCache(),
                            UUID.randomUUID().toString()+".jpg","drawing");

                    if(imgSaved!=null)
                    {
                        Toast savedToast = Toast.makeText(getApplicationContext(),
                                "Drawing saved to Gallery!", Toast.LENGTH_SHORT);
                        savedToast.show();
                    }
                    else
                    {
                        Toast unsavedToast = Toast.makeText(getApplicationContext(), "Oops! Image could not be saved.", 
                                Toast.LENGTH_SHORT);                        
                        unsavedToast.show();
                    }
                    drawView.destroyDrawingCache();
                }
            });
            saveDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener(){

                public void onClick(DialogInterface dialog, int which){
                    dialog.cancel();
                }
            });
            saveDialog.show();

        }//end of save button

    }//onClick method

}

DrawingView.java

    package com.earth0102.luckydraw;

    import android.content.Context;
    import android.view.View;
    import android.util.AttributeSet;

    //for drawing
    import android.graphics.Bitmap;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.view.MotionEvent;

    //other features
    import android.graphics.PorterDuff;
    import android.graphics.PorterDuffXfermode;
    import android.util.TypedValue;

    public class DrawingView extends View 
    {
        private float brushSize, lastBrushSize;

        //eraser flag
        private boolean erase=false;

        //drawing path
        private Path drawPath;

        //drawing and canvas paint
        private Paint drawPaint, canvasPaint;

        //initial color
        private int paintColor = 0xFF000000;

        //canvas
        private Canvas drawCanvas;

        //canvas bitmap
        private Bitmap canvasBitmap;


        public DrawingView(Context context, AttributeSet attrs)
        {
            super(context, attrs);
            setupDrawing();
        }
private void setupDrawing()
    {
        //get drawing area setup for interaction

        brushSize=getResources().getInteger(R.integer.medium_size);
        lastBrushSize=brushSize;

        //initial objects
        drawPath=new Path();
        drawPaint =new Paint();

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

        //instantiating a canvas paint object
        canvasPaint = new Paint(Paint.DITHER_FLAG);
    }

    public void setBrushSize(float newSize)
    {
        //update size for each brush
        float pixelAmount = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 
                newSize, getResources().getDisplayMetrics());

        brushSize=pixelAmount;
        drawPaint.setStrokeWidth(brushSize);
    }

    public void setLastBrushSize(float lastSize)
    {
        lastBrushSize=lastSize;
    }
    public float getLastBrushSize()
    {
        return lastBrushSize;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh)
    {
        // override a couple of methods to make 
        //the custom View function as a drawing View

        //view given size
        super.onSizeChanged(w,h,oldw,oldh);

        canvasBitmap = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
        drawCanvas = new Canvas(canvasBitmap);
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        //To allow the class to function as a custom drawing View, 
        //we also need to override the onDraw method
        //draw view
        canvas.drawBitmap(canvasBitmap, 0,0, canvasPaint);
        canvas.drawPath(drawPath, drawPaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        //detect user touch

        float touchX=event.getX();
        float touchY=event.getY();

        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:
                drawPath.moveTo(touchX, touchY);
                break;
            case MotionEvent.ACTION_MOVE:
                drawPath.lineTo(touchX, touchY);
                break;
            case MotionEvent.ACTION_UP:
                drawPath.lineTo(touchX, touchY);
                drawCanvas.drawPath(drawPath, drawPaint);
                drawPath.reset();
                break;

            default:
                return false;
        }
        //redraw - Calling invalidate will cause the onDraw method to execute.
        invalidate();
        return true;

    }

    public void setColor(String newColor)
    {
        //set color and start by invalidating the view
        invalidate();

        //parse and set the color for drawing
        paintColor = Color.parseColor(newColor);
        drawPaint.setColor(paintColor);

    }

    public void setErase (Boolean isErase)
    {
        //set erase true or false
        erase=isErase;
        if(erase)
            drawPaint.setXfermode(new PorterDuffXfermode (PorterDuff.Mode.CLEAR));
        else
            drawPaint.setXfermode(null);
    }

    public void startNew()
    {
        //set a new draw
        drawCanvas.drawColor(0,PorterDuff.Mode.CLEAR);
        invalidate();
    }


}

OnClickListener.java - it's requested to add another class to implement onClickListener in MainActivity, and so on.

package com.earth0102.luckydraw;

import android.view.View;

public interface onClickListener 
{
    public void onClick(View view);
}

In the MainActivity onCreate function, you are doing:

drawBtn.setOnClickListener((OnClickListener)this);

Here you are casing this to OnClickListener which is giving error. this gives you the activity context . You can trying to cast the activity context to OnClickListener , which is creating the casting exception. You can try just passing in the Activity's context like:

drawBtn.setOnClickListener(this);

Do the same for all the other buttons and don't cast it to OnClickListener . See if this changes something.

In MainActivity, you should implement View.OnClickListener . in this case, you don't need your own interface OnClickListener.java, just use View.OnClickListener

I mean, change

public class MainActivity extends Activity implements onClickListener

to

public class MainActivity extends Activity implements View.OnClickListener

You are casting your activity to on click listener.Do like this:

Button.setonclicklistener(commonclicklistener);

Onclicklistener commonclicklistener = new view.onclicklistener{
    //add a switch case based on your buttons and perform the code here like
    Switch(v.getid)
        Case (draw button):
            //code
        Case(imagebuttpn):
            //code
}

This is an rough idea .you can find code in net.I am typing through mobile otherwise would have provided with the code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM