Component sizes in Delphi Android

2019-05-27 20:54发布

问题:

I am creating an Android app in Delphi XE5 using Firemonkey, and for one of my forms I need a TImage that will fill the entire form where I can draw on it's Bitmap.

What I did was this:

  1. I added a TImage component to my form and set it's Align := alClient. In the designer it fills the entire form.

  2. In my FormCreate procedure I initialized the Bitmap of the TImage by setting it's size to the size of the TImage

    procedure TDrawForm.FormCreate(Sender: TObject);
    begin
        Image1.Bitmap.SetSize(Trunc(Image1.Width), Trunc(Image1.Height));
        DrawFromList(Image1);
    end;
    
  3. Then I draw on the TImage's Bitmap.Canvas

    procedure TDrawForm.DrawFromList(image: TImage);
    var draw: TDraw;
    begin
       image.Bitmap.Canvas.BeginScene;
       image.Bitmap.Canvas.Clear(claBlue);
       image.Bitmap.Canvas.Stroke.Color := claBlack;
       image.Bitmap.Canvas.Fill.Color := claYellow;
       for draw in DrawList do
       begin
          image.Bitmap.Canvas.FillPath(draw.fpath, 1);
          image.Bitmap.Canvas.DrawPath(draw.fpath, 1);
       end;
       image.Bitmap.Canvas.EndScene;
    end;
    

This code draws just fine on my Nexus 7 tablet, but it does not fill the entire screen:

In the second picture I used

Image1.Bitmap.SetSize(Trunc(Image1.Width * 1.34), Trunc(Image1.Height * 1.34));

where 1.34 was found by trial and error, to make it fill the entire screen.

I then tried to print out the size of the image and the screen. For my Nexus 7 (which is 1280 x 800 pixels) the TImage component which fills the entire screen, has a width of 601 and a height of 880. Thus, when I set the size of the Bitmap to be the size of my TImage, the Bitmap is also 601 x 880, which explains why I needed to scale the Bitmap to make it fill the entire screen. The screen size is reported as 600 x 905 (using Screen.Size).

My question is why is the size of the TImage component only 601 x 880 (and the screen only 600 x 905) when the actual resolution of my device is 800 x 1280? If these sizes are not pixels, then what are they? And more importantly, how do I convert from these numbers to actual screen pixels (bear in mind, 1.34 only works for Nexus 7 - on my HTC Sensation it needed to be even bigger)?

One of my co-workers suggested that it might have to do with the DPI of the screen, but I couldn't find any method that will give me the DPI of the current device.

I have also tried updating the size of the bitmap in the FormResize procedure, but that doesn't make a difference.

回答1:

I found a solution to my problem. Apparently there are, on the component, two properties that will return a scale. Luckily, this scale multiplied with the width and height of the component will return the width and height in pixels.

Image1.Scene.GetSceneScale
Image1.Canvas.Scale

In my case, I had to initialize my Bitmap like this:

Image1.Bitmap.SetSize(Trunc(Image1.Width * Image1.Canvas.Scale), 
                      Trunc(Image1.Height * Image1.Canvas.Scale));

This makes the Bitmap of my Image1 fill the entire screen since the image is set to Align := alClient.

I still don't know what the original size returned by Image1.Width and Image1.Height (or Screen.Size for that matter) is measured in, but it is not always pixels. It would have saved me about two weeks of headache if this was documented somewhere.