Android:如何在方向更改时保存自定义手指绘画视图 [英] Android: How to save custom finger paint view on orientation change

查看:77
本文介绍了Android:如何在方向更改时保存自定义手指绘画视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个自定义视图,用户可以在其中绘制其签名.您可以在其中以编程方式将其放置到视图中并设置大小等.在此之前我没有做过此事,因此我将其基于android api演示的fingerpaint类.现在的问题是,它会在方向改变时擦除对象,我不确定如何使它不这样做.

I'm trying to create a custom view where a user can draw their signature. One where you can put it into the view programmatically and set the size, etc. I haven't had to do this before so I based it off the fingerpaint class from android api demos. Problem right now is that it erases the object on orientation change and I'm not sure how to get it to not do that.

PaintView的代码

The code for PaintView

private Bitmap  mBitmap;
private Canvas  mCanvas;
private Path    mPath;
private Paint   mBitmapPaint;
private boolean mDrawPoint;

private int stateToSave;

private Paint mPaint;


public PaintView(Context context) {
    super(context);
    System.out.println("init");
    mPath = new Path();
    mBitmapPaint = new Paint(Paint.DITHER_FLAG);
    setupPaint();
}

private void setupPaint()
{
    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setDither(true);
    mPaint.setColor(0xFF000000);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.ROUND);
    mPaint.setStrokeWidth(4);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    System.out.println("w "+w+" h "+h+" oldw "+oldw+" oldh "+oldh);
    mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    mCanvas = new Canvas(mBitmap);
}

@Override
protected void onDraw(Canvas canvas) {
    System.out.println("on draw");
    canvas.drawColor(0xFFAAAAAA);

    canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);

    canvas.drawPath(mPath, mPaint);
}

private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;

private void touch_start(float x, float y) {
    mPath.reset();
    mPath.moveTo(x, y);
    mX = x;
    mY = y;
    mDrawPoint=true;
}
private void touch_move(float x, float y) {
    float dx = Math.abs(x - mX);
    float dy = Math.abs(y - mY);
    if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
        mDrawPoint=false;
        mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
        mX = x;
        mY = y;
    }
}
private void touch_up() {
    if(mDrawPoint == true) {
        mCanvas.drawPoint(mX, mY, mPaint);
    } else {
        mPath.lineTo(mX, mY);
        // commit the path to our offscreen
        mCanvas.drawPath(mPath, mPaint);
        // kill this so we don't double draw
        mPath.reset();
    }
}

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

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            touch_start(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_MOVE:
            touch_move(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_UP:
            touch_up();
            invalidate();
            break;
    }
    return true;
}

我添加了一个迷你测试

@Override
public Parcelable onSaveInstanceState() 
{
    System.out.println("save instance");
    stateToSave++;
    Bundle bundle = new Bundle();
    bundle.putParcelable("instanceState", super.onSaveInstanceState());  
    bundle.putInt("stateToSave", this.stateToSave);

    return bundle;
}

@Override
public void onRestoreInstanceState(Parcelable state) 
{
    System.out.println("on restore");
    if (state instanceof Bundle) 
    {
        System.out.println("on restore");
        Bundle bundle = (Bundle) state;
        this.stateToSave = bundle.getInt("stateToSave");
        super.onRestoreInstanceState(bundle.getParcelable("instanceState"));
        System.out.println(stateToSave);
        return;
    }
    super.onRestoreInstanceState(state);
}

但是onRestoreInstance()和onSaveInstance()永远不会在方向更改时被调用.这是我创建paintview的活动中oncreate中的代码.

But onRestoreInstance() and onSaveInstance() never get called on orientation change. Here is my code in the oncreate in the activity that makes a paintview.

RelativeLayout inner= (RelativeLayout) findViewById(R.id.inner);

    int width=600;
    int height=360;
    float X= 100;
    float Y=60;

    LayoutParams wrapped = new LayoutParams(width,height);

    PaintView painting=new PaintView(this);

    painting.setX(X);
    painting.setY(Y);
    painting.setLayoutParams(wrapped);
    inner.addView(painting);

我弄清楚了为什么saveinstancestate没有调用,我必须给View提供一个ID,然后它才能工作.

I figured it out why saveinstancestate wasn't calling, I had to give the View an ID and then it would work.

painting.setId(4);

painting.setId(4);

现在,我需要弄清楚如何使其保存图形.

Now I need to figure out how to make it save the drawing.

推荐答案

您需要确保您的视图为

You need to make sure your View is saveEnabled, try:

setSaveEnabled(true);

您可以从PaintView的构造函数中执行此操作.

You could do this from the constructor of your PaintView.

此外,您可能需要确保您的活动在方向改变时被销毁/重新创建.确保您不要具有:

Also, you may need to make sure that your activities are being destroyed/recreated on orientation change. Make sure you DO NOT have:

<activity name="?"
android:configChanges="keyboardHidden|orientation"
/>

使用此视图为该活动声明了该活动,否则该活动不会在方向更改时被破坏.另外,如果您在这些活动中覆盖了 onSaveInstanceState /* onRestoreInstanceState *,则需要调用相应的超类方法,即super.onSaveInstanceStateState()或super.onRestoreInstanceState()).

declared for the activity using this View or else the activity won't be destroyed on orientation change. Also, if you have overridden onSaveInstanceState/*onRestoreInstanceState* in those activities you need to call the respective superclass method, either super.onSaveInstanceState() or super.onRestoreInstanceState())

关于如何实际重新创建或保存图像以改变方向的操作,如何保存在某种可包裹列表中完成的每个事件的方式.将该列表保存在onSaveInstanceState中,然后将其还原到onRestoreInstanceState中.然后获取事件列表并遍历事件列表,调用相应的绘制函数. 您可能需要根据新的方向对X,Y值进行一些转换.

As far as how to actually recreate or save the image for orientation changes how about you save each event that is done in some kind of parcelable List. Save that list in onSaveInstanceState and restore it in onRestoreInstanceState. THen take the list of events and loop through it, calling the respective draw functions. You may need to do some translation of X,Y values based on the new orientation.

代码看起来像这样:

public class PaintView 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);

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        getParent().requestDisallowInterceptTouchEvent(true);           
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
            case MotionEvent.ACTION_UP:
            performTouchEvent(event);                
        }             
        return true;
    }

    private void performTouchEvent(MotionEvent event) {
        float x = event.getX();
            float y = event.getY();
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
                touch_start(x, y);
                break;
            case MotionEvent.ACTION_MOVE:
                touch_move(x, y);
                break;
            case MotionEvent.ACTION_UP:
                touch_up();
                break;
                }
                invalidate();
                eventList.add(MotionEvent.obtain(event));           
        }
    }


    @Override
    public Parcelable onSaveInstanceState() 
    {
        System.out.println("save instance");
        Bundle bundle = new Bundle();
        bundle.putParcelable(EXTRA_STATE, super.onSaveInstanceState());  
        bundle.putParcelableArrayList(EXTRA_EVENT_LIST, eventList);

    return bundle;
    }

    @Override
    public void onRestoreInstanceState(Parcelable state) 
    {
        if (state instanceof Bundle) 
        {
            Bundle bundle = (Bundle) state;
            super.onRestoreInstanceState(bundle.getParcelable(EXTRA_STATE));
            eventList = bundle.getParcelableArrayList(EXTRA_EVENT_LIST);
            if (eventList == null) {
               eventList = new ArrayList<MotionEvent>(100); 
            }
            for (MotionEvent event : eventList) {
               performTouchEvent(event);
            }               
            return;
        }
        super.onRestoreInstanceState(state);
    }
}

这篇关于Android:如何在方向更改时保存自定义手指绘画视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆