Android開發(fā) 學(xué)習(xí)Flutter 入門

Android開發(fā) 學(xué)習(xí)Flutter 入門

一、前言

最近項(xiàng)目準(zhǔn)備用Flutter混合開發(fā),寫寫學(xué)習(xí)的筆記吧,學(xué)習(xí)Flutter首先需要了解Dart語(yǔ)言,(當(dāng)然安全上網(wǎng)推薦一個(gè)Chrome插件(SetupVpn)),了解Dart相關(guān)語(yǔ)法之后,可以到Flutter中文網(wǎng)學(xué)習(xí)Flutter啦。

二、Flutter 環(huán)境搭建

Flutter中文網(wǎng)有詳細(xì)的教程,我在Mac和Windows上都已經(jīng)成功安裝。

  • Flutter SDK 獲取
    去flutter官網(wǎng)下載其最新可用的安裝包,轉(zhuǎn)到下載頁(yè) 。下載后將其解壓,當(dāng)前目錄將為環(huán)境變量需要配置的。

    image.png

  • mac 環(huán)境變量設(shè)置:

alias br="flutter packages pub run build_runner build" # br 快捷鍵
alias rmlock="rm -rf /Users/ningzhen942/app/flutter/bin/chche/lockfile" #刪除lockfile 快捷鍵
export PATH=/Users/ningzhen942/app/flutter/bin:$PATH
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
image.png
  • 配置好環(huán)境變量 運(yùn)行flutter --version 查看版本


    image.png
  • 運(yùn)行 flutter doctor 查看環(huán)境狀態(tài)


    image.png

三、Flutter 工程目錄結(jié)構(gòu)

四、Flutter Widget 與Android 控件聯(lián)想

image.png

五、Demo(ListView)

168336246614882_result.gif
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:vscodeflutter/home.dart';
import 'package:vscodeflutter/muti_phote_page.dart';
import 'package:vscodeflutter/phote_view_page.dart';
import 'package:vscodeflutter/widght/gradient_text.dart';
import 'package:cached_network_image/cached_network_image.dart';

void main() {
  runApp(new MyApp(
    items: new List<ListItem>.generate(1000, (i) {
      if (i % 8 == 0) {
        return new HeadingItem("Heading I am No.$i");
      } else if (i % 8 == 1) {
        return new ImageItem(
            "https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2572170802,3058063046&fm=26&gp=0.jpg",
            "Message body $i");
      } else if (i % 8 == 2) {
        List<String> urls = new List<String>.generate(8, (i) {
          return "https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3806557979,3233516071&fm=27&gp=0.jpg";
        });
        return new ListImageItem(urls, "多圖片瀏覽");
      } else {
        return new MessageItem("Sender $i", "Message body $i");
      }
    }),
  ));
}

class MyApp extends StatelessWidget {
  final List<ListItem> items;

  MyApp({Key key, @required this.items}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final title = 'Flutter List';

    return new MaterialApp(
      title: title,
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text(title),
          backgroundColor: Colors.green,
        ),
        body: new ListView.builder(
          // Let the ListView know how many items it needs to build
          itemCount: items.length,
          // Provide a builder function. This is where the magic happens! We'll
          // convert each item into a Widget based on the type of item it is.
          itemBuilder: (context, index) {
            final item = items[index];
            if (item is HeadingItem) {
              return getTitleItem(item, context);
            } else if (item is MessageItem) {
              return new ListTile(
                title: new Text(item.sender),
                subtitle: new Text(item.body),
              );
            } else if (item is ImageItem) {
              return getImageItem(item, context);
            } else if (item is ListImageItem) {
              return new Container(
                  height: 220,
                  width: double.infinity,
                  padding: EdgeInsets.fromLTRB(10, 10, 0, 10),
                  child: ListView.builder(
                    itemBuilder: (context, index) {
                      return getListItem(context, item, index);
                    },
                    itemCount: item.urls.length,
                    scrollDirection: Axis.horizontal,
                  ));
            }
          },
        ),
      ),
    );
  }

  ListTile getTitleItem(HeadingItem item, BuildContext context) {
    return new ListTile(
        title: new GestureDetector(
      child: new GradientText(
        item.heading,
        textAlign: TextAlign.left,
        gradient: LinearGradient(colors: [Colors.redAccent, Colors.green]),
        style: TextStyle(
          fontSize: 30.0,
        ),
      ),
      onTap: () {
        Navigator.push(
          context,
          new MaterialPageRoute(builder: (context) => new HomePage()),
        );
      },
    ));
  }

  Widget getImageItem(ImageItem item, BuildContext context) {
    return new Container(
      height: 100,
      margin: EdgeInsets.only(left: 10),
      child: Stack(
        children: <Widget>[
          new GestureDetector(
            /*child: ClipRRect(
              borderRadius: BorderRadius.circular(10),
              child: new CachedNetworkImage(
                imageUrl: item.url,
                height: 100,
              ),
            ),*/
            child: new ClipOval(
              child: new CachedNetworkImage(
                imageUrl: item.url,
                height: 100,
              ),
            ),
            onTap: () {
              Navigator.push(
                  context,
                  new MaterialPageRoute(
                      builder: (context) => new PhoteViewPage(item.url)));
            },
          ),
        ],
      ),
    );
  }

  Container getListItem(BuildContext context, ListImageItem item, int index) {
    return new Container(
        width: 220,
        height: 220,
        padding: new EdgeInsets.only(right: 10),
        child: GestureDetector(
          onTap: () {
            Navigator.push(
                context,
                new MaterialPageRoute(
                    builder: (context) => new MutiPhotePage(item.urls, index)));
          },
          child: ClipRRect(
            borderRadius: BorderRadius.circular(6),
            child: new CachedNetworkImage(
              imageUrl: item.urls[index],
              fit: BoxFit.cover,
              placeholder: (context, url) => new CircularProgressIndicator(),
              errorWidget: (context, url, error) => new Icon(Icons.error),
            ),
          ),
        ));
  }
}

// The base class for the different types of items the List can contain
abstract class ListItem {}

// A ListItem that contains data to display a heading
class HeadingItem implements ListItem {
  final String heading;

  HeadingItem(this.heading);
}

// A ListItem that contains data to display a message
class MessageItem implements ListItem {
  final String sender;
  final String body;

  MessageItem(this.sender, this.body);
}

// A ListItem that contains data to display a message
class ImageItem implements ListItem {
  final String url;
  final String title;

  ImageItem(this.url, this.title);
}

// A ListItem that contains data to display a message
class ListImageItem implements ListItem {
  final List<String> urls;
  final String title;

  ListImageItem(this.urls, this.title);
}

六、Demo直接貼代碼(圖片瀏覽放大)

  • 首先在pubspec.yaml引用phote_view 和網(wǎng)絡(luò)圖片加載庫(kù)


    image.png
  #https://github.com/renefloor/flutter_cached_network_image
  cached_network_image: ^0.7.0

  #https://github.com/renancaraujo/photo_view
  photo_view: ^0.2.2
import 'package:flutter/material.dart';
import 'package:photo_view/photo_view.dart';
import 'package:cached_network_image/cached_network_image.dart';
// ignore: must_be_immutable
class PhoteViewPage extends StatefulWidget {

  String url;


  PhoteViewPage(this.url);

  @override
  PhoteViewPageState createState() => new PhoteViewPageState(this.url);
}

class PhoteViewPageState extends State<PhoteViewPage> {

  String url;


  PhoteViewPageState(this.url);

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('圖片瀏覽'),
        backgroundColor: Colors.green,
      ),
      body: new Container(
        color: Colors.white,
        child: PhotoView(imageProvider: new CachedNetworkImageProvider(url),
           backgroundDecoration: new BoxDecoration(color: Colors.white),
        ),
      ),
    );
  }
  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  void didUpdateWidget(PhoteViewPage oldWidget) {
    super.didUpdateWidget(oldWidget);
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
  }
}

七、多圖片瀏覽

使用TabbarView 與PhoteView 實(shí)現(xiàn)多圖片的瀏覽

import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:photo_view/photo_view.dart';

class MutiPhotePage extends StatefulWidget {
  List<String> urls;

  int postion;

  MutiPhotePage(this.urls, this.postion);

  @override
  MutiPhotePageState createState() => new MutiPhotePageState(urls, postion);
}

class MutiPhotePageState extends State<MutiPhotePage> with SingleTickerProviderStateMixin{
  List<String> urls;

  int postion;

  TabController tabController;

  MutiPhotePageState(this.urls, this.postion);

  List<Widget> getTabView() {
    return urls.map((url) {
      return new Container(
        child: PhotoView(
          imageProvider: new CachedNetworkImageProvider(url),
          backgroundDecoration: new BoxDecoration(color: Colors.white),
        ),
      );
    }).toList(growable: true);
  }

  @override
  void initState() {
    super.initState();
    this.tabController =
        new TabController(length: urls.length, initialIndex: postion,vsync: this);
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  void didUpdateWidget(MutiPhotePage oldWidget) {
    super.didUpdateWidget(oldWidget);
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("查看多張圖片"),
        backgroundColor: Colors.green,
      ),
      body: new Container(
        child: new TabBarView(
          children: getTabView(),
          controller: tabController,
        ),
      ),
    );
  }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 表單 一、 表單的基本應(yīng)用 (一) 表單典型的應(yīng)用場(chǎng)景 1. 登錄、注冊(cè) 2. 網(wǎng)上訂單 3. 調(diào)查問(wèn)卷 4. 網(wǎng)...
    拾起_518閱讀 281評(píng)論 0 0
  • 第一次打比較正式的比賽,也看到了自己有多么菜。 Web easy_parse 考察prase_str()變量覆蓋漏...
    NoelleMu閱讀 1,612評(píng)論 0 0
  • 抖音的產(chǎn)品分析 概述 本文嘗試通過(guò)結(jié)合整個(gè)文娛和短視頻行業(yè)的發(fā)展,將抖音產(chǎn)品本身的結(jié)構(gòu)和特色置于行業(yè)環(huán)境中,分析抖...
    青尼羅河閱讀 1,434評(píng)論 0 1
  • 距離上次暈倒已經(jīng)好久了。暈倒的原因也是很有特色,比如食物中毒,比如泡溫泉,再比如跑步。 想來(lái)自己也是一直在強(qiáng)壯邊緣...
    姑娘玉秋閱讀 303評(píng)論 2 0

友情鏈接更多精彩內(nèi)容