onyx-intl / OnyxAndroidDemo

160 stars 41 forks source link

Null SurfaceView #25

Closed MrRSquared closed 4 years ago

MrRSquared commented 4 years ago

Hello, Since the demos are not working, I tried to implement the scribble_touch_helper_stylus_demo on my own, but I keep getting the following error.

Caused by: java.lang.IllegalArgumentException: hostView should not be null! Here is a copy of my main activity which is mostly just copied from the sample...

package com.r2.myscribbledemo;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;

//Onyx Imports

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.Rect;
import android.util.Log;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.RadioButton;

import com.r2.myscribbledemo.TouchUtils;
import com.r2.myscribbledemo.R;
import com.onyx.android.sdk.api.device.epd.EpdController;
import com.onyx.android.sdk.pen.BrushRender;
import com.onyx.android.sdk.pen.RawInputCallback;
import com.onyx.android.sdk.pen.TouchHelper;
import com.onyx.android.sdk.pen.data.TouchPoint;
import com.onyx.android.sdk.pen.data.TouchPointList;

import java.util.ArrayList;
import java.util.List;

import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnCheckedChanged;
import butterknife.OnClick;

public class MainActivity extends AppCompatActivity {

    //Setup variables and constants
    private static final String TAG = MainActivity.class.getSimpleName();
    /** skip point count*/
    private static final int INTERVAL = 10;

    @Bind(R.id.button_pen)
    Button buttonPen;
    @Bind(R.id.button_eraser)
    Button buttonEraser;
    @Bind(R.id.surfaceview)
    SurfaceView surfaceView;
    @Bind(R.id.cb_render)
    CheckBox cbRender;
    @Bind(R.id.rb_brush)
    RadioButton rbBrush;
    @Bind(R.id.rb_pencil)
    RadioButton rbPencil;

    private TouchHelper touchHelper;

    private Paint paint = new Paint();
    private TouchPoint startPoint;
    private int countRec = 0;

    private Bitmap bitmap;
    private Canvas canvas;

    private final float STROKE_WIDTH = 3.0f;

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

        ButterKnife.bind(this);
        initPaint();
        initSurfaceView();
    }

    @Override
    protected void onResume() {
        touchHelper.setRawDrawingEnabled(true);
        super.onResume();
    }

    @Override
    protected void onPause() {
        touchHelper.setRawDrawingEnabled(false);
        super.onPause();
    }

    @Override
    protected void onDestroy() {
        touchHelper.closeRawDrawing();
        if (bitmap !=null) {
            bitmap.recycle();
            bitmap = null;
        }
        super.onDestroy();
    }

    private void initPaint(){
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(Color.BLACK);
        paint.setStrokeWidth(STROKE_WIDTH);
    }

    private void initSurfaceView() {
        touchHelper = TouchHelper.create(surfaceView, callback);

        surfaceView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
            @Override
            public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int
                    oldRight, int oldBottom) {
                if (cleanSurfaceView()){
                    surfaceView.removeOnLayoutChangeListener(this);
                }
                List<Rect> exclude = new ArrayList<>();
                exclude.add(getRelativeRect(surfaceView, buttonEraser));
                exclude.add(getRelativeRect(surfaceView, buttonPen));
                exclude.add(getRelativeRect(surfaceView, cbRender));
                exclude.add(getRelativeRect(surfaceView, rbBrush));
                exclude.add(getRelativeRect(surfaceView, rbPencil));

                Rect limit = new Rect();
                surfaceView.getLocalVisibleRect(limit);
                touchHelper.setStrokeWidth(STROKE_WIDTH)
                        .setLimitRect(limit, exclude)
                        .openRawDrawing();
                touchHelper.setStrokeStyle(TouchHelper.STROKE_STYLE_BRUSH);
            }
        });
    }

    @OnClick(R.id.button_pen)
    public void onPenClick() {
        touchHelper.setRawDrawingEnabled(true);
        onRenderEnableClick();
    }

    @OnClick(R.id.button_eraser)
    public void onEraserClick() {
        touchHelper.setRawDrawingEnabled(false);
        if (bitmap !=null) {
            bitmap.recycle();
            bitmap = null;
        }
        cleanSurfaceView();
    }

    @OnCheckedChanged(R.id.cb_render)
    public void onRenderEnableClick() {
        touchHelper.setRawDrawingRenderEnabled(cbRender.isChecked());
        if (bitmap !=null) {
            bitmap.recycle();
            bitmap = null;
        }
        Log.d(TAG,"onRenderEnableClick setRawDrawingRenderEnabled =  " + cbRender.isChecked());
    }

    @OnClick({R.id.rb_brush, R.id.rb_pencil})
    public void onRadioButtonClicked(RadioButton radioButton) {

        boolean checked = radioButton.isChecked();
        Log.d(TAG, radioButton.toString());
        switch (radioButton.getId()) {
            case R.id.rb_brush:
                if (checked) {
                    touchHelper.setStrokeStyle(TouchHelper.STROKE_STYLE_BRUSH);
                    Log.d(TAG, "STROKE_STYLE_BRUSH");
                }
                break;
            case R.id.rb_pencil:
                if (checked) {
                    touchHelper.setStrokeStyle(TouchHelper.STROKE_STYLE_PENCIL);
                    Log.d(TAG, "STROKE_STYLE_PENCIL");
                }
                break;
        }
        // refresh ui
        onEraserClick();
        onPenClick();
    }

    public Rect getRelativeRect(final View parentView, final View childView) {
        int [] parent = new int[2];
        int [] child = new int[2];
        parentView.getLocationOnScreen(parent);
        childView.getLocationOnScreen(child);
        Rect rect = new Rect();
        childView.getLocalVisibleRect(rect);
        rect.offset(child[0] - parent[0], child[1] - parent[1]);
        return rect;
    }

    private boolean cleanSurfaceView() {
        if (surfaceView.getHolder() == null) {
            return false;
        }
        Canvas canvas = surfaceView.getHolder().lockCanvas();
        if (canvas == null) {
            return false;
        }
        canvas.drawColor(Color.WHITE);
        surfaceView.getHolder().unlockCanvasAndPost(canvas);
        return true;
    }

    private void drawRect(TouchPoint endPoint){
        Canvas canvas = surfaceView.getHolder().lockCanvas();
        if (canvas == null ) {
            return;
        }

        if (startPoint == null || endPoint == null) {
            surfaceView.getHolder().unlockCanvasAndPost(canvas);
            return;
        }

        canvas.drawColor(Color.WHITE);
        canvas.drawRect(startPoint.getX(), startPoint.getY(), endPoint.getX(), endPoint.getY(), paint);
        Log.d(TAG,"drawRect ");
        surfaceView.getHolder().unlockCanvasAndPost(canvas);
    }

    private RawInputCallback callback = new RawInputCallback() {

        @Override
        public void onBeginRawDrawing(boolean b, TouchPoint touchPoint) {
            Log.d(TAG, "onBeginRawDrawing");
            startPoint = touchPoint;
            Log.d(TAG,touchPoint.getX() +", " +touchPoint.getY());
            countRec = 0;
            TouchUtils.disableFingerTouch(getApplicationContext());
        }

        @Override
        public void onEndRawDrawing(boolean b, TouchPoint touchPoint) {
            Log.d(TAG, "onEndRawDrawing###");
            if (!cbRender.isChecked()){
                drawRect(touchPoint);
            }
            Log.d(TAG,touchPoint.getX() +", " +touchPoint.getY());
            TouchUtils.enableFingerTouch(getApplicationContext());
        }

        @Override
        public void onRawDrawingTouchPointMoveReceived(TouchPoint touchPoint) {
            Log.d(TAG, "onRawDrawingTouchPointMoveReceived");
            Log.d(TAG,touchPoint.getX() +", " +touchPoint.getY());
            countRec++;
            countRec = countRec % INTERVAL;
            Log.d(TAG,"countRec = " + countRec);
        }

        @Override
        public void onRawDrawingTouchPointListReceived(TouchPointList touchPointList) {
            Log.d(TAG, "onRawDrawingTouchPointListReceived");
            drawScribbleToBitmap(touchPointList.getPoints());
        }

        @Override
        public void onBeginRawErasing(boolean b, TouchPoint touchPoint) {
            Log.d(TAG, "onBeginRawErasing");
        }

        @Override
        public void onEndRawErasing(boolean b, TouchPoint touchPoint) {
            Log.d(TAG, "onEndRawErasing");
        }

        @Override
        public void onRawErasingTouchPointMoveReceived(TouchPoint touchPoint) {
            Log.d(TAG, "onRawErasingTouchPointMoveReceived");
        }

        @Override
        public void onRawErasingTouchPointListReceived(TouchPointList touchPointList) {
            Log.d(TAG, "onRawErasingTouchPointListReceived");
        }
    };

    private void drawScribbleToBitmap(List<TouchPoint> list) {
        if (!cbRender.isChecked()) {
            return;
        }
        if (bitmap == null) {
            bitmap = Bitmap.createBitmap(surfaceView.getWidth(), surfaceView.getHeight(), Bitmap.Config.ARGB_8888);
            canvas = new Canvas(bitmap);
        }

        if (rbBrush.isChecked()) {
            float maxPressure = EpdController.getMaxTouchPressure();
            BrushRender.drawStroke(canvas, paint, list, STROKE_WIDTH, maxPressure);
        }

        if (rbPencil.isChecked()) {
            Path path = new Path();
            PointF prePoint = new PointF(list.get(0).x, list.get(0).y);
            path.moveTo(prePoint.x, prePoint.y);
            for (TouchPoint point : list) {
                path.quadTo(prePoint.x, prePoint.y, point.x, point.y);
                prePoint.x = point.x;
                prePoint.y = point.y;
            }
            canvas.drawPath(path, paint);
        }
    }

    private void drawBitmapToSurface() {
        if (!cbRender.isChecked()) {
            return;
        }
        if (bitmap == null) {
            return;
        }
        Canvas lockCanvas= surfaceView.getHolder().lockCanvas();
        if (lockCanvas == null) {
            return;
        }
        lockCanvas.drawColor(Color.WHITE);
        lockCanvas.drawBitmap(bitmap, 0f, 0f, paint);
        surfaceView.getHolder().unlockCanvasAndPost(lockCanvas);
        // refresh ui
        touchHelper.setRawDrawingEnabled(false);
        touchHelper.setRawDrawingEnabled(true);
        if (!cbRender.isChecked()) {
            touchHelper.setRawDrawingRenderEnabled(false);
        }
    }
}
MrRSquared commented 4 years ago

I am also noticing that if I attempt to utilize the touchHelper on an already established surfaceView, like so...

touchHelper.setup(view)
           .setStrokeWidth(3.0f)
           .setUseRawInput(true)
           .setLimitRect(limit, exclude)
           .openRawDrawing();

I get the following error... Cannot resolve method 'setup' in 'TouchHelper' Does anyone have any thoughts?

MrRSquared commented 4 years ago

After trying to implement the scribble library for the past few days, I am having this issue with all the various examples.

MrRSquared commented 4 years ago

I found the solution to this one... If you look at the ScribbleMultipleScribbleViewActivity, you can see around line 52, it does this... touchHelper = TouchHelper.create(getWindow().getDecorView().getRootView(), getRawInputCallback()); Which sets one input TouchHelper for the entire window. From there, you can create new instances of the surfaceView.

        initSurfaceView(surfaceView1);
        initSurfaceView(surfaceView2);