I am trying to render multiple PDF pages on a custom View in Xamarin.
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++;
}
}
The output is drawing the page from the last loop run in all pageRect's. I can imagine why it might happen, but the real question is how I can fix this code to draw all pages without creating a separate bitmap for each page.
EDIT. Debugger screenshots attached. (At canvas.DrawBitmap breakpoint)
EDIT. Added java code. Expected: one red and one green rect. Observed: two green rects.
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);
}
}
}


David and I believe this is related to using the Canvas with Drawable objects loaded from the same resource. Bitmap is a drawable. Xamarin is a very thin layer of wrappers over the APIs, so this isn’t likely related to Xamarin, but more specific to Android. Notice this section of the documentation: Note: Each unique resource in your project can maintain only one state, no matter how many different objects you instantiate for it. For example, if you instantiate two Drawable objects from the same image resource and change a property (such as the alpha) for one object, then it also affects the other. When dealing with multiple instances of an image resource, instead of directly transforming the Drawable object you should perform a tween animation. - https://developer.android.com/guide/topics/graphics/drawables - https://developer.android.com/reference/android/graphics/Canvas So, the most likely cause is that you’re creating bitmap instances from the same resource (the pdf). I can’t see this in your code snippet to confirm, but it’s the most likely cause. It may also be related to using the same instance of bitmap repeatedly, rather than multiple separate bitmap instances, but I can’t see this from the snippet either. It may be less likely to be the cause than the previously mentioned issues with Drawables on the Canvas. Check to see if tween animation will help you in your scenario.
Note though, there may be more simplified methods to present the PDF. Android (and Xamarin.Andriod) have API for PdfRenderer. Android’s documentation for this is here: https://developer.android.com/reference/android/graphics/pdf/PdfRenderer Xamarin.Android and we have API docs for the Xamarin wrapper here: https://developer.xamarin.com/api/type/Android.Graphics.Pdf.PdfRenderer/ Alternatively, you can also set a pdf as the source for a WebView in Xamarin.Android or Xamarin.Forms, by setting the Source property to the pdf in Xamarin.Forms.WebView or by calling LoadUrl from an instance of Android.Webkit.WebView.