Flutter自定義控制項第一式,炫酷「蛛網」控制項

2021-09-24 06:47:52 字數 4129 閱讀 5422

「萬物之中,希望至美」,《肖生剋的救贖》這句話一直記在心裡,不論生活多麼不易,心有希望,生活一定會越來越好。

「 hope is a good thing , maybe the best of things , and no good thing ever dies . 」

flutter 出現已經有一段時間了,搭好環境由於忙其他事就擱置了,恰好這次參與公司 flutter 專案開發,是時候拾起來了,前兩天了解了 dart 語言,今天剛好看到控制項這部分,於是簡單寫了個「蛛網」控制項。

效果圖如下:

從效果圖上可以分析得到,「蛛網」 由簡單的線條組成,那需要繪製線條。在 android 中,可以通過自定義 view ,在 ondraw 方法中呼叫 canvas.drawline;或者呼叫 canvas.drawpath 繪製線條。那麼在 flutter 又該怎樣繪製線條?

在 android 中有 view 提供繪製;同樣在 flutter 中有 custompainter 提供繪製,原始碼中是這麼介紹的:

///  * [canvas], the class that a custom painter uses to paint.

/// * [custompaint], the widget that uses [custompainter], and whose sample

/// code shows how to use the above `sky` class.

/// * [radialgradient], whose sample code section shows a different take

/// on the sample code above.

abstract

class

custompainter

extends

listenable

@override

bool shouldrepaint

(custompainter olddelegate)

}複製**

繼承 custompainter ,重寫 paint 與 shouldrepaint 方法。paint 方法類似 android 中的 ondraw 方法,但多了乙個 size 引數,來看下 size 類的定義:

const

size

(double width, double height) : super

(width, height)

;複製**

構造引數 width ,height 表示繪製區域的寬高,可以理解成畫布大小。size 需要從外部呼叫的地方傳入,而 android 需要在 onmeasure 進行測量,flutter 的方式更加靈活。

shouldrepaint 從方法名就可以知道,用於控制重繪,為了提高效率,一般可以這麼寫:

@override

bool shouldrepaint

(custompainter olddelegate)

複製**

那麼我們就可以在 paint(canvas canvas, size size) 方法中繪製我們想要的形狀。

蛛網由底部的網狀路徑以及頂部的不規則覆蓋物組成。那可以分成兩部分,第一部分繪製底部網狀;第二部分繪製頂部覆蓋物。

觀察底部網狀路徑由多個正多邊形組成(邊長遞增),那麼可以拆分先繪製乙個正多邊形。

在 flutter 的 canvas 中提供了 drawpath(path path, paint paint) 方法繪製路徑,與 android 的使用方式一樣。

通過 size 可以拿到整個控制項區域的大小,那麼正多邊形的中點座標就很容易獲取到:

mcenterx = size.width / 2;

mcentery = size.height / 2;

複製**

為了方便,這裡可以把正多邊形看成圓內切,想到圓,就應該想到圓的半徑,同樣根據控制項大小獲取半徑:

radius = mcenterx / medgesize

複製**

最後需要獲取到圓內切正多邊形的頂點,簡單的數學公式:

double x = mcenterx + radius * cos(degtorad(angle * j));

double y = mcentery + radius * sin(degtorad(angle * j));

複製**

比較尷尬的是,flutter 中並沒有 math.toradians 函式,那只能自己擼乙個,就像這樣:

num degtorad

(num deg)

=> deg * (pi / 180.0);

num radtodeg

(num rad)

=> rad * (180.0 / pi);

複製**

繪製多個正多邊形,只需要改變 radius 的值:

//  medgesize 表示多邊形的邊數 i + 1 

radius = mcenterx / medgesize * (i + 1);

複製**

到此,底部的網狀路徑繪製差不多,頂部的覆蓋物類似,隨機改變 radius 的長度:

double value = (random.nextint(10) + 1) / 10;

double x = mcenterx + radiusmaxlimit * cos(degtorad(angle * i)) * value;

double y = mcentery + radiusmaxlimit * sin(degtorad(angle * i)) * value;

複製**

接著看看**如何寫。

起乙個接地氣的名字,能夠讓你眼前一亮,就叫spiderview

spiderview類

先來看看 spiderview 類的成員變數:

paint mpaint;

// 覆蓋物畫筆

paint mcoverpaint;

// 文字畫筆

paint mtextpaint;

path mpath;

// 繪製邊數預設為6

int medgesize = 6;

final

double circle_angle = 360;

// 整個繪製區域的中點座標

double mcenterx = 0;

double mcentery = 0;

複製**

畫筆,路勁初始化:

spiderview(this.medgesize) 

複製**

paint 方法:

@override

void

paint

(canvas canvas, size size)

複製**

/**

* 繪製邊線

*/void

drawspideredge

(canvas canvas)

else

}mpath.close();

canvas.drawpath(mpath, mpaint);

}drawspideraxis(canvas, radiusmaxlimit, angle);

} /**

* 繪製軸線

*/void

drawspideraxis

(canvas canvas, double radius, double angle)

}複製**

繪製頂部覆蓋物:

/**

* 繪製覆蓋區域

*/void

drawcover

(canvas canvas)

else

}mpath.close();

canvas.drawpath(mpath, mcoverpaint);

}複製**

Flutter 自定義單選控制項

在flutter 應用開發中,經常會遇到各種單選效果,雖然官方提供了radio元件,但是並不能滿足我們實際的開發需求,所以往往還需要自定義控制項才能滿足平時的開發需求。下面就平時開發中用到的單選進行介紹 對於分段元件大家肯定不會陌生,主要是實現多個分段,實現單選功能,效果如下圖。話不多說,直接上 c...

自定義控制項《一》

view的工作流主要是指measure layout draw,即測量 布局和繪製。案例 做乙個圓形的控制項 public class circleview extends view public circleview context context,attributeset attrs publi...

自定義控制項 一

定義控制項 編寫自己的伺服器控制項從而來補充常用控制項的不足或封裝自己在開發中常用 功能 外觀的控制項 建立自定義控制項 方法一 新建asp.net資料夾 新建類 cs 一般將類設定為public 並指定命名空間 該類 繼承 system.web.ui.webcontrols 或其子類 textbo...