我正在开发一个绘图应用程序并遵循此处的在线教程:http: //mobile.tutsplus.com/tutorials/android/android-sdk-create-a-drawing-app-essential-functionality/
直到最后一部分(如上)都没有问题。然后,我尝试再次清理并导入项目(每次都重新启动虚拟设备),但问题仍然存在。
你介意帮我看看这个吗?
提前致谢!!
PS我正在使用Eclipse ADT
这是错误日志:
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
}
绘图视图.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 - 要求在MainActivity中添加另一个类来实现onClickListener,依此类推。
package com.earth0102.luckydraw;
import android.view.View;
public interface onClickListener
{
public void onClick(View view);
}