flutter基礎faq

weixin_33686714發表於2018-09-24

寫在前面

這篇文章的目的是給純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可以是任意屬性

這樣的,我應該怎麼佈局,那樣的我該怎麼佈局

這樣的問題,通常歸結為不會劃分,總體來說有以下幾點

  1. 橫向多控制元件,用Row包起來,順序排下去
  2. 縱向多控制元件,用Column包起來,順序排下去
  3. 單頁顯示不下的,用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專案

相關文章