Fiiremonkey 的跨平臺能力,你們有目共睹(一碼同介面跨四平臺),惟獨移動平臺在幾何繪圖方面,質量始終不盡人意,我也曾試着去修正(如:修正曲線平滑問題),也曾找過第三方案(如:AggPas),但都不完美,我一直在想,移動平臺有這麼強的繪圖能力及質量(Android & iOS),若是能直接拿來用,不是很好?爲何 Firemonkey 要本身重寫?html
目前網上許多針對此問題的改善方案,但多以控件形式,且需依各平臺的繪圖函數來繪圖,或僅提供固定的幾何圖形控件,若是能延用現有的 TCanvas.Draw????? 繪圖代碼,只要加入幾行代碼(或編譯開關),就能達到原生繪圖的效果,豈不是很理想,因而開是構想這種方案的可行性,最後證明是可行的。android
要先說明的是,這裏提供的只是一種改善方案,而不是修正,最終仍是但願能受到 EMB 官方的關注,由官方來改進這個問題。ios
FMX 的繪圖方法:git
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas); var Rect, DesRect: TRectF; begin Rect := PaintBox1.LocalRect; Canvas.Stroke.Thickness := 10; Canvas.Stroke.Kind := TBrushKind.Solid; Canvas.Stroke.Dash := TStrokeDash.DashDotDot; DesRect := Rect; InflateRect(DesRect, -(Canvas.Stroke.Thickness / 2), -(Canvas.Stroke.Thickness / 2)); // 線在區內 Canvas.FillRect(DesRect, 30, 30, AllCorners, 1); Canvas.DrawRect(DesRect, 30, 30, AllCorners, 1); end;
說明 | Android | iOS | Windows | macOS |
上面的代碼,使用 FMX 繪圖方法github (移動平臺是有問題的)app |
![]() |
![]() |
![]() |
![]() |
下面的代碼,使用原生繪圖方法函數 (四個平臺所有相同了)spa |
![]() |
![]() |
|
![]() |
下面改爲原生繪圖方案,只要在原有絵圖代碼前後加入二行代碼(原繪圖代碼不用更動):.net
{$i NativeDraw.inc} uses FMX.Graphics.Native; procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas); var Rect, DesRect: TRectF; begin Rect := PaintBox1.LocalRect; Canvas.Stroke.Thickness := 10; Canvas.Stroke.Kind := TBrushKind.Solid; Canvas.Stroke.Dash := TStrokeDash.DashDotDot; {$IFDEF UseNativeDraw}Canvas.NativeDraw(Rect, procedure begin {$ENDIF} // 原生繪圖 by Aone DesRect := Rect; InflateRect(DesRect, -(Canvas.Stroke.Thickness / 2), -(Canvas.Stroke.Thickness / 2)); // 線在區內 Canvas.FillRect(DesRect, 30, 30, AllCorners, 1); Canvas.DrawRect(DesRect, 30, 30, AllCorners, 1); {$IFDEF UseNativeDraw}end);{$ENDIF} // 原生繪圖 by Aone end;
Android, iOS:使用原生繪圖 TCanvasHelper 方法3d
咱們沒法觸及 FMX 的最核心,只能利用這種 Bitmap 方式來變通,要知道這種方式可能帶來的問題(記憶體及效能),纔不致錯用
{$i NativeDraw.inc} uses FMX.Graphics.Native; {$IFDEF UseNativeDraw}Canvas.NativeDraw(Rect, procedure begin {$ENDIF} // 原生繪圖 by Aone // 繪圖代碼 {$IFDEF UseNativeDraw}end);{$ENDIF} // 原生繪圖 by Aone
DrawLine | 畫線 |
FillRect | 圓距區 |
DrawRect | 圓距框線 |
FillPath | 路徑區 |
DrawPath | 路徑框線 |
FillEllipse | 橢圓區 |
DrawEllipse | 橢圓框線 |
FillArc | 孤線區 |
DrawArc | 孤框線 |
FillPolygon | 多邊形區 |
DrawPolygon | 多邊形框線 |
IntersectClipRect | 相交剪裁區 |
ExcludeClipRect | 其它剪裁區 |
原生 | FMX |
![]() |
![]() |
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas); var Rect, DesRect: TRectF; begin Rect := PaintBox1.LocalRect; Canvas.Stroke.Thickness := 10; Canvas.Stroke.Kind := TBrushKind.Gradient; Canvas.Stroke.Dash := TStrokeDash.DashDotDot; Canvas.Stroke.Gradient.Color := TAlphaColorRec.Blue; Canvas.Stroke.Gradient.Color1 := TAlphaColorRec.Gold; {$IFDEF UseNativeDraw}Canvas.NativeDraw(Rect, procedure begin {$ENDIF} // 原生繪圖 by Aone DesRect := Rect; InflateRect(DesRect, -(Canvas.Stroke.Thickness / 2), -(Canvas.Stroke.Thickness / 2)); // 線在區內 Canvas.FillRect(DesRect, 30, 30, AllCorners, 1); Canvas.DrawRect(DesRect, 30, 30, AllCorners, 1); {$IFDEF UseNativeDraw}end);{$ENDIF} // 原生繪圖 by Aone end;
文件下載:
2017.06.22 新增 TestArc Demo(已更新到 GitHub):