一個iOS開放者的Flutter「歷險記」

一、 官方簡介html

Flutter是谷歌的移動UI框架,能夠快速在iOS和Android上構建高質量的原生用戶界面。ios

官方介紹:git

快速開發: 毫秒級的熱重載,修改後,您的應用界面會當即更新。使用豐富的、徹底可定製的widget在幾分鐘內構建原生界面。github

富有表現力和靈活的UI: 快速發佈聚焦於原生體驗的功能。分層的架構容許您徹底自定義,從而實現難以置信的快速渲染和富有表現力、靈活的設計web

原生性能: Flutter包含了許多核心的widget,如滾動、導航、圖標和字體等,這些均可以在iOS和Android上達到原生應用同樣的性能。編程

二、安裝環境json

①下載FlutterSDK:api

https://github.com/flutter/flutter/releasesxcode

②配置vscode編輯器:架構

https://flutterchina.club/get-started/editor/#vscode

附:vs下載地址

③vscode 命令運行flutter doctor,會提示你設置flutterSDK路徑 (若是遇到權限問題須要用Sudo chown命令,若是遇到文件夾不存在須要手動建立對應的文件夾)

④構建第一個Flutter程序:

建立程序 :VSCode -> View -> Command palette : Flutter NewProject運行程序 :Debug -> Start Debuging

注意事項 :若是遇到 Multiple commands produce 錯誤,cocoapods導入問題,嘗試修改build system:在Xcode菜單欄 -> File -> Workspace Setting,將build system修改成legacy build system,而後clean後編譯。

⑤Hello World!:

void main() => runApp(Center(child:Text("hello,world!",textDirection: TextDirection.ltr)));

Pubspec Format介紹:

https://www.dartlang.org/tools/pub/pubspec

 

三、Widget介紹

官方佈局介紹:https://flutterchina.club/tutorials/layout/

連接:

https://flutterchina.club/widgets-intro/

基礎Widget:

MaterialApp:該widget在應用程序的根部建立了一些有用的widget,其中包括一個Navigator, 它管理由字符串標識的Widget棧(即頁面路由棧)。Navigator可讓您的應用程序在頁面之間的平滑的過渡。

Scaffold:實現MaterialDesign佈局Widget, 此類提供tabbar,navigationBar和bottomSheets等。

Row、 Column: 這些具備彈性空間的佈局類Widget可以讓您在水平(Row)和垂直(Column)方向上建立靈活的佈局。其設計是基於web開發中的Flexbox佈局模型。

Stack: 取代線性佈局 (譯者語:和Android中的LinearLayout類似),Stack容許子 widget 堆疊, 你可使用 Positioned 來定位他們相對於Stack的上下左右四條邊的位置。Stacks是基於Web開發中的絕度定位(absolute positioning )佈局模型設計的。

Container: Container 可以讓您建立矩形視覺元素。container 能夠裝飾爲一個BoxDecoration, 如 background、一個邊框、或者一個陰影。 Container 也能夠具備邊距(margins)、填充(padding)和應用於其大小的約束(constraints)。另外, Container可使用矩陣在三維空間中對其進行變換。

固然還有經常使用的其餘一些Widget就不一一羅列了,exam:Padding、Image、Clip...

https://flutterchina.club/widgets/

可是有必要說一下:Cupertino系列Widget是基於iOS設計語言的Widget風格

 

四、動畫

官方詳細介紹:

https://flutterchina.club/animations/

我的總結:

Flutter 動畫不一樣於iOS動畫,一個block執行一個動畫

Flutter的動畫的核心類爲:

AnimationController:控制動畫的開始,暫停,與結束,它不關心我在執行什麼動畫

Animation:這個是一個抽象類,決定動畫的數據和變化方式等,能夠經過addListener去監聽其Value的變化,初始化的時候須要一個AnimationController;

開始一段動畫過程:

①AnimationController.forward();//開始動畫

②Animation.value 發生變化,並執行Animation.notifyListener()

③監聽函數執行 setState()

④子Widget 根據Animation的value值進行佈局

總結:就是不停的根據Animation的變化進行setState(),Flutter的動畫並不關心Widget的佈局方式等,只提供動畫的數據模型

 

五、界面跳轉

使用了 Navigator 和 Routes。一個路由是 App 中「屏幕」或「頁面」的抽象,而一個 Navigator 是管理多個路由的 widget 。你能夠粗略地把一個路由對應到一個 UIViewController。Navigator 的工做原理和 iOS 中 UINavigationController 很是類似,當你想跳轉到新頁面或者重新頁面返回時,它能夠 push() 和 pop() 路由。

兩種方式跳轉:

△構建路由表

void main() { runApp(MaterialApp( home: MyAppHome(), // becomes the route named '/'

routes: <String, WidgetBuilder> { '/a': (BuildContext context) => MyPage(title: 'page A'), '/b': (BuildContext context) => MyPage(title: 'page B'), '/c': (BuildContext context) => MyPage(title: 'page C'),

},

));

}//跳轉Navigator.of(context).pushNamed('/b');

△直接經過widget建立一個路由

Navigator.push(context, new MaterialPageRoute(

builder: (BuildContext context) => new FTShareHomePage(title: "ShareSDK Flutter Bridge"),

// fullscreenDialog: true,

));

△數據回傳

//好比push到位置選擇界面Map coordinates = await Navigator.of(context).pushNamed('/location');//用戶選擇了位置pop出來Navigator.of(context).pop({"lat":43.821757,"long":-79.226392});

 

六、Dart中的異步

①先了解代碼怎麼寫

Future<Map> loadData() async { String dataURL = "https://jsonplaceholder.typicode.com/posts";

http.Response response = await http.get(dataURL); return json.decode(response.body);

}//調用loadData().then((Map data){

});

② 原理其實不重要 (手動滑稽)

官方介紹:

Dart 是單線程執行模型,可是它支持 Isolate(一種讓 Dart 代碼運行在其餘線程的方式)、事件循環和異步編程。除非你本身建立一個 Isolate ,不然你的 Dart 代碼永遠運行在 UI 線程,並由 event loop 驅動。Flutter 的 event loop 和 iOS 中的 main loop 類似——Looper 是附加在主線程上的。

Dart 的單線程模型並不意味着你寫的代碼必定是阻塞操做,從而卡住 UI。相反,使用 Dart 語言提供的異步工具,例如 async / await ,來實現異步操做。

 

七、與原生進行交互

官方介紹連接:

https://flutterchina.club/platform-channels/

介紹

應用的Flutter部分經過平臺通道(platform channel)將消息發送到其應用程序的所在的宿主(iOS或Android)。

宿主監聽的平臺通道,並接收該消息。而後它會調用特定於該平臺的API(使用原生編程語言)

代碼示例(分享到第三方平臺):

dart代碼怎麼寫

//建立一個channel

static const channel = const MethodChannel('com.mob.flutter/sharesdk');// invokeMethod 方法執行原生方法

static Future<Map> share(int platform, Map params) async { return await channel.invokeMethod("share", [platform, params]);

}

原生層:

- (BOOL)application:(UIApplication *)application

didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

[GeneratedPluginRegistrant registerWithRegistry:self];

FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController;

FlutterMethodChannel *channel = [FlutterMethodChannel

methodChannelWithName:@"com.mob.flutter/sharesdk"

binaryMessenger:controller];

[channel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult _Nonnull result) {

dispatch_async(dispatch_get_main_queue(), ^{

if ([call.method isEqualToString:@"share"])

{ NSMutableDictionary *params = @{}.mutableCopy; NSArray *args = call.arguments;

[params SSDKSetupShareParamsByText:args.lastObject[@"text"] images:args.lastObject[@"images"] url:args.lastObject[@"url"] title:args.lastObject[@"title"] type:SSDKContentTypeAuto];

[ShareSDK share:[args.firstObject integerValue]

parameters:params

onStateChanged:^(SSDKResponseState state, NSDictionary *userData,

SSDKContentEntity *contentEntity, NSError *error) {

NSMutableDictionary *dic = @{}.mutableCopy;

dic[@"state"] = @(state);

dic[@"userData"] = userData;

dic[@"contentEntity"] = contentEntity.dictionaryValue;

dic[@"error"] = error.userInfo; if (result)

{

result(dic);

}

}];

}

});

}];

return [super application:application didFinishLaunchingWithOptions:launchOptions];

}

注意:

通道的客戶端和宿主經過通道構造函數中傳遞的通道名稱進行鏈接。單個應用中使用的全部通道名稱必須是不一樣的; 咱們建議在通道名稱前加一個特殊的「域名前綴」,例如 samples.flutter.io/battery(flutter 中文網google翻譯害死人)

setMethodCallHandler 回調不在主線程

 

八、開發Package

官方介紹連接:

https://flutterchina.club/developing-packages/

步驟:

①建立一個Package工程

flutter create --template=package hello#指定org能夠自動建立平臺橋接文件和example示例path_to_fluttersdk/bin/flutter create --org com.yoozoo --template=plugin sharesdk

②實現package:lib/<package name>.dart下爲插件的flutter端代碼,ios/Classes/HelloPlugin.m 下爲 原生層實現代碼,初始代碼已有bridge示例

③啓動xcode,插件bridge文件在Pods/Development Pods/hello/Classes/下:在編輯Xcode中的iOS平臺代碼以前,首先確保代碼至少已經構建過一次(例如,從Xcode中運行示例應用程序或終端執行cd hello/example; flutter build ios --no-codesign)。

④自動生成api文檔:

cd package工程目錄export FLUTTER_ROOT=~/dev/flutter$FLUTTER_ROOT/bin/cache/dart-sdk/bin/dartdoc

⑤發佈前檢查:

//過程會提示你完善pubspec.yaml,關於example和test的警告可無視flutter packages pub publish --dry-run

⑥發佈:

flutter packages pub publis

關於分包: 對於ShareSDK和支付這樣的Plugin須要分包且cocoapods含有subspec的,須要開發者在設置完dependences後手動去 packageName.podspec 設置對應的依賴,而後運行 Flutter upgrade package

## To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html#Pod::Spec.new do |s|

s.name = 'sharesdk_flutter'

s.version = '0.0.1'

s.summary = 'flutter plugin for sharesdk.'

s.deion = 'ShareSDK is the most comprehensive Social SDK in the world,which share easily with 40+ platforms.'

s.homepage = 'http://www.mob.com'

s.license = { :file => '../LICENSE' }

s.author = { 'Mob' => 'mobproducts@163.com' }

s.source = { :path => '.' }

s.source_files = 'Classes/**/*'

s.public_header_files = 'Classes/**/*.h'

s.dependency 'Flutter'

s.dependency 'mob_sharesdk'# s.dependency 'mob_sharesdk/ShareSDKUI'# s.dependency 'mob_sharesdk/ShareSDKPlatforms/QQ'# s.dependency 'mob_sharesdk/ShareSDKPlatforms/SinaWeibo'# s.dependency 'mob_sharesdk/ShareSDKPlatforms/WeChat'# s.dependency 'mob_sharesdk/ShareSDKPlatforms/Facebook'# s.dependency 'mob_sharesdk/ShareSDKPlatforms/Twitter'

s.ios.deployment_target = '8.0'end

附:

ShareSDK官方package主頁:

https://pub.dartlang.org/packages/sharesdk

我的學習Demo github地址:

https://github.com/vhbvb/Flutter_learn

ShareSDK package開發git: https://github.com/MobClub/ShareSDK-For-Flutter

我的爬坑記錄:

如何給圖片設置圓角

Clip系列的Widget能夠嘗試一下,好比 ClipRRect。這種裝飾反而很差作

如何設置圖片Slice

image Widget有slice屬性,可是注意你的圖片必定要在拉伸狀態,不然會顯示異常

如何設置默認ListView 底部顯示

ListView 的reverse 設置成true 而後吧scroll的offset設置成 0 既能夠,使用與 IM 消息列表等場景

ListView 沉浸式狀態欄怎麼弄的

ListView 默認會偏離狀態欄,目前解決方案是scrollable + column

如何優雅的設置鍵盤彈出偏移動畫

嵌套一個safaArea widget,會默認偏移

如何解決 ListView Widget複用問題

AutomaticKeepAliveClientMixin

多繼承問題怎麼解決

mixin, 什麼是mixin :

https://blog.csdn.net/awftnaaa/article/details/52885155

slider默認padding怎麼解決

相關文章
相關標籤/搜索