隨着移動互聯網的發展,越來越多的APP需要顯示豐富的場景,這就需要我們有一種以高效、靈活為特點的界面框架,Scenic就是這樣的一種框架。Scenic它是一種以OpenGL為基礎的圖形庫,用於構建高效、靈活的用戶接口。
一、Scenic的特點
1. 矢量渲染:Scenic使用OpenGL繪製2D圖形,支持不同的變形和旋轉,這使得圖形很容易適應不同大小的屏幕。同時,Scenic支持基於路徑的渲染技術,使開發者可以更輕鬆的繪製各種複雜的圖形。
2. 豐富的圖形元素:Scenic提供了各種常見的UI元素,如文本、圖片、按鈕、列表和滾動視圖等,這些元素可供組合成豐富的用戶界面。
3. 異步布局:Scenic支持異步布局,這意味着當界面使用布局時,布局的計算是在單獨的線程中進行的,可以大大減少界面卡頓的情況。
4. 支持GPU加速:Scenic使用OpenGL,可以充分利用GPU的性能,提高性能,同時也可以減少CPU的工作量。
5. 高度可定製:Scenic允許開發者自定義UI元素以及界面樣式,這使得開發者可以輕鬆構建適應各種需求的用戶界面。
二、Scenic的基本用法
安裝Scenic: Scenic可以使用Flutter的package manager進行安裝,只需要輸入以下命令即可:
flutter packages add scenic
創建Scenic Widget: Scenic的UI元素被封裝為Widget,開發者可以輕鬆創建一個Scenic Widget:
class ScenicWidget extends StatelessWidget {
const ScenicWidget();
@override
Widget build(BuildContext context) {
return Scenic.custom(
sizeCallback: (size) {},
onPaint: (canvas) {},
);
}
}
在上面的代碼中,我們創建了一個簡單的Scenic Widget,並重寫了build方法,返回一個Scenic.custom Widget。通過這個Widget,我們可以自定義畫布大小以及視圖繪製方法。
這個Widget現在什麼也不顯示,我們需要自定義視圖的繪製方法,來讓其顯示出來:
return Scenic.custom(
sizeCallback: (size) {},
onPaint: (canvas) {
canvas.drawRect(
rect: Offset.zero & Size(100, 100),
style: Paint.Style.fill,
color: ScenicColor.fromHex('#FFFFFF'));
},
);
這裡的canvas就是用於繪製的畫布,我們在畫布上繪製了一個白色的矩形,這個矩形的大小是100×100。
三、Scenic實現ListView
我們可以使用Scenic輕鬆地構建一個ListView,下面是一個簡單的例子:
class CustomListViewItemWidget extends ScenicWidget {
const CustomListViewItemWidget(
this.index, {
this.color = 'FF0000',
});
final int index;
final String color;
@override
void onPaint(Canvas canvas) {
canvas.drawRect(
rect: Offset.zero & size,
style: Paint.Style.fill,
color: ScenicColor.fromHex('#$color'),
);
canvas.drawText(
text: 'Item $index',
position: Offset(16, size.height / 2 - 16),
textStyle: TextStyle(color: ScenicColor.fromHex('#FFFFFF')),
);
}
@override
get width => 320;
@override
get height => 64;
}
class CustomListViewWidget extends ScenicWidget {
const CustomListViewWidget();
@override
void sizeCallback(Size size) {
super.sizeCallback(size);
final width = size.width;
final height = size.height / CustomListViewItemWidget.height;
sizeCallback(Size(width, height));
}
@override
void onPaint(Canvas canvas) {
for (var i = 0; i < size.height / CustomListViewItemWidget.height; i++) {
canvas.drawRRect(
rect: Offset(0, i * CustomListViewItemWidget.height) &
Size(size.width, CustomListViewItemWidget.height),
radius: 4,
style: Paint.Style.fill,
color: ScenicColor.fromHex(
i.isEven ? '#F5F5F5' : '#FFFFFF',
),
);
canvas.save();
canvas.translate(0, i * CustomListViewItemWidget.height);
canvas.clipRRect(
rect: Offset.zero &
Size(size.width, CustomListViewItemWidget.height),
radius: 4);
CustomListViewItemWidget(i, color: i.isEven ? '0087FF' : 'FF0000')
..paint(canvas);
canvas.restore();
}
}
}
在上面的代碼中,我們創建了兩個Widget,CustomListViewItemWidget和CustomListViewWidget,分別用於顯示ListView中每一個Item和整個ListView。CustomListViewItemWidget表示ListView的Item,我們在這裡繪製了一個矩形和文本;CustomListViewWidget表示整個ListView,我們在這裡使用onPaint方法繪製了多個CustomListViewItemWidget,然後每一個CustomListViewItemWidget都需要調用paint方法繪製到畫布上。
四、Scenic實現表單
Scenic同樣也非常適合用於實現表單,為開發者提供了很多便利和高度的靈活性。下面是一個簡單的例子:
class ScenicFormWidget extends ScenicWidget {
const ScenicFormWidget();
@override
double get width => 240;
@override
double get height => 200;
final TextEditingController _nameController = TextEditingController();
void submit() {
print(_nameController.text);
}
@override
void onPaint(Canvas canvas) {
final inputWidth = width - 32;
final inputOffset = Offset(16, 32);
canvas.drawRect(
rect: Offset.zero & size,
style: Paint.Style.fill,
color: ScenicColor.fromHex('#FFFFFF'),
);
canvas.drawText(
text: 'Scenic Form',
position: Offset(width / 2 - 50, 16),
textStyle: TextStyle(
color: ScenicColor.fromHex('#000000'), fontSize: 18),
);
canvas.drawText(
text: 'Name',
position: inputOffset - Offset(0, 16),
textStyle: TextStyle(
color: ScenicColor.fromHex('#000000'),
fontSize: 14,
),
);
canvas.drawRect(
rect: Rect.fromLTWH(inputOffset.dx, inputOffset.dy, inputWidth, 32),
style: Paint.Style.stroke,
color: ScenicColor.fromHex('#000000'),
strokeWidth: 1,
);
canvas.drawText(
text: _nameController.text,
position: inputOffset,
textStyle: TextStyle(
color: ScenicColor.fromHex('#000000'),
fontSize: 14,
),
);
}
}
在上面的代碼中,我們創建了一個ScenicFormWidget,這個Widget裡面繪製了一個表單,包含一個輸入框和一個提交按鈕。在onPaint方法中,我們使用ScenicDraw來繪製各種UI元素,如文本、矩形、線條等。同時,我們為表單綁定了一個該Controller,使用submit方法來處理其提交事件。
五、Scenic實現動畫
Scenic使用Flutter的Animation框架來支持動畫,提供了ScenicAnimationBuilder Widget,可方便地創建動畫並將其連接到UI元素:
class ScenicAnimationDemo extends StatefulWidget {
const ScenicAnimationDemo();
@override
State createState() => _ScenicAnimationDemoState();
}
class _ScenicAnimationDemoState extends State
with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 3),
vsync: this,
);
_animation = Tween(begin: 0.0, end: 1.0).animate(_controller);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ScenicAnimationBuilder(
animation: _animation,
builder: (context, child, value) {
return Scenic.custom(
onPaint: (canvas) {
canvas.drawRect(
rect: Offset.zero & Size(100, 100),
style: Paint.Style.fill,
color: ScenicColor.fromHex('#000000').withOpacity(value),
);
},
);
},
);
}
}
在上面的代碼中,我們使用ScenicAnimationBuilder Widget來創建動畫,並使用ScenicDraw中的canvas.drawRect方法繪製一個黑色矩形。在動畫執行過程中,我們修改矩形的透明度,將其從完全透明變為完全不透明。
總結
Scenic是一個輕量級的UI框架,其特點在於支持矢量渲染、異步布局、GPU加速、高度可定製等方面。Scenic可以輕易地創建各種豐富的用戶界面,例如ListView、表單和動畫等。同時,Scenic也與Flutter配合得非常好,為Flutter開發者提供了一個高度定製的解決方案。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/257691.html