假设我有一个在主活动中托管的自定义图纸视图。现在,当设备的方向发生变化时,我正在努力保存绘图状态。我在定向更改后得到NullPointerException
。所以我可以毫无问题地绘制,但在旋转设备后它会崩溃。请给我一个暗示,我很沮丧。这是我的绘图视图。在此行中获取NPE:drawCanvas.drawPath(drawPath, drawPaint);
在轮换后调用performTouchEvent()
public class DrawingView extends View {
private static final String EXTRA_EVENT_LIST = "event_list";
private static final String EXTRA_STATE = "instance_state";
private ArrayList<MotionEvent> eventList = new ArrayList<MotionEvent>(100);
private ArrayList<MotionEvent> myObject = new ArrayList<MotionEvent>(100);
//drawing path
private Path drawPath;
//drawing and canvas paint
private Paint drawPaint, canvasPaint;
//initial color
private int paintColor = 0xFF660000, paintAlpha = 255;
//canvas
private Canvas drawCanvas;
//canvas bitmap
private Bitmap canvasBitmap;
//brush sizes
private float brushSize, lastBrushSize;
//erase flag
private boolean erase=false;
public DrawingView(Context context, AttributeSet attrs){
super(context, attrs);
setupDrawing();
}
//setup drawing
private void setupDrawing(){
//prepare for drawing and setup paint stroke properties
brushSize = getResources().getInteger(R.integer.medium_size);
lastBrushSize = brushSize;
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);
canvasPaint = new Paint(Paint.DITHER_FLAG);
}
//size assigned to view
@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);
}
//draw the view - will be called after touch event
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
canvas.drawPath(drawPath, drawPaint);
}
//register user touches as drawing action
@Override
public boolean onTouchEvent(MotionEvent event) {
getParent().requestDisallowInterceptTouchEvent(true);
//respond to down, move and up events
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
performTouchEvent(event);
}
//redraw
invalidate();
eventList.add(MotionEvent.obtain(event));
return true;
}
private void performTouchEvent(MotionEvent event) {
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;
}
invalidate();
eventList.add(MotionEvent.obtain(event));
}
//update color
public void setColor(String newColor){
invalidate();
//check whether color value or pattern name
if(newColor.startsWith("#")){
paintColor = Color.parseColor(newColor);
drawPaint.setColor(paintColor);
drawPaint.setShader(null);
}
else{
//pattern
int patternID = getResources().getIdentifier(
newColor, "drawable", "com.androbro.navigationdrawerproject");
//decode
Bitmap patternBMP = BitmapFactory.decodeResource(getResources(), patternID);
//create shader
BitmapShader patternBMPshader = new BitmapShader(patternBMP,
Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
//color and shader
drawPaint.setColor(0xFFFFFFFF);
drawPaint.setShader(patternBMPshader);
}
}
//set brush size
public void setBrushSize(float newSize){
float pixelAmount = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
newSize, getResources().getDisplayMetrics());
brushSize=pixelAmount;
drawPaint.setStrokeWidth(brushSize);
}
//get and set last brush size
public void setLastBrushSize(float lastSize){
lastBrushSize=lastSize;
}
public float getLastBrushSize(){
return lastBrushSize;
}
//set erase true or false
public void setErase(boolean isErase){
erase=isErase;
if(erase) {
drawPaint.setColor(Color.WHITE);//set the color to white
}
else drawPaint.setColor(paintColor); //if erase is set to false, it will use the previous color.
}
//start new drawing
public void startNew(){
drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
invalidate();
}
//return current alpha
public int getPaintAlpha(){
return Math.round((float)paintAlpha/255*100);
}
//set alpha
public void setPaintAlpha(int newAlpha){
paintAlpha=Math.round((float)newAlpha/100*255);
drawPaint.setColor(paintColor);
drawPaint.setAlpha(paintAlpha);
}
@Override
public Parcelable onSaveInstanceState()
{
Log.i("Saving", "drawing");
Bundle bundle = new Bundle();
bundle.putParcelable(EXTRA_STATE, super.onSaveInstanceState());
bundle.putParcelableArrayList(EXTRA_EVENT_LIST, eventList);
return bundle;
}
@Override
public void onRestoreInstanceState(Parcelable state)
{
Log.i("OnRestore", "state");
if (state instanceof Bundle)
{
Bundle bundle = (Bundle) state;
super.onRestoreInstanceState(bundle.getParcelable(EXTRA_STATE));
eventList = bundle.getParcelableArrayList(EXTRA_EVENT_LIST);
if (eventList != null) {
Log.i("EventList", "is not null");
myObject = new ArrayList<>(eventList);
} else{
return;
}
for (MotionEvent event : myObject) {
Log.i("Event", "" + event);
performTouchEvent(event);
}
return;
}
super.onRestoreInstanceState(state);
}
}
答案 0 :(得分:0)
通过设备轮换,Activity
将被销毁以及视图,您应该覆盖onSaveInstanceState(Bundle outState)
方法以将重要数据保存在Bundle
对象中并重新恢复,请记住这一点对象应该实现Parcelable
Interface
,实际上在您的情况下Bitmap
对象是Parcelable
但如果您因屏幕大小更改而将其传递给Bundle
,则视图的大小会有所不同,您需要一个不同大小的Bitmap
。
另一种方法是扩展图形Path
并实施Parcelable
,以便您可以使用Bundle
传递它,并在轮换后重绘Path
。
如果您想了解有关Parcelable
的更多信息,请查看此内容: