Android的UnsupportedOperationException异常在Canvas.cli

2019-07-04 09:54发布

我使用的图片剪裁库从这里https://github.com/lvillani/android-cropimage在我的项目裁剪存储在设备中的图像。

然而,某些用户报告以下堆栈跟踪崩溃

java.lang.UnsupportedOperationException
at android.view.GLES20Canvas.clipPath(GLES20Canvas.java:413)
at com.android.camera.HighlightView.draw(HighlightView.java:101)
at com.android.camera.CropImageView.onDraw(CropImage.java:783)
at android.view.View.draw(View.java:11006)
at android.view.View.getDisplayList(View.java:10445)
at android.view.ViewGroup.drawChild(ViewGroup.java:2850)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
at android.view.View.getDisplayList(View.java:10443)
at android.view.ViewGroup.drawChild(ViewGroup.java:2850)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
at android.view.View.getDisplayList(View.java:10443)
at android.view.ViewGroup.drawChild(ViewGroup.java:2850)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
at android.view.View.getDisplayList(View.java:10443)
at android.view.ViewGroup.drawChild(ViewGroup.java:2850)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
at android.view.View.getDisplayList(View.java:10443)
at android.view.ViewGroup.drawChild(ViewGroup.java:2850)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
at android.view.View.draw(View.java:11009)
at android.widget.FrameLayout.draw(FrameLayout.java:450)
at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2154)
at android.view.View.getDisplayList(View.java:10445)
at android.view.HardwareRenderer$GlRenderer.draw(HardwareRenderer.java:853)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:1961)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1679)
at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2558)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4697)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:787)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:554)
at dalvik.system.NativeStart.main(Native Method)

从搜索,我认为它是由硬件加速仅某些设备造成的。 我有禁用硬件加速在我的清单,但异常仍然发生。 我还发现“一个坚实的解决方法是,以确定有问题的操作在你的代码,这些画对位图代替,然后将的blit位图到您的加速画布上。”

根据有问题的代码,以堆栈跟踪是

protected void draw(Canvas canvas) {
    if (mHidden) {
        return;
    }
    canvas.save();
    Path path = new Path();
    if (!hasFocus()) {
        mOutlinePaint.setColor(0xFF000000);
        canvas.drawRect(mDrawRect, mOutlinePaint);
    } else {
        Rect viewDrawingRect = new Rect();
        mContext.getDrawingRect(viewDrawingRect);
        if (mCircle) {
            float width  = mDrawRect.width();
            float height = mDrawRect.height();
            path.addCircle(mDrawRect.left + (width  / 2),
                           mDrawRect.top + (height / 2),
                           width / 2,
                           Path.Direction.CW);
            mOutlinePaint.setColor(0xFFEF04D6);
        } else {
            path.addRect(new RectF(mDrawRect), Path.Direction.CW);
            mOutlinePaint.setColor(0xFFFF8A00);
        }
        canvas.clipPath(path, Region.Op.DIFFERENCE);
        canvas.drawRect(viewDrawingRect,
                hasFocus() ? mFocusPaint : mNoFocusPaint);

        canvas.restore();
        canvas.drawPath(path, mOutlinePaint);

        if (mMode == ModifyMode.Grow) {
            if (mCircle) {
                int width  = mResizeDrawableDiagonal.getIntrinsicWidth();
                int height = mResizeDrawableDiagonal.getIntrinsicHeight();

                int d  = (int) Math.round(Math.cos(/*45deg*/Math.PI / 4D)
                        * (mDrawRect.width() / 2D));
                int x  = mDrawRect.left
                        + (mDrawRect.width() / 2) + d - width / 2;
                int y  = mDrawRect.top
                        + (mDrawRect.height() / 2) - d - height / 2;
                mResizeDrawableDiagonal.setBounds(x, y,
                        x + mResizeDrawableDiagonal.getIntrinsicWidth(),
                        y + mResizeDrawableDiagonal.getIntrinsicHeight());
                mResizeDrawableDiagonal.draw(canvas);
            } else {
                int left    = mDrawRect.left   + 1;
                int right   = mDrawRect.right  + 1;
                int top     = mDrawRect.top    + 4;
                int bottom  = mDrawRect.bottom + 3;

                int widthWidth   =
                        mResizeDrawableWidth.getIntrinsicWidth() / 2;
                int widthHeight  =
                        mResizeDrawableWidth.getIntrinsicHeight() / 2;
                int heightHeight =
                        mResizeDrawableHeight.getIntrinsicHeight() / 2;
                int heightWidth  =
                        mResizeDrawableHeight.getIntrinsicWidth() / 2;

                int xMiddle = mDrawRect.left
                        + ((mDrawRect.right  - mDrawRect.left) / 2);
                int yMiddle = mDrawRect.top
                        + ((mDrawRect.bottom - mDrawRect.top) / 2);

                mResizeDrawableWidth.setBounds(left - widthWidth,
                                               yMiddle - widthHeight,
                                               left + widthWidth,
                                               yMiddle + widthHeight);
                mResizeDrawableWidth.draw(canvas);

                mResizeDrawableWidth.setBounds(right - widthWidth,
                                               yMiddle - widthHeight,
                                               right + widthWidth,
                                               yMiddle + widthHeight);
                mResizeDrawableWidth.draw(canvas);

                mResizeDrawableHeight.setBounds(xMiddle - heightWidth,
                                                top - heightHeight,
                                                xMiddle + heightWidth,
                                                top + heightHeight);
                mResizeDrawableHeight.draw(canvas);

                mResizeDrawableHeight.setBounds(xMiddle - heightWidth,
                                                bottom - heightHeight,
                                                xMiddle + heightWidth,
                                                bottom + heightHeight);
                mResizeDrawableHeight.draw(canvas);
            }
        }
    }
}

怎样绘制成位图,然后BitBlt到画布?

任何帮助将不胜感激!

Answer 1:

在ICS的设备,有一个开发商选项强制硬件加速,即使应用程序不要求它。 这是什么原因造成的死机。 你应该能够使用这样的事情,迫使它使用软件呈现:

if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) {
   myCusomView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}


Answer 2:

我想你可以请你以一个离屏位图和位图复制到屏幕上的画布。 例如,

protected void draw(Canvas canvas) {
    if (mHidden) {
        return;
    }

    Bitmap bitmap = createOffScreenBitmap();
    canvas.drawa(bitmap,0f, 0f, null);

}


private Bitmap drawOffScreenBitmap(){

    // Draw whatever you want to draw right here.
}

此外,您还可以使用PorterDuffxfermode支持硬件加速,而不是clippath



Answer 3:

myCustomView =视图类名或使用this

if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) {
   this.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

我得到使用该解决方案是方法。



文章来源: Android UnsupportedOperationException at Canvas.clipPath