Recent

Author Topic: LAMW Bug: UpdateLayout After Rotate  (Read 630 times)

Handoko

  • Hero Member
  • *****
  • Posts: 2992
  • My goal: build my own game engine using Lazarus
LAMW Bug: UpdateLayout After Rotate
« on: February 12, 2019, 07:31:26 pm »
When learning how to use jView, I found something not working correctly. I could be wrong but I believe it is a bug.

How to reproduce the bug?

1. Run the code below (you can download and use the apk on the next post)
2. Press the button several times, to switch between different layout parameters
3. A small rectangle and triangle will be moving inside the jView1
4. The big green rectangle represents the border of jView1
5. Rotate your mobile phone

6. Bug:
If the jView1.LayoutParam = lpMatchParent and the phone orientation is Landscape then
the value of jView1.Width and jView1.Height are incorrect (swapped).

Code: Pascal  [Select]
  1. {Hint: save all files to location: /home/handoko/Desktop/JCanvasPolygon/LamwGUIProject1/jni }
  2. unit unit1;
  3.  
  4. {$mode delphi}
  5.  
  6. interface
  7.  
  8. uses
  9.   Classes, SysUtils, AndroidWidget, Laz_And_Controls;
  10.  
  11. type
  12.  
  13.   TPolygon = array of TPoint;
  14.  
  15.   { TAndroidModule1 }
  16.  
  17.   TAndroidModule1 = class(jForm)
  18.     jButton1: jButton;
  19.     jCanvas1: jCanvas;
  20.     jTextView1: jTextView;
  21.     jTimer1: jTimer;
  22.     jView1: jView;
  23.     procedure AndroidModule1Destroy(Sender: TObject);
  24.     procedure AndroidModule1JNIPrompt(Sender: TObject);
  25.     procedure AndroidModule1Rotate(Sender: TObject; rotate: TScreenStyle);
  26.     procedure jButton1Click(Sender: TObject);
  27.     procedure jTimer1Timer(Sender: TObject);
  28.     procedure jView1Draw(Sender: TObject);
  29.   private
  30.     FBorderS: Integer;
  31.     FSquareX: Integer;
  32.     FSquareY: Integer;
  33.     FSquareS: Integer;
  34.     FSquareVeloX: Integer;
  35.     FSquareVeloY: Integer;
  36.     FTriangleX: Integer;
  37.     FTriangleY: Integer;
  38.     FTriangleVeloX: Integer;
  39.     FTriangleVeloY: Integer;
  40.     procedure DrawPoly(BorderColor: TARGBColorBridge; BorderWidth: Integer;
  41.       Points: TPolygon);
  42.     procedure ShowInfo;
  43.   end;
  44.  
  45. var
  46.   AndroidModule1: TAndroidModule1;
  47.  
  48. implementation
  49.  
  50. {$R *.lfm}
  51.  
  52. { TAndroidModule1 }
  53.  
  54. procedure TAndroidModule1.jView1Draw(Sender: TObject);
  55. var
  56.   Polygon: TPolygon;
  57. begin
  58.  
  59.   // Draw Border
  60.   Polygon := TPolygon.Create(
  61.     Point(0, 0),
  62.     Point(jView1.Width, 0),
  63.     Point(jView1.Width, jView1.Height),
  64.     Point(0, jView1.Height));
  65.   DrawPoly(colbrGreen, FBorderS, Polygon);
  66.  
  67.   // Draw Square
  68.   Polygon := TPolygon.Create(
  69.     Point(FSquareX-FSquareS, FSquareY-FSquareS),
  70.     Point(FSquareX+FSquareS, FSquareY-FSquareS),
  71.     Point(FSquareX+FSquareS, FSquareY+FSquareS),
  72.     Point(FSquareX-FSquareS, FSquareY+FSquareS));
  73.   DrawPoly(colbrCyan, 3, Polygon);
  74.  
  75.   // Draw Triangle
  76.   Polygon := TPolygon.Create(
  77.     Point(FTriangleX,     FTriangleY-80),
  78.     Point(FTriangleX+100, FTriangleY+80),
  79.     Point(FTriangleX-100, FTriangleY+80));
  80.   DrawPoly(colbrRed, 3, Polygon);
  81.  
  82. end;
  83.  
  84. procedure TAndroidModule1.jButton1Click(Sender: TObject);
  85. const
  86.   Layout: Integer = 0;
  87. begin
  88.   Inc(Layout);
  89.   if Layout > 3 then Layout := 1;
  90.   case Layout of
  91.     1: begin
  92.       jView1.LayoutParamHeight := lpMatchParent;
  93.       jView1.LayoutParamWidth  := lpMatchParent;
  94.       jButton1.Text            := 'lpMatchParent';
  95.     end;
  96.     2: begin
  97.       jView1.LayoutParamHeight := lpFourFifthOfParent;
  98.       jView1.LayoutParamWidth  := lpFourFifthOfParent;
  99.       jButton1.Text            := 'lpFourFifthOfParent';
  100.     end;
  101.     3: begin
  102.       jView1.LayoutParamHeight := lp99PercentOfParent;
  103.       jView1.LayoutParamWidth  := lp99PercentOfParent;
  104.       jButton1.Text            := 'lp99PercentOfParent';
  105.     end;
  106.   end;
  107.   jView1.UpdateLayout;
  108.   ShowInfo;
  109. end;
  110.  
  111. procedure TAndroidModule1.jTimer1Timer(Sender: TObject);
  112. begin
  113.  
  114.   // Animate Border
  115.   Inc(FBorderS);
  116.   if FBorderS > 50 then FBorderS := 1;
  117.  
  118.   // Animate Square
  119.   Inc(FSquareS);
  120.   if FSquareS > 200 then            FSquareS := 50;
  121.   if FSquareX <= 0  then            FSquareVeloX := abs(FSquareVeloX);
  122.   if FSquareX >= jView1.Width then  FSquareVeloX := -(abs(FSquareVeloX));
  123.   if FSquareY <= 0  then            FSquareVeloY := abs(FSquareVeloY);
  124.   if FSquareY >= jView1.Height then FSquareVeloY := -(abs(FSquareVeloY));
  125.   Inc(FSquareX, FSquareVeloX);
  126.   Inc(FSquareY, FSquareVeloY);
  127.  
  128.   // Animate Triangle
  129.   if FTriangleX <= 0  then            FTriangleVeloX := Random(8)  +1;
  130.   if FTriangleX >= jView1.Width  then FTriangleVeloX := -Random(8) -1;
  131.   if FTriangleY <= 0  then            FTriangleVeloY := Random(8)  +1;
  132.   if FTriangleY >= jView1.Height then FTriangleVeloY := -Random(8) -1;
  133.   Inc(FTriangleX, FTriangleVeloX);
  134.   Inc(FTriangleY, FTriangleVeloY);
  135.  
  136.   jView1.Refresh;
  137.  
  138. end;
  139.  
  140. procedure TAndroidModule1.AndroidModule1Destroy(Sender: TObject);
  141. begin
  142.   jTimer1.Enabled := False;
  143. end;
  144.  
  145. procedure TAndroidModule1.AndroidModule1JNIPrompt(Sender: TObject);
  146. begin
  147.  
  148.   // Initial Border
  149.   FBorderS := 1;
  150.  
  151.   // Initialize Square
  152.   FSquareX     := (jView1.Width div 2) -100;
  153.   FSquareY     := jView1.Height div 2;
  154.   FSquareS     := 50;
  155.   FSquareVeloX := Random(8) +1;
  156.   FSquareVeloY := Random(8) +1;
  157.  
  158.   // Initialize Triangle
  159.   FTriangleX     := (jView1.Width div 2) +100;
  160.   FTriangleY     := jView1.Height div 2;
  161.   FTriangleVeloX := Random(8) +1;
  162.   FTriangleVeloY := Random(8) +1;
  163.  
  164.   jTimer1.Enabled := True;
  165.   ShowInfo;
  166.  
  167. end;
  168.  
  169. procedure TAndroidModule1.AndroidModule1Rotate(Sender: TObject;
  170.   rotate: TScreenStyle);
  171. begin
  172.   jView1.UpdateLayout;
  173. end;
  174.  
  175. procedure TAndroidModule1.DrawPoly(BorderColor: TARGBColorBridge;
  176.   BorderWidth: Integer; Points: TPolygon);
  177. var
  178.   i: Integer;
  179. begin
  180.   jView1.Canvas.PaintColor       := BorderColor;
  181.   jView1.Canvas.PaintStrokeWidth := BorderWidth;
  182.   for i := Low(Points) to High(Points)-1 do
  183.     jCanvas1.drawLine(Points[i].x, Points[i].y, Points[i+1].x, Points[i+1].y);
  184.   i := High(Points);
  185.   jView1.Canvas.drawLine(Points[i].X, Points[i].Y, Points[0].X, Points[0].Y);
  186. end;
  187.  
  188. procedure TAndroidModule1.ShowInfo;
  189. begin
  190.   jTextView1.Text := jView1.Width.ToString + ' x ' + jView1.Height.ToString;
  191. end;
  192.  
  193. end.

Handoko

  • Hero Member
  • *****
  • Posts: 2992
  • My goal: build my own game engine using Lazarus
Re: LAMW Bug: UpdateLayout After Rotate
« Reply #1 on: February 12, 2019, 07:34:52 pm »
Below is the apk file.

Note:
Tested on Redmi 4X Android 7.1.2 LAMW 0.7 Lazarus 1.8.4.
I first notice this issue because the moving objects move to the outside the visible screen area. To make it clearly, I have added the green border. So you can ignore the moving objects.
« Last Edit: February 12, 2019, 07:39:37 pm by Handoko »

loaded

  • Full Member
  • ***
  • Posts: 100
Re: LAMW Bug: UpdateLayout After Rotate
« Reply #2 on: February 12, 2019, 07:59:07 pm »
Handoko, I don't think it's a bug.
There's something we don't know. I found the solution in the following way.

Code: Pascal  [Select]
  1. {Hint: save all files to location: C:\Users\loaded\Desktop\silan\AppLAMWProject2\jni }
  2. unit unit1;
  3.  
  4. {$mode delphi}
  5.  
  6. interface
  7.  
  8. uses
  9.   Classes, SysUtils, AndroidWidget, Laz_And_Controls;
  10.  
  11. type
  12.  
  13.   { TAndroidModule1 }
  14.  
  15.   TAndroidModule1 = class(jForm)
  16.     jCanvas1: jCanvas;
  17.     jView1: jView;
  18.     procedure AndroidModule1Rotate(Sender: TObject; rotate: TScreenStyle);
  19.     procedure jView1Draw(Sender: TObject);
  20.  
  21.   private
  22.     {private declarations}
  23.   public
  24.     {public declarations}
  25.   end;
  26.  
  27. var
  28.   AndroidModule1: TAndroidModule1;
  29.   J_Rotate:Boolean=false;
  30. implementation
  31.  
  32. {$R *.lfm}
  33.  
  34.  
  35. { TAndroidModule1 }
  36. procedure TAndroidModule1.jView1Draw(Sender: TObject);
  37. begin
  38.   if J_Rotate then
  39.   begin
  40.   showmessage(inttostr(jView1.Width)+'x'+inttostr(jView1.Height));
  41.   J_Rotate:=false;
  42.   end;
  43. end;
  44.  
  45.  
  46.  
  47. procedure TAndroidModule1.AndroidModule1Rotate(Sender: TObject;
  48.   rotate: TScreenStyle);
  49. begin
  50.   Self.UpdateLayout;
  51.   J_Rotate:=true;
  52.   jView1.Refresh;
  53. end;
  54.  
  55. end.
  56.  
Installing the spelling, google translate is used :)