java - 如何在大于屏幕尺寸的 Canvas 上绘图?

标签 java android bitmap android-bitmap bitmapimage

我正在创建一个允许用户在表面上绘图的 Android 应用程序。不幸的是,我的应用程序中 Canvas 的最大图像尺寸在我的手机上为 1000 x 1500 像素,并且根据设备尺寸进行缩放,但不会更大。

我的目标是允许用户在应用程序中绘图,但绘图包含在各种较大的 Canvas 中,例如 4032 x 3264 像素的 Canvas 。如何覆盖我想要在其上绘制位图的设备的最大 Canvas 尺寸?绘制过程是否应该发生在服务器上,渲染的图像是否应该实时显示在客户端上?或者我可以以某种方式使 Canvas 大于屏幕,初始化图像的完全缩小 View 并允许用户在其周围滚动、放大/缩小等,同时还能够绘图?

我已将公共(public)要点发布到我在此处创建的类中以供引用:

https://gist.github.com/santafebound/57f45c636e69c53b1df79302b8946099

仅更改生成图像的大小会导致以下错误:

09-17 11:29:03.718 4490-4490/com.elgami.customizer E/AndroidRuntime: FATAL EXCEPTION: main

Process: com.elgami.customizer, PID: 4490
     java.lang.OutOfMemoryError: Failed to allocate a 52641804 byte allocation with 16777216 free bytes and 44MB until OOM
         at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
         at android.graphics.Bitmap.nativeCreate(Native Method)
         at android.graphics.Bitmap.createBitmap(Bitmap.java:831)
         at android.graphics.Bitmap.createBitmap(Bitmap.java:808)
         at android.graphics.Bitmap.createBitmap(Bitmap.java:775)
         at com.elgami.customizer.MainActivity.SetupTemplate(MainActivity.java:451)
         at com.elgami.customizer.MainActivity.SetupTemplate(MainActivity.java:434)
         at com.elgami.customizer.MainActivity$1.onPageScrollStateChanged(MainActivity.java:289)
         at android.support.v4.view.ViewPager.dispatchOnScrollStateChanged(ViewPager.java:1944)
         at android.support.v4.view.ViewPager.setScrollState(ViewPager.java:497)
         at android.support.v4.view.ViewPager.onInterceptTouchEvent(ViewPager.java:2119)
         at com.elgami.views.ExtendedViewPager.onInterceptTouchEvent(ExtendedViewPager.java:44)
         at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2108)
         at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
         at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197)
         at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
         at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197)
         at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
         at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197)
         at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
         at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197)
         at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
         at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197)
         at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
         at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197)
         at com.android.internal.policy.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2403)
         at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1737)
         at android.app.Activity.dispatchTouchEvent(Activity.java:2771)
         at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:63)
         at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:63)
         at com.android.internal.policy.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2364)
         at android.view.View.dispatchPointerEvent(View.java:9520)
         at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4230)
         at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4096)
         at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
         at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695)
         at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661)
         at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3787)
         at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669)
         at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3844)
         at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
         at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695)
         at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661)
         at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669)
         at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
         at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5922)
         at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5896)
         at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5857)
         at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6025)
         at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
         at android.os.MessageQueue.nativePollOnce(Native Method)
        at andr

最佳答案

尝试对 Canvas 进行子类化并使用固定的 MeasureSpec 来锁定您想要的尺寸:

private static final int fixedWidthMeasureSpec
        = View.MeasureSpec.makeMeasureSpec(4032, View.MeasureSpec.EXACTLY);

private static final int fixedHeightMeasureSpec
        = View.MeasureSpec.makeMeasureSpec(3264, View.MeasureSpec.EXACTLY);

// ...

@Override
protected void onMeasure(int widthMS, int heightMS) {
    super.onMeasure(fixedWidthMeasureSpec, fixedHeightMeasureSpec);
}

关于java - 如何在大于屏幕尺寸的 Canvas 上绘图?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39545137/

相关文章:

java - 服务器端的 GWT I18N

android - avd 管理器不显示 - 我没有使用 eclipse

android - 如何在Android服务上实现准确的(精确到秒)计时

android - java.io.IOException : Permission denied cannot create file 异常

android - 使用位图和 Volley 查看寻呼机内存泄漏

java - 如何在我的自定义控件中实现类似 JLabel 的大小管理?

java - 设置 null 而不出现 NullPointerException

java - 当我将元素从一个包移动到另一个包时出现 ObjectDeletedException

java - [Cocos2d]如何从GlSurfaceView创建位图

android - URI 和位图图像之间的区别