flutter学习集合

文章集合

showDialog(
  context: context,
  builder: (BuildContext context) {
    return AlertDialog(
      title: new Text('你确定要这样做吗?'),
      actions: <Widget>[
        new FlatButton(
          child: new Text('取消'),
          onPressed: () {
            Navigator.of(context).pop();   // 取消返回
            print('取消');
          },
        ),
        new FlatButton(
          child: new Text('确定'),
          onPressed: () {
            Navigator.of(context).pop();
            print('确定');
          },
        )
      ],
    );
  }
);
// vertical-font.dart
import 'package:ZyFlutter/utils/hex_color.dart';
import 'package:flutter/material.dart';

class VerticalFont extends StatelessWidget {
  // 标题
  final String title;
  // 字体大小
  final double fontSize;
  // 字体颜色
  final String color;
  VerticalFont({this.title, this.fontSize = 20.0, this.color = '#000000'});
  @override
  Widget build(BuildContext context) {
    return RotatedBox(
      quarterTurns: 1,
      child: RichText(
        text: TextSpan(
            text: title,
            style: TextStyle(
                fontFamily: 'mn',
                fontSize: this.fontSize,
                color: HexColor(color))),
      ),
    );
  }
}


  • flutter顶部tabs创建(方式一,在title上创建)
    • 使用StatefulWidget和自行构造TabController实现
/*
 * @Description: 
 * @version: 
 * @Author: 周凯
 * @Date: 2020-06-16 21:38:15
 * @LastEditors: 周凯
 * @LastEditTime: 2020-07-25 19:27:49
 */
// 下面代码将TabBar放到了AppBar的title上。
import 'package:flutter/material.dart';

/// 短视屏页面
class ShortVideo extends StatefulWidget {
  @override
  _ShortVideoState createState() => _ShortVideoState();
}

class _ShortVideoState extends State<ShortVideo>
    with SingleTickerProviderStateMixin {
  TabController tabController;

  @override
  void initState() {
    super.initState();

    tabController = TabController(length: 2, vsync: this);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: TabBar(
          tabs: [
            Tab(
              icon: Icon(Icons.directions_car),
              text: "短视频",
            ),
            Tab(
              icon: Icon(Icons.directions_bike),
              text: "其他",
            ),
          ],
          controller: tabController,
        ),
      ),
      body: TabBarView(
        children: [
          Center(child: Text('汽车')),
          Center(child: Text('自行车')),
        ],
        controller: tabController,
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    tabController.dispose();
  }
}
  • flutter顶部tabs创建(方式二)
    • 使用DefaultTabController来实现简单的tab效果:
class TopTabPage1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 3,
      child: Scaffold(
        appBar: AppBar(
          title: Text('交通工具'),
          bottom: TabBar(tabs: [
            Tab(
              icon: Icon(Icons.directions_car),
              text: "汽车",
            ),
            Tab(
              icon: Icon(Icons.directions_bike),
              text: "自行车",
            ),
            Tab(
              icon: Icon(Icons.directions_boat),
              text: '轮船',
            ),
          ]),
        ),
        body: TabBarView(children: [
          Center(child: Text('汽车')),
          Center(child: Text('自行车')),
          Center(child: Text('轮船')),
        ]),
      ),
    );
  }
}
/*
 * @Description: 
 * @version: 
 * @Author: 周凯
 * @Date: 2020-06-16 21:38:15
 * @LastEditors: 周凯
 * @LastEditTime: 2020-07-26 15:32:50
 */
import 'dart:async';

import 'package:ZyFlutter/pages/home/live_video_list.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart'
    as extended;

/// NestedScrollView示例页面
class NestedScrollViewPage extends StatefulWidget {
  @override
  NestedScrollViewPageState createState() {
    return NestedScrollViewPageState();
  }
}

class NestedScrollViewPageState extends State<NestedScrollViewPage>
    with SingleTickerProviderStateMixin {
  // 滚动控制器
  ScrollController _scrollController;
  // Tab控制器
  TabController _tabController;
  int _tabIndex = 0;
  // 列表
  int _listCount = 20;
  // 表格
  int _gridCount = 30;

  // 初始化
  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: 2, vsync: this);
    _scrollController = ScrollController();
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: extended.NestedScrollView(
        pinnedHeaderSliverHeightBuilder: () {
          return MediaQuery.of(context).padding.top + kToolbarHeight;
        },
        innerScrollPositionKeyBuilder: () {
          if (_tabController.index == 0) {
            return Key('Tab0');
          } else {
            return Key('Tab1');
          }
        },
        headerSliverBuilder: (context, innerBoxIsScrolled) {
          return <Widget>[
            new SliverAppBar(
              title: new PreferredSize(
                child: new Card(
                  color: Theme.of(context).primaryColor,
                  elevation: 0.0,
                  margin: new EdgeInsets.all(0.0),
                  shape: new RoundedRectangleBorder(
                    borderRadius: BorderRadius.all(Radius.circular(0.0)),
                  ),
                  child: new TabBar(
                    controller: _tabController,
                    onTap: (index) {
                      setState(() {
                        _tabIndex = index;
                      });
                    },
                    tabs: <Widget>[
                      new Tab(
                        text: '短视频',
                      ),
                      new Tab(
                        text: '直播',
                      ),
                    ],
                  ),
                ),
                preferredSize: new Size(double.infinity, 46.0),
              ),
            ),
          ];
        },
        body: IndexedStack(
          index: _tabIndex,
          children: <Widget>[
            extended.NestedScrollViewInnerScrollPositionKeyWidget(
              Key('Tab0'),
              EasyRefresh(
                child: ListView.builder(
                  padding: EdgeInsets.all(0.0),
                  itemBuilder: (context, index) {
                    return SampleListItem();
                  },
                  itemCount: _listCount,
                ),
                onRefresh: () async {
                  await Future.delayed(Duration(seconds: 2), () {
                    if (mounted) {
                      setState(() {
                        _listCount = 20;
                      });
                    }
                  });
                },
                onLoad: () async {
                  await Future.delayed(Duration(seconds: 2), () {
                    if (mounted) {
                      setState(() {
                        _listCount += 10;
                      });
                    }
                  });
                },
              ),
            ),
            extended.NestedScrollViewInnerScrollPositionKeyWidget(
              Key('Tab1'),
              EasyRefresh(
                child: GridView.builder(
                  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                    crossAxisCount: 2,
                    childAspectRatio: 6 / 7,
                  ),
                  itemBuilder: (context, index) {
                    return SampleListItem(
                      direction: Axis.horizontal,
                    );
                  },
                  itemCount: _gridCount,
                ),
                onRefresh: () async {
                  await Future.delayed(Duration(seconds: 2), () {
                    if (mounted) {
                      setState(() {
                        _gridCount = 30;
                      });
                    }
                  });
                },
                onLoad: () async {
                  await Future.delayed(Duration(seconds: 2), () {
                    if (mounted) {
                      setState(() {
                        _gridCount += 10;
                      });
                    }
                  });
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}
//pages/home/live_video_list.dart
import 'package:flutter/material.dart';
import 'package:ZyFlutter/utils/hex_color.dart';
import 'package:ZyFlutter/routes/application.dart';

/// 简单列表项
class SampleListItem extends StatelessWidget {
  /// 方向
  final Axis direction;

  /// 宽度
  final double width;

  /// 右侧颜色
  // 红色
  final String defaultRightRed = '#00FF3A';
  // 绿色
  final String defaultRightGreen = '#00FF3A';
  // 蓝色
  final String defaultRightBlue = '#0008FF';

  const SampleListItem(
      {Key key, this.direction = Axis.vertical, this.width = double.infinity})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        _goToDetails(context);
      },
      child: Container(
        padding: EdgeInsets.only(top: 10.0, right: 10.0, bottom: 0, left: 10.0),
        height: 112.0,
        color: Theme.of(context).backgroundColor,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Expanded(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
                  Row(children: <Widget>[
                    // 左侧价钱
                    topText('%3', Theme.of(context).textSelectionColor,
                        Theme.of(context).backgroundColor, 14.0, 0, 14.0, 0),
                    // 左侧清晰度
                    topText('HD', Theme.of(context).textSelectionColor,
                        Theme.of(context).backgroundColor, 2, 0, 2, 0, 10.0)
                  ]),
                  // 右侧
                  topText('测试123123', HexColor(defaultRightBlue),
                      HexColor('#ffffff'), 14.0, 0, 14.0, 0),
                ],
              ),
            ),
            Text(
              '直播播放标题---------------------------------',
              textAlign: TextAlign.start,
              style: TextStyle(color: HexColor('#ffffff')),
            ),
            Container(
              width: double.infinity,
              margin: EdgeInsets.only(top: 8.0),
              padding: EdgeInsets.only(bottom: 8.0),
              decoration: BoxDecoration(
                border: Border(
                  bottom: BorderSide(color: HexColor('#222222'), width: 1.0),
                ),
              ),
              child: Text(
                '2020/05/16 10:00 - 05/18 12:00',
                style: TextStyle(
                  color: HexColor('#ffffff'),
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

/// 跳转详情页面
void _goToDetails(BuildContext context) {
  Application.router.navigateTo(context, '/detail?id=3');
}

/// 列表顶部小部件
Widget topText(String title, Color boxcolor, Color textColor, double left,
    double top, double right, double bottom,
    [double marginLeft = 0]) {
  return Container(
    decoration: BoxDecoration(
      color: boxcolor,
      borderRadius: BorderRadius.all(Radius.circular(2.0)),
    ),
    margin: EdgeInsets.only(left: marginLeft),
    padding:
        EdgeInsets.only(left: left, top: top, right: right, bottom: bottom),
    child: Text(
      title,
      style: TextStyle(
        color: textColor,
      ),
    ),
  );
}
  • flutter使用dio网络库请求 异常跳转路由 获取context
    • main.dart 添加全局的key
    • 原文: 地址
// main.dar
final GlobalKey<NavigatorState> navigatorKey = new GlobalKey<NavigatorState>();

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 路由注入全局使用
    final router = Router();
    Routes.configureRoutes(router);
    Application.router = router;
    // 结束
    return Container(
      child: FlutterEasyLoading(
        child: MaterialApp(
          debugShowCheckedModeBanner: false,
          title: '测试app',
          // 添加的全局key
          navigatorKey: navigatorKey,
        ),
      ),
    );
  }
}

// 路由跳转
navigatorKey.currentState.pushNamed('/login');
  • flutter实现沉浸式导航
### 我们只需要在生命周期 initState()或者其他的钩子中调用下面的 方法即可
/// 状态栏样式 沉浸式状态栏
  _statusBar([String color]) {
    // 白色沉浸式状态栏颜色  白色文字
    SystemUiOverlayStyle light = SystemUiOverlayStyle(
      systemNavigationBarColor: Color(0xFF000000),
      systemNavigationBarDividerColor: null,
      /// 注意安卓要想实现沉浸式的状态栏 需要底部设置透明色
      statusBarColor: Colors.transparent,
      systemNavigationBarIconBrightness: Brightness.light,
      statusBarIconBrightness: Brightness.light,
      statusBarBrightness: Brightness.dark,
    );

 // 黑色沉浸式状态栏颜色 黑色文字
    SystemUiOverlayStyle dark = SystemUiOverlayStyle(
      systemNavigationBarColor: Color(0xFF000000),
      systemNavigationBarDividerColor: null,
      /// 注意安卓要想实现沉浸式的状态栏 需要底部设置透明色
      statusBarColor: Colors.transparent,
      systemNavigationBarIconBrightness: Brightness.light,
      statusBarIconBrightness: Brightness.dark,
      statusBarBrightness: Brightness.light,
    );
// 这个地方你可以去掉三目运算符 直接调用你想要的 效果即可
    "while" == color?.trim()
        ? SystemChrome.setSystemUIOverlayStyle(light)
        : SystemChrome.setSystemUIOverlayStyle(dark);
  }

flutter报错整合

  • flutter运行报错
FAILURE: Build failed with an exception.                                
                                                                        
* What went wrong:                                                      
Could not determine the dependencies of task ':app:compileDebugJavaWithJavac'.
> Could not resolve all task dependencies for configuration ':app:debugCompileClasspath'.
   > Could not resolve io.flutter:flutter_embedding_debug:1.0.0-540786dd51f112885a89792d678296b95e6622e5.
     Required by:                                                       
         project :app                                                   
      > Skipped due to earlier error                                    
      > Skipped due to earlier error                                    
      > Skipped due to earlier error                                    
      > Skipped due to earlier error                                    
   > Could not resolve io.flutter:x86_debug:1.0.0-540786dd51f112885a89792d678296b95e6622e5.
     Required by:                                                       
         project :app                                                   
      > Skipped due to earlier error                                    
      > Skipped due to earlier error                                    
      > Skipped due to earlier error                                    
      > Skipped due to earlier error                                    
   > Could not resolve io.flutter:x86_64_debug:1.0.0-540786dd51f112885a89792d678296b95e6622e5.
     Required by:                                                       
         project :app                                                   
      > Skipped due to earlier error                                    
      > Skipped due to earlier error                                    
      > Skipped due to earlier error                                    
      > Skipped due to earlier error                                    
                                                                        
* Try:                                                                  
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
                                                                        
* Get more help at https://help.gradle.org                              
                                                                        
BUILD FAILED in 1m 48s 
- 解决方案:[地址](https://www.jianshu.com/p/93d06d1bbf37) 
  • flutter 打包release网络请求无法使用
  • 解决方案: 我第一次也是加到android/src/profile/AndroidManifest.xml不生效 真机上图片都加载不出来,查看应用信息显示没有申请任何权限,
    稍后看了一下,和profile同级的main目录下还有一个AndroidManifest.xml文件,即android/src/main/AndroidManifest.xml使用权限申请配置放到这里 打包再次安装 就可以访问网路了。
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
  • 使用flutter_ijkplayer插件打包release闪退
    • 解决方案: 在 proguard 文件加入下面内容,参考地址: 地址
-keep class tv.danmaku.ijk.media.player.** {*;}
flutter_bugly和open_file使用lib冲突
  • open_file readme 地址
  • 解决方案: 在 /android/app/src/main/AndroidManifest.xml添加
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"   // 添加+++
          package="xxx.xxx.xxxxx">
    <application>
        ...
        // 添加+++
        <provider
                android:name="androidx.core.content.FileProvider"
                android:authorities="${applicationId}.fileProvider"
                android:exported="false"
                android:grantUriPermissions="true"
                tools:replace="android:authorities">
            <meta-data
                    android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/filepaths"
                    tools:replace="android:resource" />
        </provider>
        // 结束+++
    </application>
</manifest>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值