寫在前面
這篇文章的目的是給純flutter萌新回答一些基礎問題,ctrl+f/cmd+f 搜尋關鍵字 控制元件名
本篇會持續更新
最後更新時間 2018-08-02
佈局篇
flutter中 控制元件各司其職,基礎控制元件中基本只包含自己的功能
顯示內容的負責顯示內容,如Text負責文字,Image負責圖片
容器的負責容器,Row,Column,ListView等
尺寸位置的負責自己,Padding,Container,SizedBox等
觸控手勢觸控相關:GestureDetector
flutter中在widget層級提倡組合模式,而不提倡繼承模式
比如你不應該有一個class TextButton extend Text/RaisedButton
這樣的方案出現
而應該是
class TextButton extends StatelessWidget {
final Function onPressed;
final String text;
final Color color;
final double fontSize;
final EdgeInsets padding;
const TextButton({
Key key,
this.onPressed,
this.text = "",
this.color = Colors.black87,
this.fontSize = 14.0,
this.padding = EdgeInsets.zero,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return new Material(
color: Colors.transparent,
child: InkWell(
onTap: onPressed,
child: Padding(
padding: padding,
child: new Text(
text,
style: new TextStyle(fontSize: fontSize, color: color),
),
),
),
);
}
}
複製程式碼
類似於這樣的方案
怎麼設定寬度/高度
外面包一個SizedBox,設定height,Container也可以,還能加padding,背景顏色等
child可以是任意屬性
這樣的,我應該怎麼佈局,那樣的我該怎麼佈局
這樣的問題,通常歸結為不會劃分,總體來說有以下幾點
- 橫向多控制元件,用Row包起來,順序排下去
- 縱向多控制元件,用Column包起來,順序排下去
- 單頁顯示不下的,用ListView,預設縱向,修改scrollDirection屬性,ListView在flutter中就是scrollView
我要給某某控制元件加一個點選事件,沒有onTap,onPressed嗎?
GestureDetector包含了豐富的手勢,包上你的控制元件就好了
GestureDetector(onTap:()=>print('點選點選'),child:Text('點選'));
複製程式碼
這on開頭的屬性全部都是系統定義好的回撥
tap是點選相關,doubleTap是雙擊,longPress長按
VerticalDrag相關是縱向拖動
HorizontalDrag相關是橫向拖動
pan相關是手指移動
scale是雙指縮放手勢
behavior
代表控制元件透明時是否可以響應手勢
圓角怎麼設定,背景圖片怎麼設定
Container控制元件中有decoration
屬性可以設定,要注意的一點是 這個屬性本身和color是互斥的,一旦設定decoration,需要去掉color屬性
BoxDecoration有很多屬性可以用
顏色,圖片,邊框,圓角,陰影,漸變色,形狀
SnackBar 顯示沒有scaffold
Scaffold.of() called with a context that does not contain a Scaffold.
複製程式碼
context層級用錯了
這個是由於flutter層級中 這個context的父佈局沒有Scaffold的原因,大概就是你是直接用的頁面級的context
page -> scaffold -> button
你用了page級的, 所以找不到了
解決方案就是中間套一個builder,用於"轉換"出一個位於scaffold後的context,然後就可以了
page -> scaffold -> Builder ->button
import 'package:flutter/material.dart';
import 'package:kappbar/kappbar.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: MyAppBar(
title: Text('測試'),
elevation: 0.0,
),
body: Container(
child: Builder(
// 這裡套一層
builder: (ctx) => RaisedButton(
onPressed: () => _click(ctx), //把builder給的ctx傳遞給方法
)),
),
);
}
void _click(BuildContext context) {
// 這裡使用傳入的context就好了
Scaffold.of(context).showSnackBar(SnackBar(
content: Text('內容'),
));
}
}
複製程式碼
ListView 套ListView 報錯
這個是因為ListView是會佔滿父佈局的控制元件,你需要給內部的ListView加一個高度/寬度限制,如果外部是縱向,則需要高度,外部是橫向,需要寬度
可以看你的情況,可以使用SizedBox,Container,AspectRatio這樣的控制元件
適配篇
我個人理解的最佳適配方案是當年那套.文字流式,圖片寬高比
原文連結
圖片應該在設計時給定寬高比
文字的話沒特殊要求直接自適應
控制元件彈性的意思,控制元件高度是固定的,然後佔滿螢幕,或者百分比,內部的東西左對齊的左對齊,右對齊的右對齊,剩下的佔滿剩餘區域,或者比例分配
dart相關語法篇
先定義一個類,後面用到
class User {
String name;
void print() {
print(this.name);
}
}
複製程式碼
?. 什麼意思
以下兩種寫法是等效的
void foo(User user) {
user?.print();
}
複製程式碼
void foo(User user) {
if (user != null) {
user.print();
}
}
複製程式碼
??啥意思
以下兩種寫法是等效的
var text = user?.name ?? "預設名字";
複製程式碼
String text;
if (user != null && user.name != null) {
text = user.name;
} else {
text = "預設名字";
}
複製程式碼
??= 啥意思
User create(User user){
var user ??= User();
return user;
}
複製程式碼
User create(User user){
if(user == null){
user = User();
}
return user;
}
複製程式碼
typedef 是啥意思
在dart語言中,函式是一等公民,函式本身也是物件
可以被賦值給變數
舉個栗子
這個是在Hero動畫中用到的final CreateRectTween createRectTween;
檢視下CreateRectTween的定義,會發現有這麼一個寫法typedef Tween<Rect> CreateRectTween(Rect begin, Rect end);
簡單的說: 這個是一個函式型別,名稱是CreateRectTween
,這個函式接收兩個Rect值,返回一個Tween物件
使用的時候就是這樣的
Hero(
createRectTween:(Rect begin,Rect end){
return MaterialRectArcTween(begin:begin,end:end);
}
);
複製程式碼
拆開來寫
CreateRectTween method = (Rect begin,Rect end){
return MaterialRectArcTween(begin:begin,end:end);
};
Hero(
createRectTween:method,
);
複製程式碼
android studio 中 怎麼編輯android專案,沒有程式碼提示,還報錯
這裡需要在一個新視窗中開啟android專案