顯示具有 Flutter 標籤的文章。 顯示所有文章
顯示具有 Flutter 標籤的文章。 顯示所有文章

2024年4月6日 星期六

Flutter教學-Dart的運算符

(一)算術運算符

+ 加法

 - 減法   

* 乘法 

 / 除法   

% 取餘  

 ~/ 取整

// 定義兩個整數變數 a  b
int a = 13; // a 的值為 13
int b = 4; // b 的值為 4

// 計算 a b 的和
var sum = a + b; // sum 的值為 17

// 計算 a b 的差
var difference = a - b; // difference 的值為 9

// 計算 a b 的積
var product = a * b; // product 的值為 52

// 計算 a b 的商
var quotient = a / b; // quotient 的值為 3.25

// 計算 a b 的餘數
var remainder = a % b; // remainder 的值為 1

// 計算 a b 整數部份的商
var integerQuotient = a ~/ b; // integerQuotient 的值為 3


(二)關係運算符

== 等於 

!= 不等於 

>大於 

<小於 

>= 大於或等於 

<=小於或等於

例子:

// 定義兩個整數變數 a  b
int a = 13;
int b = 4;

// 檢查 a 是否等於 b
var isEqualTo = a == b; // isEqualTo = false

// 檢查 a 是否不等於 b
var isNotEqualTo = a != b; // isNotEqualTo = true

// 檢查 a 是否大於 b
var isGreaterThan = a > b; // isGreaterThan = true

// 檢查 a 是否小於 b
var isLessThan = a < b; // isLessThan = false

// 檢查 a 是否大於或等於 b
var isGreaterThanOrEqualTo = a >= b; // isGreaterThanOrEqualTo = true

// 檢查 a 是否小於或等於 b
var isLessThanOrEqualTo = a <= b; // isLessThanOrEqualTo = false


(三)邏輯運算符

! 取反

 || 或者 

 && 並且 

  • &&: 邏輯與運算符。只有兩個運算元都為 true 時,結果才為 true
  • ||: 邏輯或運算符。只要有一個運算元為 true,結果就為 true
  • !: 邏輯非運算符。對運算元取反。


// 定義兩個布林變數 a  b
bool a = true; //a宣告為真
bool b = false; //b宣告為假

// 檢查 a b 是否都為 true
var isBothTrue = a && b; // isBothTrue = false

// 檢查 a b 是否為 true
var isEitherTrue = a || b; // isEitherTrue = true

// 檢查 a 是否為 false
var isAFalse = !a; // isAFalse = false


(四)賦值運算符

  • =: 基本賦值運算符。將右運算元的值賦值給左運算元。
  • ??=: 如果左運算元為 null,則將右運算元的值賦值給左運算元。
  • +=: 加法賦值運算符。將右運算元的值加到左運算元上。
  • -=: 減法賦值運算符。將右運算元的值從左運算元中減去。
  • *=: 乘法賦值運算符。將左運算元的值乘以右運算元的值。
  • /=: 除法賦值運算符。將左運算元的值除以右運算元的值。
  • %=: 取餘賦值運算符。將左運算元的值除以右運算元的值並取餘數。
  • ~/=: 整數除法賦值運算符。將左運算元的值除以右運算元的值並取整數商。

例子:

// 定義兩個整數變數 a,e
double a;
int? e;

// 13 賦值給 a,b沒有賦值,為null
a = 13;

// a 1
a += 1;

// a 乘以 2
a *= 2;

// a 除以 3
a /= 3;

// a 的餘數賦值給 b
double b = a % 3;

// a 的整數商賦值給 c
int c = a ~/ 3;

// e的值為null,會被賦值為23
e??=23;



2023年8月14日 星期一

Flutter學習-Drawer

 drawer(抽屜)是Flutter中Scraffold的一個UI組件,用於創建一個從屏幕邊緣滑出的側邊欄菜單。這個側邊欄通常用於放置應用程序的導航鏈接、設置選項或其他相關內容,以提供更好的用戶體驗和導航方式。



以下是Drawer類的各項屬性說明:

const Drawer({
super.key,
this.backgroundColor, //背景顏色
this.elevation, //陰影高度
this.shadowColor, //陰影顏色
this.surfaceTintColor,
this.shape, //邊線設定
this.width, //側欄寬度
this.child, //主要內容,多半是於listview中,DrawerHeader和ListTile相互配合
this.semanticLabel, //語義標籤,用於更好的適別
}) : assert(elevation == null || elevation >= 0.0);
範例:

drawer: Drawer(
//背景顏色
backgroundColor: Colors.blueGrey,
elevation: 8.0, //陰影高度
semanticLabel: 'Custom Drawer', //語義標籤
width: 300, //側欄寬度
//邊線設定
shape: Border(
top: BorderSide(width: 1.0, color: Color(0xFFFFDFDFDF)),
left: BorderSide(width: 2.0, color: Color(0xFFFFDFDFDF)),
right: BorderSide(width: 3.0, color: Color(0xFFFF7F7F7F)),
bottom: BorderSide(width: 4.0, color: Color(0xFFFF7F7F7F)),
),
shadowColor: Colors.cyan, //陰影顏色
//側欄內容 ,一般配合listview使用
child: ListView(
children: [
DrawerHeader(
decoration: BoxDecoration(
color: Colors.blue,
),
child: Text(
'側欄標題',
style: TextStyle(
color: Colors.white,
fontSize: 24,
),
),
),
ListTile(
leading: Icon(Icons.home),
title: Text('Home'),
onTap: () {
// Handle tap on Home
},
),
ListTile(
leading: Icon(Icons.settings),
title: Text('設定一'),
onTap: () {
// Handle tap on Settings
},
),
],
),
),


如果要在側欄上,點選後,關閉側欄,要使用:Navigator.pop(context);
ListTile(
leading: Icon(Icons.keyboard_backspace_outlined),
title: Text('設定一'),
onTap: () {
Navigator.pop(context); //關閉側欄方法
},
),

要在特定的按鈕點選後讓側欄打開,需先用Builder包起來,才能使用
floatingActionButton: Builder(
builder: (BuildContext context) {
return FloatingActionButton(
onPressed: () {
Scaffold.of(context).openDrawer();
},
tooltip: 'Increment',
child: const Icon(Icons.add),
);
},
)

在每個頁面都用相同的appbar 、drawer方法參考:



2023年5月7日 星期日

flutter學習-riverpod

Riverpod

一、使用目的

Riverpod是一個flutter使用的狀態管理工具。


二、官網及下載處

官網:https://riverpod.dev/

pub:https://pub.dev/packages/riverpod


三、使用方法:

(一)在使用時,一般在程式的入口main()中,加入ProviderScope(child: MyApp()),這樣於下運作的程式才能使用全域常數的功能

void main() {
runApp(ProviderScope(child: MyApp()));
}

(二)六種不同情況的引入方式及用法

(1)Provider  宣告一個在任何地方都可以使用及讀取的全域常數。

宣告的方法如下:

//宣告number為一個Provider<int>類型的全域變數,切始值為0

(1-1)需要一個全域的int常數時,宣告為Provider<int>

final Provider<int> number=Provider<int>((ProviderRef ref) {
return 0;
});


要在別的位置取得這個值,可以在可使用ref的地方,使用以下的寫法

ref.watch(number)

或將其值賦予一個變數,以便在後面使用:

final getNumber=ref.watch(number);

上面ref.watch(number)的值就是等於上面回傳的0。

(1-2)需要一個全域的String常數時,宣告為Provider<String>

final Provider<String> countryProvider = Provider<String>((ProviderRef ref) {
return 'Taiwan';
});


要在別的位置取得這個值,可以在可使用ref的地方,使用以下的寫法

ref.watch(countryProvider)

或將其值賦予一個變數,以便在後面使用:

final getNumber=ref.watch(countryProvider);

上面ref.watch(countryProvider)的值就是等於上面回傳的Taiwan。


(1-3)需要一個全域的方法,宣告為Provider<方法>

(1-3-1) 不傳入參數

final Provider<Location> locationProvider = Provider((ProviderRef ref) {
return Location();
});


(1-3-2)若要傳入一個參數,可再自己新增

final Provider<Location> locationProvider = Provider((ProviderRef ref) {
return Location(providerRef: ref);
});


為了便於透過ProviderRef 類型的ref,引入其它的Provider,因此這裡將它當作location傳入建構式中,寫法如下:

final Provider<Location> locationProvider = Provider((ProviderRef ref) {
return Location(providerRef: ref); //這裡多了一個傳入的參數
});

class Location {
final ProviderRef providerRef;

Location({required this.providerRef}); //與之搭配的建構式

String get info { //下面使用了傳入的providerRef,以便引入其它的全域Provider,做其它使用
final String country = providerRef.read(countryProvider); //taiwan
final String city = providerRef.read(cityProvider); //taipei
return '$country ,$city';
}
}


要在別的位置取得這個Provider,可以在可使用ref的地方,使用以下的寫法

ref.watch(locationProvider)

或將其值賦予一個變數,以便在後面使用:

final location=ref.watch(locationProvider);

上面ref.watch(locationProvider)的值為 Location(providerRef: ref)。

而要使用這個 Location裡的方法,或讀取它的值,可以用。

location.info <=這可以取得上面info方法的回傳值  '$country ,$city'


(2)StateProvider  宣告一個可以變得簡單變數

宣告方法如下:

final StateProvider<int> postalCodeProvider = StateProvider((ref) {
return 369;
});

上面的posttalCodeProvider為StateProvider<int>類型,其值為369,與上面的Provider不同的地方,使用者可以透過簡單的方法,改變回傳的369的值。

改變的方法,可以在一個可使用ref的地方,設定一個按鈕,並寫如下的程式
ElevatedButton(
onPressed: () {
ref.read(postalCodeProvider.notifier).state++;
},
child: const Text('點我加數字'),
),

read的()中的格式是(要引入的StatePriver變數名稱.notifier),而後的.state <=這代表要執行的那個值,這裡指的是上面的369,後面的++,指每點一次就加1。因此上面的寫法,會在每一次點選的時候,將state值加1。

而要在畫面中顯示的方法與執行的方法略有不同,它是透過watch進行監聽。如下宣告的方法:
舊的寫法
final postalCode = ref.watch(postalCodeProvider.state).state;
要注意的是,這裡用到的是watch,不是read,( )裡面的格式則是(要引入的StatePriver變數名稱.state),,而後的.state <=這代表要顯示的那個值。

新版有寫的寫法較為簡潔
final postalCode = ref.watch(postalCodeProvider);

其後可能在畫面中,適當的地方顯示出這個postalCode,如Text(postalCode.toString()), 這樣就可以做到隨時監聽,在畫面中改變數字的效果。

(3)StateNotifierProvider 宣告多個可以變的變數

StateNotifierProvider和StateProvider用法很相似,StateProvider有一個state可以讀取,寫程式時可以簡單的改變它的值,而StateNotifierProvider它可以建立一個類,其中擴充自StateNotifier,相對於只能操控固定的值,StateNotifierProvider可以進行更靈活的操作。

宣告的方法如下:
final StateNotifierProvider<FamilyNumberProvider, int> familyNumberProvider =
StateNotifierProvider<FamilyNumberProvider, int>((ref) {
return FamilyNumberProvider();
});
上面程式中< 1,2> ,前面的部份為要傳入類的名字,而後面int則為要傳回值的類型,而最後要回傳(return)的是你要宣告為全域變數的方法,這個方法名要與你建的類建構式相同。

擴充自StateNotifier的類寫法參考如下:
class FamilyNumberProvider extends StateNotifier<int> {
//super(0)中的0,預設state變數的值,除了可以是int外,也可以是Stringlist
//:super([])
FamilyNumberProvider() : super(0);

//state增加的方法,想寫什麼可以自己設計
void increament() {
state = state + 1;
}

//state減少的方法,想寫什麼可以自己設計
void decreament() {
state--;
}
}
上面要注意的是super(0)這個部份,這裡0,在這個class裡預設為state,所以下面你要透過state進行進一步的操作,而這個state,是等等使用ref.watch監控的對象。
如果要引入的值比較多,可以使用陣列,super([]),可以參考官網的作法。

而若要顯示於畫面的寫法如下:
final familyNumber = ref.watch(familyNumberProvider);
注意這裡宣告的方法與StateProvider是不同的,( )中沒有加上.state

其後可能在畫面中,適當的地方顯示出這個familyNumber,如Text(familyNumber.toString()), 這樣就可以做到隨時監聽,在畫面中改變數字的效果。


(4)FutureProvider flutter中有一些異步的方法,而riverpod有提供了一個可以將異步的方法於全域方法引用的方法,以下為使用的方法示範。


(4-1)任何一個異步的方法,以下會每隔2秒傳回Hello, Riverpod字串

Future<String> fetchData() async {

  await Future.delayed(Duration(seconds: 2));

  return 'Hello, Riverpod!';

}


(4-2)宣告dataProvider為全域變數,可在適當的時機,讀取上面4-1建立的異步程式,因為是異步,所以宣告時要記得加入async和await

final dataProvider = FutureProvider<String>((ref) async { return await fetchData(); });

(4-3)顯示於畫面

Widget build(BuildContext context, WidgetRef ref) {
  AsyncValue<dataProvider> dataAsyncValue = ref.watch(dataProvider); //利用ref.watch(dataProvider); 

  return dataAsyncValue.when(

    data: (data) => Text(data), //讀取到資料後會在這裡處理,data指的是回傳的資料

    loading: () => CircularProgressIndicator(),  //讀取中顯示的值

    error: (error, stackTrace) => Text('Error: $error'), //讀取錯誤的回傳值

  );

})



(5)StreamProvider

這個用法與futureProvider相同,就是其宣告成全域變數的方法為一個Stream,而在宣告時用StreamProvider<回傳類型>((ref){ })取代FutureProvider<回傳類型>((ref) async {})

(6)ChangeNotifierProvider

ChangeNotifierProvider官方並不推薦使用,但在實際使用上,這個方法相對於較於靈活,簡單,如果你的狀態很多,採用這個方法比較容易宣告很多的變數。

宣告成全域變數的方法如下:

final counterProvider = ChangeNotifierProvider<MychangerNotifierProvider>(
(ref) => MychangerNotifierProvider());

其回傳類別的寫法,裡面設了兩個變數_value及_value1

class MychangerNotifierProvider extends ChangeNotifier {
var _value = 0;
var _value1 = 0;
int get value => _value;
int get value1 => _value1;

void increament() {
_value++;
notifyListeners();
}

void decreament() {
_value1--;
notifyListeners();
}
}
要注意擴充的類別為ChangeNotifier,而在其方法裡面,在執行完後,要加上notifyListeners();更新畫面,否則畫面不會更新。

而若要顯示於畫面的寫法如下:
final counter = ref.watch(counterProvider);

其後可能在畫面中,適當的地方顯示出這個counter,如Text(counter.value)), 或是Text(counter.value1)),其中value是你於changeNotifier中宣告的值,這樣就可以做到隨時監聽,在畫面中改變數字的效果。

在顯示方面,可配合Consumer進行小範圍的更新,減少畫面的重新繪製,減少資源浪費。
宣告counter為CounterProvider。




.family

有時候,在使用ref時,會有丟入參數的需要,而.family就可以在引用時丟入一個參數。

宣告的方法如下:

//.family
final message = Provider.family((ref, int myvalue) {
return Location2(providerRef: ref, number: myvalue);
});

第二個參數,就是在引用時,要丟入的值。

回傳的loction2類的寫法如下:

class Location2 {
final ProviderRef providerRef;
int number;

Location2({required this.providerRef, required this.number});

int get info {
return number;
}

count() {
number++;
}
}


而若要顯示於畫面的寫法如下:

final message=ref.watch(messageProvider(5));

記得要在引入的Provider後加入你要給的參數。

其後可能在畫面中,適當的地方顯示出這個message,如Text(message.info.toString())。



參考網頁:

Youtube視訊,示範各個不同riverpod的用法


Flutter状态管理之Riverpod



riverpod實作,透過Appwrite複刻一個Twitter
Flutter App Development Course – Build a Twitter Clone with Appwrite and Riverpod

Flutter Riverpod 輕鬆學,簡單處理狀態管理!

Flutter Riverpod 輕鬆學(二),一些進階用法!




2023年4月17日 星期一

Flutter學習-image_picker組件

官方庫下載連結

https://pub.dev/packages/image_picker


目的:在Flutter中,image_picker套件可以讓使用者在應用程式中從不同來源選擇圖像,例如相機或圖庫。它提供了一個方便的API,可以幫助開發人員輕鬆地獲取所需的圖像並將其集成到應用程式中。使用image_picker,您可以讓用戶在應用程式中添加個性化的圖像,這有助於提高應用程式的用戶體驗。


在使用前需給予手機使用本地端圖片的權限

ISO系統:

將以下鍵添加到您的Info.plist文件中,該文件位於<project root>/ios/Runner/Info.plist

  • NSPhotoLibraryUsageDescription- 描述為什麼您的應用需要照片庫的許可。這在可視化編輯器中 稱為隱私 - 照片庫使用說明。
    • false如果您始終傳遞for則不會請求此權限requestFullMetadata,但 App Store 政策要求包含 plist 條目。
  • NSCameraUsageDescription- 描述為什麼您的應用需要訪問相機。這在可視化編輯器中稱為Privacy - Camera Usage Description 。
  • NSMicrophoneUsageDescription- 如果您打算錄製視頻,請描述為什麼您的應用需要訪問麥克風。這在可視化編輯器中稱為Privacy - Microphone Usage Description 。

安卓系統

從版本0.8.1開始,Android 實現支持在 Android 4.3 或更高版本上選擇(多個)圖像。

無需配置 - 插件應該開箱即用。然而,強烈建議為 Android 在內存不足時殺死應用程序做好準備。在Android 上處理 MainActivity 銷毀部分討論瞭如何為此做準備 。

不再需要將其android:requestLegacyExternalStorage="true"作為屬性添加到<application>AndroidManifest.xml 中的標記,因為image_picker已更新為使用範圍存儲。

注意:使用相機拾取的圖像和視頻會保存到應用程序的本地緩存中,因此預計只會暫時存在。如果您需要永久存儲您選擇的圖像,您有責任將其移動到更永久的位置。

如要更改,檔案位置位於app/src/main/AndroidManifest.xml


<manifest> <application> ... </application> // 寫入文件權限 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> // 讀取文件權限 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> // 使用相機檔限 <uses-permission android:name="android.permission.CAMERA" /> </manifest>


使用的方法

(一)初始化
//初始化一個imagePicker選擇器,以便進行後續的選擇工作
final ImagePicker picker = ImagePicker();

(二)選擇一張照片
(2-1) picker.pickImage()

如果要從相簿選擇一張照片,並存在一個變數中,如下:

final XFile? image = await picker.pickImage(source: ImageSource.gallery); 

(2-2)picker.pickImage()
如果要從相機選擇一張照片,並存在一個變數中,如下:

final XFile? photo = await picker.pickImage(source: ImageSource.camera); 


(二)選擇多張照片(picker.pickMultiImage)

final List<XFile> images = await picker.pickMultiImage();


(三)選擇一段影片
(3-1)從相簿取得(source: ImageSource.gallery)
final XFile? galleryVideo = await picker.pickVideo(source: ImageSource.gallery); 

(3-2)從相機取得(source: ImageSource.camera)

 final XFile? cameraVideo = await picker.pickVideo(source: ImageSource.camera); 


教學網頁

https://www.cnblogs.com/ilgnefz/p/15954507.html

教學影片

https://www.youtube.com/watch?v=IePaAGXzmtU

iso權限說明

https://www.jianshu.com/p/d5f70743fee1


2023年3月16日 星期四

Flutter學習- 序列化及反序列化

 一、讀取json數據

var a=jsonDecode(這裡放讀出來要轉的資料);  那a就是你可以直接處理的東西..

如果要讀資料,基本就是 a['你的key的名字'] 或是 a[你要讀取的序號]

{ }<=這種引號就是以key的方法讀取.  [ ]<=這種就是讀陣列所在位置,由0開始..

以{"name":[a,b,c]} 當原始資料為例,那轉完以後,存在a這個變數。

 那要讀就是 a['name'] <=這樣可以讀到 [a,b,c] 如果你要再讀下去  a['name'][0] ,這樣就可以讀到 a, 而a['name'][1]這樣可以讀到b

二、序列化及反序列化

如果你要序列化,就是把你現在的資料在一個類裡面。所以要建一個存這些資料的類別。如以User類別為例:class User { },這裡面有幾個屬性,就要建幾個變數...因為你要把每個你讀到的資料都對應進去,以方便用我們習慣讀類屬性的方法用 點 . 的方法讀取。假設你讀的資料有name 和 email。包含每個類下面要有的建構式,如下的寫法:
class User {

final String name; //宣告一個字串類型的name

final String email; //宣告一個字串類型的email


User(this.name, this.email); //建構式

}


序列化方法

fromJson函式裡面的寫法有很有多種,我習慣的寫法如下,這種寫法如果有空值,它會自動存為null,比較不會因為對應不到而報錯。

factory User.fromJson(Map<String, dynamic> json) => User(

    name: json["name"]== null ? null : json["name"],

    email: json["email"]== null ? null : json["emal"],

  );

基本就是將你的json原始資料跟User類相互對應好。如果你有更多的資料,就配合上面的程式,一直增加下去..如要填加一個性別,就是:

 Sex: json["sex"]== null ? null : json["sex"]



反序列化方法

最後是轉回來的方法,要存進資料庫的方法,大致如下,也是以此類推而已。

Map<String, dynamic> toJson() => {

    "name": name == null ? null : name,  //如果資料為null,就空值,沒有就將name值,當value值讀進去。

    "email": email == null ? null : email,

  };


可以直接轉譯的網站:

https://app.quicktype.io/

JSON to Dart (javiercbk.github.io)

2023年1月29日 星期日

Flutter學習- RxList和List類型轉換方法


List initial = [];

  RxList data= RxList(initial);

像這樣使用

  List<clientModal> clientmodal = [] ;
  RxList<clientModal> data = RxList(initial as List<clientModal> );

 引自:flutter - A value of type 'List<ClienteModel>' can't be assigned to a variable of type 'RxList<ClienteModel>' - Stack Overflow


2022年12月23日 星期五

Flutter學習總目錄

一、Dart語言學習

Map

List


二、Flutter相關知識整理

初始程式範例頁面註解

建構子的寫法

將map以 key值或是values排序的方法

Stack練習 橫標製作

Flow布局練習

key

Material及Scaffold介紹

StatelessWidget和StatefulWidget

序列化及反序列化


三、Flutter組件使用說明

theme 布景

教學隨意談: Flutter學習- theme (acao0429.blogspot.com)

教學隨意談: Flutter學習-11 padding (acao0429.blogspot.com)

教學隨意談: Flutter學習 -FittedBox組件 (acao0429.blogspot.com)


文字

教學隨意談: Flutter學習-8 Text組件 (acao0429.blogspot.com)

教學隨意談: Flutter學習-10 TextField組件 (acao0429.blogspot.com)

教學隨意談: Flutter學習-8-1 RichText組件 (acao0429.blogspot.com)


按鈕

教學隨意談: Flutter學習-6 Button組件 (acao0429.blogspot.com)

教學隨意談: Flutter學習-DropdownButton組件 (acao0429.blogspot.com)

教學隨意談: Flutter學習-9-4 Radio和RadioListTile (acao0429.blogspot.com)

教學隨意談: Flutter學習-9-2 checkbox和CheckboxListTile組件 (acao0429.blogspot.com)

教學隨意談: Flutter學習-9-1 switch及SwitchListTile組件 (acao0429.blogspot.com)


圖片

教學隨意談: Flutter學習-7 圖片 image組件 (acao0429.blogspot.com)

教學隨意談: Flutter學習-image_picker組件 (acao0429.blogspot.com)


滑動軸

教學隨意談: Flutter學習-Slider組件 (acao0429.blogspot.com)


Bar

教學隨意談: Flutter學習-5 appBar組件 (acao0429.blogspot.com)

教學隨意談: Flutter學習- TabBar組件 (acao0429.blogspot.com)

教學隨意談: Flutter學習 -BottomAppBar組件 (acao0429.blogspot.com)

教學隨意談: Flutter學習- BottomNavigationBar組件 (acao0429.blogspot.com)

教學隨意談: Flutter學習 - flutter_rating_bar組件 (acao0429.blogspot.com)


繪圖

教學隨意談: Flutter學習-Path 路徑 (acao0429.blogspot.com)

教學隨意談: Flutter學習-Canvas組件 (acao0429.blogspot.com)


其它

教學隨意談: Flutter學習-AbsorbPointer組件 (acao0429.blogspot.com)

教學隨意談: Flutter學習- Badge組件 (acao0429.blogspot.com)

教學隨意談: Flutter學習- hero組件 (acao0429.blogspot.com)

教學隨意談: Flutter學習- statefulbuilder組件 (acao0429.blogspot.com)

教學隨意談: Flutter學習 -poppular組件 (acao0429.blogspot.com)


頁面切換

教學隨意談: Flutter學習-Pageview (acao0429.blogspot.com)


清單顯示及方格顯示

教學隨意談: Flutter學習-listview (acao0429.blogspot.com)


教學隨意談: Flutter學習-silver及SliverFillRemaining使用 (acao0429.blogspot.com)


裝飾器

教學隨意談: Flutter學習11-Decoration (acao0429.blogspot.com)


表單

教學隨意談: Flutter學習-10 form組件 (acao0429.blogspot.com)

異步

教學隨意談: Flutter學習-streambuilder組件 (acao0429.blogspot.com)


狀態管理

教學隨意談: flutter學習-riverpod (acao0429.blogspot.com)

教學隨意談: Flutter學習 -Provider組件 (acao0429.blogspot.com)

Flutter與GetX相關

教學隨意談: flutter學習-GetX (路由整理) (acao0429.blogspot.com)


Flutter與firebase讀取相關

教學隨意談: Flutter學習-如何從firebase Cloud Firestore取值 (acao0429.blogspot.com)

教學隨意談: Flutter學習-firebase (acao0429.blogspot.com)

教學隨意談: Flutter學習-firebase Cloud Firestore說明(1) (acao0429.blogspot.com)

教學隨意談: Flutter學習-firebase Cloud Firestore說明(2) (acao0429.blogspot.com)

教學隨意談: flutter中的firebase套件有哪些,還有哪些功能? (acao0429.blogspot.com)

教學隨意談: 如何取得SHA-1 (acao0429.blogspot.com)



其它別人的教學:https://blog.csdn.net/sinat_17775997/article/details/110490527

2022年11月1日 星期二

Flutter學習-Pageview

Pageview提供了頁面滑動,可提供滑動展示,圖示展示等功能
屬性說明:
PageView({
Key? key,
this.scrollDirection = Axis.horizontal, //滑動方向
this.reverse = false, //是否反轉滑動
PageController? controller, //page控制器
this.physics, //拉動至邊緣時特效顯示的模式
this.pageSnapping = true, //是否要一次滑動到底
this.onPageChanged, //page改變的回調
List<Widget> children = const <Widget>[], //要放的page,為列表
this.dragStartBehavior = DragStartBehavior.start,
this.allowImplicitScrolling = false, //允許前後頁緩存
this.restorationId, //在某種情況下,保持滑動的偏移量
this.clipBehavior = Clip.hardEdge, //滑裁的方式
this.scrollBehavior,
this.padEnds = true,
}) : assert(allowImplicitScrolling != null),
assert(clipBehavior != null),
controller = controller ?? _defaultPageController,
childrenDelegate = SliverChildListDelegate(children),
super(key: key);

二、基本的使用方法如下:
PageView(
children: [
Container(
color: Colors.red,
child: Center(child: Text('第一頁', style: TextStyle(color: Colors.black),),),
),
Container(
color: Colors.blue,
child: Center(child: Text('第二頁', style: TextStyle(color: Colors.black),),),
),
Container(
color: Colors.yellow,
child: Center(child: Text('第三頁', style: TextStyle(color: Colors.black),),),
),
],
),


三、PageController使用方法如下:

PageController({
this.initialPage = 0, //初始頁面
this.keepPage = true, //scrable的頁面
this.viewportFraction = 1.0, //
}) : assert(initialPage != null),
assert(keepPage != null),
assert(viewportFraction != null),
assert(viewportFraction > 0.0);

配合PageController使用的範例:

class _MyHomePageState extends State<MyHomePage> with AutomaticKeepAliveClientMixin{
PageController page=PageController();
@override
void dispose() {
page.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
super.build(context);

return Scaffold(
body:Column(
children: [
Expanded(child: PageView(
controller:page,
allowImplicitScrolling: true,
children: [
Container(
color: Colors.red,
child: Center(child: Text('第一頁', style: TextStyle(color: Colors.black),),),
),
Container(
color: Colors.blue,
child: Center(child: Text('第二頁', style: TextStyle(color: Colors.black),),),
),
Container(
color: Colors.yellow,
child: Center(child: Text('第三頁', style: TextStyle(color: Colors.black),),),
),
],
),),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ElevatedButton(onPressed: (){
if (page.hasClients) {
page.animateToPage(
0,
duration: const Duration(milliseconds: 400),
curve: Curves.easeInOut,
);
}
}, child: Text('點我跳到第一頁'),),
ElevatedButton(onPressed: (){
if (page.hasClients) {
page.animateToPage(
1,
duration: const Duration(milliseconds: 400),
curve: Curves.easeInOut,
);
}
}, child: Text('點我跳到第二頁'),),
ElevatedButton(onPressed: (){
if (page.hasClients) {
page.animateToPage(
2,
duration: const Duration(milliseconds: 400),
curve: Curves.easeInOut,
);
}
}, child: Text('點我跳到第三頁'),),
],
),
],

), // This trailing comma makes auto-formatting nicer for build methods.
);
}

//此為AutomaticKeepAliveClientMixin的方法,在此重寫裡面的wantKeepAlive,使頁面可緩存,不用每次重複讀取
@override
bool get wantKeepAlive => true;

}