我在我的项目中使用来自此处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);
}
}
}
}
如何绘制位图然后blit到画布?
非常感谢任何帮助!
答案 0 :(得分:17)
在ICS设备上,有一个开发人员选项可以强制硬件加速,即使应用程序没有请求它也是如此。这就是导致崩溃的原因。你应该可以使用这样的东西强迫它使用软件渲染:
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) {
myCusomView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
答案 1 :(得分:0)
我猜你可以将你的视图绘制到离屏位图并将位图复制到屏幕画布上。例如,
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
。
答案 2 :(得分:0)
myCustomView =查看班级名称或使用this
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) {
this.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
我使用that方法获得解决方案。