相對(duì)于iOS開(kāi)發(fā),F(xiàn)lutter的布局更具有靈活性,每個(gè)頁(yè)面設(shè)計(jì)都不一樣,相同頁(yè)面可選擇的布局方式也不一樣,如果單純的說(shuō)應(yīng)該如何去布局,我覺(jué)得不現(xiàn)實(shí),大家可以參考下 Flutter官方的布局教程 。接下來(lái),筆者,通過(guò)項(xiàng)目中的一個(gè)頁(yè)面,來(lái)一步一步的拆解布局的流程。整個(gè)過(guò)程,基本上按照拆解、組件封裝、具體布局這三步來(lái)的。
創(chuàng)新互聯(lián)公司是一家專(zhuān)注于網(wǎng)站設(shè)計(jì)制作、網(wǎng)站制作與策劃設(shè)計(jì),澄海網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)公司做網(wǎng)站,專(zhuān)注于網(wǎng)站建設(shè)十多年,網(wǎng)設(shè)計(jì)領(lǐng)域的專(zhuān)業(yè)建站公司;建站業(yè)務(wù)涵蓋:澄海等地區(qū)。澄海做網(wǎng)站價(jià)格咨詢(xún):18982081108
根據(jù)設(shè)計(jì)圖,可以看出整體可以分成兩部分,上面一部分是系統(tǒng)介紹模塊,下面一部分是真正的登錄內(nèi)容,因?yàn)樯婕暗蒋B加,因此考慮用Stack;
系統(tǒng)介紹模塊部分:整體也是涉及到疊加,考慮用Stack,分為四部分。最底部漸變色背景用一個(gè)contanier,無(wú)須指定位置,全視圖擴(kuò)展;載放logo圖標(biāo)在上一層,用Image。最后兩個(gè)Text同級(jí)放在最上層。Image,Text各用Positioned包裹去指定位置。
登錄內(nèi)容模塊是最外層是一個(gè)Contanier容器,去控制背景色和圓角。然后是一個(gè)Column元素,逐行排列。
第一行為Image,
第二行為T(mén)ext,
第三行可以看成一個(gè)小Column,分兩塊進(jìn)行布局
第四行可以看成一個(gè)小Column,分兩塊進(jìn)行布局
第五行可以看作一個(gè)TextButton,
第六行可以看作一個(gè)Row,分三塊進(jìn)行布局
通過(guò)上面這樣一步一步的分析后,基本上對(duì)大致的布局有了一個(gè)了解,最外層的控件大致選對(duì)(只要能實(shí)現(xiàn)的話,就是復(fù)雜度以及效率的問(wèn)題),然后一步一步的拆解每一行的元素,如果有重復(fù)的或者覺(jué)得可以封裝出來(lái)的部分,則進(jìn)行下一步。
每一行的拆解,大致也是按照這個(gè)思路來(lái)進(jìn)行,因此筆者在這里就不做講解了。
在做到第三第四行的時(shí)候,發(fā)現(xiàn)這兩個(gè)很相似,而且設(shè)計(jì)到一些交互邏輯,筆者就想對(duì)第三第四行的這種展示進(jìn)行封裝,覺(jué)得今后的布局可能會(huì)用到,因此在這一步,可以先把這一塊兒抽離出一個(gè)控件。利用TextField來(lái)實(shí)現(xiàn)這種輸入操作,具體的實(shí)現(xiàn)筆者不再詳細(xì)的描述了。
經(jīng)過(guò)這一步,整體的規(guī)劃設(shè)計(jì)圖已經(jīng)有了,各個(gè)組件也都有了,接下來(lái)的工作就是組裝了。
具體布局設(shè)計(jì)到一些細(xì)節(jié)的地方,例如整體Column的居中對(duì)齊(crossAxisAlignment)、間隔(Padding或Container包裹,筆者更喜歡用SizedBox占位)、居左居右居中(Align)、點(diǎn)擊事件(GestureDetector)以及圓角(BorderRadius)等一些特殊情況。
像第六行row是放在底部的,就可以在第六行前面增加一個(gè)Spacer()去填充空白區(qū)域。
對(duì)文字顏色大小等,可以用TextStyle直接設(shè)置。
對(duì)于輸入框的刪除按鈕,可以用Offstage這種Flutter特有的控制顯示隱藏的控件。
gRPC是谷歌開(kāi)發(fā)的一款遠(yuǎn)程過(guò)程調(diào)用系統(tǒng),可以讓客戶(hù)端像調(diào)用本地對(duì)象一樣使用服務(wù)端應(yīng)用的方法,使用protocol buffers接口定義語(yǔ)言來(lái)定義服務(wù)方法,protocol buffer定義參數(shù)和返回類(lèi)型。
protobuf類(lèi)似json,是一種數(shù)據(jù)結(jié)構(gòu)協(xié)議,在android studio中安裝Protobuf Support,方便查看編寫(xiě)的proto文件
dart使用proto插件將proto文件生成對(duì)應(yīng)的dart文件,使用如下步驟
1、安裝flutter之后,再flutter的下面路徑中有pub命令,需要將命令加入到path中。
可以vi ~/.zshrc,在文件中加入source ~/.bash_profile,然后在vi ~/.bash_profile文件中加入下面路徑(:分割不同的路徑)
export PATH=/Users/webull/app/flutter/bin:/Users/webull/app/flutter/bin/cache/dart-sdk/bin:/Users/webull/.pub-cache/bin:$PATH
其中fluter/bin是flutter的命令路徑,dart-sdk/bin中包含了pub和其他dart命令,.pub-cache/bin是之后運(yùn)行pub之后建立的路徑,里面包含了proto-gen-dart命令,用來(lái)將proto文件轉(zhuǎn)換為dart的命令
2、使用下面的命令安裝proto插件
$ pub global activate protoc_plugin
安裝完成后,上面的用戶(hù)目錄中的.pub-cache目錄才會(huì)有proto-gen-dart文件。
1、其中/Users/webull是我的用戶(hù)目錄 app/flutter是flutter的安裝目錄
參考:
1、gRPC介紹
2、gRPC配置
環(huán)境準(zhǔn)備階段:
android-studio 版本:android-studio-ide-191.5977832-windows.exe 3.5.2
flutter版本:stable 版本 (完成系統(tǒng)環(huán)境變量 path配置)
dart版本:2.12.0 (完成系統(tǒng)環(huán)境變量 path配置)
完成相關(guān)軟件安裝。
配置flutter相關(guān)SDK及andriod studio路徑:
flutter config --android-sdk="C:\Users\Administrator\AppData\Local\Android\Sdk"
flutter config --android-studio-dir="D:\Program Files\Android\Android Studio"
執(zhí)行flutter doctor運(yùn)行成功。
夜神模擬器地址:D:\Program Files\Nox\bin (完成系統(tǒng)環(huán)境變量 path配置)
andriod SDK tools:C:\Users\Administrator\AppData\Local\Android\Sdk\platform-tools (完成系統(tǒng)環(huán)境變量 path配置)
nox_adb.exe connect 127.0.0.1:62001
dart SDK:D:\software\dartsdk-windows-x64-release\dart-sdk\bin
將C:\Users\Administrator\AppData\Local\Android\Sdk\platform-tools 下面adb.exe 復(fù)制至D:\Program Files\Nox\bin覆蓋
adb.exe,此外重新復(fù)制adb.exe命名為nox_adb.exe,替換原有的nox_adb.exe。
cdm 輸入nox_adb version 及adb version發(fā)現(xiàn)版本一致。
啟動(dòng)野神模擬器,輸入adb devices發(fā)現(xiàn)虛擬設(shè)備,執(zhí)行flutter devices發(fā)現(xiàn) 127.0.0.1:62001 設(shè)備。
修改C:\learn_flutter\first_flutter\android\gradle\wrapper\gradle-wrapper.properties
distributionUrl=
修改C:\learn_flutter\first_flutter\android\build.gradle
buildscript {
ext.kotlin_version = '1.3.50'
repositories {
// google()
// jcenter()
maven { url ' ' }
maven { url ' ' }
maven { url ' ' }
}
}
allprojects {
repositories {
// google()
// jcenter()
maven { url ' ' }
maven { url ' ' }
maven { url ' ' }
}
}
修改:C:\win-flutter\flutter\packages\flutter_tools\gradle\flutter.gradle
buildscript {
repositories {
// google()
// jcenter()
maven { url ' ' }
maven { url ' ' }
maven { url ' ' }
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.0'
}
}
//private static final String DEFAULT_MAVEN_HOST = " ";
private static final String DEFAULT_MAVEN_HOST = " ";
修改:C:\win-flutter\flutter\packages\flutter_tools\gradle\resolve_dependencies.gradle
repositories {
google()
jcenter()
maven {
//url "$storageUrl/download.flutter.io"
url " "
}
}
執(zhí)行 flutter run啟動(dòng)成功。
環(huán)境搭建坑點(diǎn)在于JDK兼容問(wèn)題以及網(wǎng)絡(luò)問(wèn)題。
當(dāng)我們同時(shí)為手機(jī)和平板適配編寫(xiě) app 針對(duì)不同屏幕尺寸進(jìn)行 UI 布局或當(dāng)用戶(hù)偏好設(shè)置較大字號(hào)或是想要最大限度等減少動(dòng)畫(huà)等;此時(shí)就需要 MediaQuery 來(lái)幫我們獲取所用設(shè)備的信息以及用戶(hù)設(shè)置的偏好信息;
MediaQuery 一直存在于 WidgetsApp 和 MaterialApp 中, MediaQuery 繼承自 InheritedWidget 是一個(gè)單獨(dú)的 Widget ,但一般通過(guò) MediaQuery.of(context) 來(lái)獲取相關(guān)信息;
當(dāng)相關(guān)信息發(fā)生變化,例如屏幕旋轉(zhuǎn)等時(shí),屏幕中 Widget 會(huì)重新構(gòu)建,以保持最新?tīng)顟B(tài);我們可以通過(guò) MediaQuery 構(gòu)造函數(shù)和提供的靜態(tài)方法手動(dòng)設(shè)置對(duì)應(yīng)的相關(guān)信息;
MediaQueryData 包含關(guān)于媒介的相關(guān)信息;一般通過(guò) MediaQuery.of(context) 獲??;
size 為媒介的尺寸大小,以邏輯像素為單位;
devicePixelRatio 為像素密度;與設(shè)備物理像素有關(guān),與橫豎屏等無(wú)關(guān);
orientation 為橫豎屏, Orientation.landscape 為橫屏, Orientation.portrait 為豎屏;
textScaleFactor 為
每個(gè)邏輯像素的字體像素?cái)?shù),小菜理解為字體的像素比;注意,小菜設(shè)置了默認(rèn)字體像素密度為標(biāo)準(zhǔn)的 1.2 倍之后調(diào)整設(shè)備系統(tǒng)字號(hào),其 1.2 倍依舊是以標(biāo)準(zhǔn)字號(hào)為基礎(chǔ)擴(kuò)大 1.2 倍;
platformBrightness 為當(dāng)前設(shè)備的亮度模式;注意調(diào)整屏幕亮度并不會(huì)改變?cè)撃J?,與當(dāng)前系統(tǒng)支持的黑暗模式和明亮模式相關(guān);
alwaysUse24HourFormat 為當(dāng)前設(shè)備是否為 24 小時(shí)制;
accessibleNavigation 為是否使用 TalkBack 或 VoiceOver 之類(lèi)的輔助功能與應(yīng)用程序進(jìn)行交互,用以輔助視力障礙人群;
invertColors 為是否使用顏色反轉(zhuǎn),主要用于 iOS 設(shè)備;
highContrast 為用戶(hù)是否要求前景與背景之間的對(duì)比度高,主要用于 iOS 設(shè)備;
disableAnimations 為平臺(tái)是否要求禁用或減少動(dòng)畫(huà);
boldText 為平臺(tái)是否要求使用粗體;
padding 為屏幕內(nèi)邊距,一般是劉海兒屏或異形屏中被系統(tǒng)遮擋部分邊距;
viewInsets 為鍵盤(pán)彈出時(shí)等遮擋屏幕邊距,其中 viewInsets.bottom 為鍵盤(pán)高度;
systemGestureInsets 為手勢(shì)邊距,如 Android Q 之后添加的向左滑動(dòng)關(guān)閉頁(yè)面等;
viewPadding 小菜理解為視圖內(nèi)邊距,為屏幕被劉海兒屏或異形屏中被系統(tǒng)遮擋部分,從 MediaQuery 邊界的邊緣計(jì)算;此值是保持不變;例如,屏幕底部的軟件鍵盤(pán)可能會(huì)覆蓋并占用需要底部填充的相同區(qū)域,因此不會(huì)影響此值;
physicalDepth 為設(shè)備物理層級(jí),小菜暫時(shí)還未想到對(duì)應(yīng)的應(yīng)用場(chǎng)景;
小菜在嘗試獲取其他子 Widget Size 時(shí),有兩點(diǎn)需要注意,首先要設(shè)置一個(gè)全局的 GlobalKey 來(lái)獲取當(dāng)前位置, key 需要為唯一的;第二通過(guò) GlobalKey().currentContext 獲取 BuildContext 上下文環(huán)境,從而獲取對(duì)應(yīng)尺寸;
MediaQuery 案例嘗試
小菜對(duì)于部分 MediaQueryData 的應(yīng)用和理解還不夠深入;如有錯(cuò)誤請(qǐng)多多指導(dǎo)!
Flutter是一個(gè)移動(dòng)應(yīng)用程序的軟件開(kāi)發(fā)工具包(SDK),具有以下特征:
跨平臺(tái)應(yīng)用的框架,沒(méi)有使用WebView或者系統(tǒng)平臺(tái)自帶的控件,使用自身的高性能渲染引擎自繪
簡(jiǎn)化版的瀏覽器,最大限度在android和ios上統(tǒng)一UI,包括業(yè)務(wù)邏輯和用戶(hù)體驗(yàn)
開(kāi)發(fā)語(yǔ)言使用dart,結(jié)合C, C++, 和Skia(2D渲染引擎)構(gòu)建
支持hot reload,包含著完整的控件和工具鏈
一切皆控件,控件是每個(gè)Flutter應(yīng)用程序的基本構(gòu)建塊,與分離視圖、控制器、布局和其他屬性的框架不同,F(xiàn)lutter具有一致的統(tǒng)一對(duì)象模型:控件。一個(gè)控件可以定義:結(jié)構(gòu)元素(比如按鈕或菜單)、風(fēng)格元素(比如字體或顏色方案)、布局的方面(比如填充)、一些業(yè)務(wù)邏輯等
組合大于繼承,控件本身通常由許多小型、單用途的控件組成,結(jié)合起來(lái)產(chǎn)生強(qiáng)大的效果,類(lèi)的層次結(jié)構(gòu)是扁平的,以最大化可能的組合數(shù)量
強(qiáng)化版的WebView,框架僅提供一個(gè)View層,大部分功能要依賴(lài)原生
目前只能夠運(yùn)行大部分Dart代碼(不能引入dart:mirrors或dart:html庫(kù))