首页 > 解决方案 > Canvas.drawBitmap 使用 Bitmap 的最后内容进行所有调用

问题描述

我正在尝试在 Xamarin 中的自定义视图上呈现多个 PDF 页面。

    public override void Draw( AG.Canvas canvas ) {
        base.Draw( canvas );
        if( !(Parent is AW.ScrollView p) || pdfRenderer == null )
            return;
        int topPage = pdfRenderer.PageCount * p.ScrollY / Height;
        while( topPage < pdfRenderer.PageCount && topPage * screenPageHeight < p.ScrollY + p.Height ) {
            using( var page = pdfRenderer.OpenPage( topPage ) ) {
                page.Render( bitmap, null, null, PdfRenderMode.ForDisplay );
                page.Close();
            }
            AG.Rect pageRect = new AG.Rect {
                Left = 0,
                Top = topPage * screenPageHeight,
                Right = Width,
                Bottom = (topPage + 1) * screenPageHeight,
            };
            canvas.DrawBitmap( bitmap, null, pageRect, null );
            topPage++;
        }
    }

输出是从所有 pageRect 中运行的最后一个循环绘制页面。我可以想象为什么会发生这种情况,但真正的问题是如何修复此代码以绘制所有页面,而无需为每个页面创建单独的位图。

编辑。附上调试器屏幕截图。(在 canvas.DrawBitmap 断点处)

编辑。添加了java代码。预期:一个红色和一个绿色矩形。观察到:两个绿色矩形。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new TestView());
    }

    class TestView extends View {
        public TestView() {
            super(MainActivity.this);
        }

        Bitmap bmp = Bitmap.createBitmap(600, 200, Bitmap.Config.ARGB_8888);
        Paint paint = new Paint();

        void FillBitmap(int color) {
            Canvas canvas = new Canvas(bmp);
            canvas.drawColor(color);
        }

        protected void onDraw (Canvas canvas) {
            FillBitmap(Color.RED);
            canvas.drawBitmap(bmp, 60, 120, paint);
            FillBitmap(Color.GREEN);
            canvas.drawBitmap(bmp, 60, 440, paint);
        }

        protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {
            setMeasuredDimension(720, 720);
        }
    }
}

在此处输入图像描述 在此处输入图像描述

标签: androidxamarincanvasbitmapdrawbitmap

解决方案


David 和我相信这与使用 Canvas 和从同一资源加载的 Drawable 对象有关。位图是可绘制的。Xamarin 是 API 上的一个非常薄的包装层,因此这可能与 Xamarin 无关,但更特定于 Android。请注意文档的这一部分: 注意:项目中的每个唯一资源只能保持一种状态,无论您为其实例化了多少不同的对象。例如,如果您从同一个图像资源中实例化两个 Drawable 对象并更改一个对象的属性(例如 alpha),那么它也会影响另一个对象。在处理图像资源的多个实例时,您应该执行补间动画,而不是直接转换 Drawable 对象。- https://developer.android.com/guide/topics/graphics/drawables -https://developer.android.com/reference/android/graphics/Canvas 因此,最可能的原因是您正在从同一资源(pdf)创建位图实例。我无法在您的代码片段中看到这一点来确认,但这是最可能的原因。它也可能与重复使用相同的位图实例有关,而不是与多个单独的位图实例有关,但我也无法从片段中看到这一点。与前面提到的 Canvas 上的 Drawables 问题相比,它可能不太可能是原因。检查补间动画是否会对您的场景有所帮助。

但请注意,可能有更简化的方法来呈现 PDF。Android(和 Xamarin.Andriod)有用于 PdfRenderer 的 API。Android 的文档在这里:https ://developer.android.com/reference/android/graphics/pdf/PdfRenderer Xamarin.Android 我们在这里有 Xamarin 包装器的 API 文档:https ://developer.xamarin.com/ api/type/Android.Graphics.Pdf.PdfRenderer/ 或者,您还可以将 pdf 设置为 Xamarin.Android 或 Xamarin.Forms 中 WebView 的源,方法是将 Source 属性设置为 Xamarin.Forms.WebView 或通过从 Android.Webkit.WebView 的实例调用 LoadUrl。


推荐阅读