弹性盒子布局、状态管理、项目搭建

2021-11-21  本文已影响0人  浅墨入画

Stack布局

继续上篇文章弹性盒子布局进行学习,这一篇我们主要是探索Stack层叠布局

Stack层叠样式 与 Positioned配合使用

Stack是多层布局,主轴方向是从内向外。
Positioned小部件有leftrighttopbottom四个属性定位,参数是像素位置。

import 'package:flutter/material.dart';

class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StackDemo();
  }
}

class StackDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.yellow,
      alignment: const Alignment(0, -1),
      child: Stack(
        children: [
          //Positioned 绝对定位
          Positioned(
            child: Container(
              color: Colors.white,
              width: 200,
              height: 200,
              child: const Icon(Icons.add),
            ),
          ),
          Positioned(
            child: Container(
              color: Colors.red,
              width: 100,
              height: 100,
              child: const Icon(Icons.search_off),
            ),
            left: 0,
          ),
          Positioned(
            child: Container(
              color: Colors.blue,
              width: 50,
              height: 50,
              child: const Icon(Icons.search),
              // margin: EdgeInsets.only(right: 20),
            ),
            right: 0,
            // right: 20,
          ),
        ],
      ),
    );
  }
}
运行效果
AspectRatio用来影响父部件宽高

AspectRatio的设置影响的是父布局,当父布局同时有宽度和高度,设置宽高比失效

import 'package:flutter/material.dart';

class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Container(
      color: Colors.yellow,
      width: 300,
      height: 300,
      alignment: const Alignment(0, 0),
      child: Container(
        //属性:child
        color: Colors.blue,
        height: 150,
        child: const AspectRatio(
          aspectRatio: 1 / 1,
        ),
      ),
    );
  }
}
运行效果
import 'package:flutter/material.dart';

class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Container(
      color: Colors.yellow,
      width: 300,
      height: 300,
      alignment: const Alignment(0, 0),
      child: Container(
        //属性:child
        color: Colors.blue,
        height: 150,
        width: 200,
        child: const AspectRatio(
          aspectRatio: 1 / 1,
        ),
      ),
    );
  }
}
运行效果

Flutter的Widget状态管理

flutter中小部件大都是无状态的,如果小部件有变化,就需要改变其状态,下面自定义一个有状态的小部件
StatefulWidget有状态小部件,用于对外提供接口,继承自State用来管理状态;需实现build方法访问数据,数据在state中,通过setState设置/改变数据。
有状态的Widget,需要把渲染逻辑数据逻辑分开,并且保留数据逻辑。

import 'package:flutter/material.dart';

//渲染逻辑,仍然是不可变的!!
class StateManagerDemo extends StatefulWidget {
  @override
  // 创建数据管理对象
  State<StatefulWidget> createState() => _SMDState();
}

//状态管理者,State<StateManagerDemo>表示用于管理StateManagerDemo
//_SMDState表示私有类,只在当前文件内可用
class _SMDState extends State<StateManagerDemo> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        backgroundColor: Colors.grey[100],
        appBar: AppBar(
          title: const Text('StateDemo'),
        ),
        body: Center(
          // Chip气泡小部件
          child: Chip(
            label: Text('$count'),
          ),
        ),
        // 添加悬浮按钮
        floatingActionButton: FloatingActionButton(
          child: const Icon(Icons.add),
          onPressed: () {
            //实时设置count数据,用于页面刷新。调用一次setState相当于调用一次build方法,因为flutter是增量渲染,所以只会执行Text('$count'),效率会很高
            //setState影响的是build方法内所有与count相关的地方,可能会是多个
            setState(() {
              count += 1;
            });
            print("count = $count");
          },
        ),
      ),
    );
  }
}
import 'package:flutter/material.dart';
import 'package:hello_flutter/state_mag_demo.dart';

void main() => runApp(App());

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return StateManagerDemo();
  }
}
运行效果

搭建项目

Flutter基础组件以及用法我们已经学完了,下面我们来搭建一个微信项目,通过这个项目,我们在实战中学习网络多线程

<!-- main.dart文件 -->
import 'package:flutter/material.dart';

void main() {
  runApp(App());
}

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {

  int _currentIndex = 0;

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Container(
      child: Scaffold(
        bottomNavigationBar: BottomNavigationBar(
          //BottomNavigationBarItem 三个的话,默认选中是蓝色,四个的话变成了白色,所以这里要加type属性修改样式
          type: BottomNavigationBarType.fixed,
          //BottomNavigationBarItem 选中颜色修改
          fixedColor: Colors.green,
          //currentIndex 修改选中的BottomNavigationBarItem 默认是0
          currentIndex: _currentIndex,
          items: const [
            BottomNavigationBarItem(icon: Icon(Icons.chat), label: '微信'),
            BottomNavigationBarItem(icon: Icon(Icons.bookmark), label: '通讯录'),
            BottomNavigationBarItem(icon: Icon(Icons.history), label: '发现'),
            BottomNavigationBarItem(icon: Icon(Icons.person_outline), label: '我的'),
          ],
        ),
      ),
    );
  }
}
运行效果
<!-- root_page.dart文件 -->
import 'package:flutter/material.dart';

class RootPage extends StatefulWidget {
  @override
  _RootPageState createState() => _RootPageState();
}

class _RootPageState extends State<RootPage> {
  int _currentIndex = 0;

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Container(
      child: Scaffold(
        bottomNavigationBar: BottomNavigationBar(
          //BottomBar点击事件
          onTap:(index) {
            setState(() {
              _currentIndex = index;
            });
          },

          //BottomNavigationBarItem 三个的话,默认选中是蓝色,四个的话变成了白色,所以这里要加type属性修改样式
          type: BottomNavigationBarType.fixed,
          //BottomNavigationBarItem 选中颜色修改
          fixedColor: Colors.green,
          //currentIndex 修改选中的BottomNavigationBarItem 默认是0
          currentIndex: _currentIndex,
          items: const [
            BottomNavigationBarItem(icon: Icon(Icons.chat), label: '微信'),
            BottomNavigationBarItem(icon: Icon(Icons.bookmark), label: '通讯录'),
            BottomNavigationBarItem(icon: Icon(Icons.history), label: '发现'),
            BottomNavigationBarItem(icon: Icon(Icons.person_outline), label: '我的'),
          ],
        ),
      ),
    );
  }
}

<!-- main.dart文件 -->
import 'package:flutter/material.dart';
import 'package:wechat_demo/root_page.dart';

void main() {
  runApp(App());
}

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      home: RootPage(),
    );
  }
}
运行效果
<!-- chat_page.dart文件 -->
import 'package:flutter/material.dart';

class ChatPage extends StatefulWidget {
  @override
  _ChatPageState createState() => _ChatPageState();
}

class _ChatPageState extends State<ChatPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('微信页面'),
      ),
      body: const Center(
        child: Text('微信页面'),
      ),
    );
  }
}

<!-- friends_page.dart文件 -->
import 'package:flutter/material.dart';

class FriendsPage extends StatefulWidget {
  @override
  _FriendsPageState createState() => _FriendsPageState();
}

class _FriendsPageState extends State<FriendsPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('通讯录'),
      ),
      body: const Center(
        child: Text('通讯录'),
      ),
    );
  }
}

<!-- discover_page.dart文件 -->
import 'package:flutter/material.dart';

class DiscoverPage extends StatefulWidget {
  @override
  _DiscoverPageState createState() => _DiscoverPageState();
}

class _DiscoverPageState extends State<DiscoverPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('发现页面'),
      ),
      body: const Center(
        child: Text('发现页面'),
      ),
    );
  }
}

<!-- mine_page.dart文件 -->
import 'package:flutter/material.dart';

class MinePage extends StatefulWidget {
  @override
  _MinePageState createState() => _MinePageState();
}

class _MinePageState extends State<MinePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('我的页面'),
      ),
      body: const Center(
        child: Text('我的页面'),
      ),
    );
  }
}
import 'package:flutter/material.dart';
import 'package:wechat_demo/chat_page.dart';
import 'package:wechat_demo/discover_page.dart';
import 'package:wechat_demo/friends_page.dart';
import 'package:wechat_demo/mine_page.dart';

class RootPage extends StatefulWidget {
  @override
  _RootPageState createState() => _RootPageState();
}

class _RootPageState extends State<RootPage> {
  int _currentIndex = 0;
  //配置四个页面
  List <Widget> _pages = [ChatPage(), FriendsPage(), DiscoverPage(), MinePage()];
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Container(
      child: Scaffold(
        // 选中BottomBar配置body页面
        body: _pages[_currentIndex],
        bottomNavigationBar: BottomNavigationBar(
          //BottomBar点击事件
          onTap:(index) {
            setState(() {
              _currentIndex = index;
            });
          },

          //BottomNavigationBarItem 三个的话,默认选中是蓝色,四个的话变成了白色,所以这里要加type属性修改样式
          type: BottomNavigationBarType.fixed,
          //BottomNavigationBarItem 选中颜色修改
          fixedColor: Colors.green,
          //currentIndex 修改选中的BottomNavigationBarItem 默认是0
          currentIndex: _currentIndex,
          items: const [
            BottomNavigationBarItem(icon: Icon(Icons.chat), label: '微信'),
            BottomNavigationBarItem(icon: Icon(Icons.bookmark), label: '通讯录'),
            BottomNavigationBarItem(icon: Icon(Icons.history), label: '发现'),
            BottomNavigationBarItem(icon: Icon(Icons.person_outline), label: '我的'),
          ],
        ),
      ),
    );
  }
}
运行效果
水波纹、标题头、选中字体大小属性配置
<!-- main.dart文件 -->
class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    // MaterialApp类似于iOS中 UIApplicationMain
    return MaterialApp(
      // title用于安卓设备 退出后台顶部显示app名称
      title: 'WeChatDemo',
      theme: ThemeData(
        // 去掉水波纹效果
        highlightColor: Color.fromRGBO(1, 0, 0, 0.0),
        splashColor: Color.fromRGBO(1, 0, 0, 0.0),
        // 设置NavigationBar主题色,全局有效
        primarySwatch: Colors.grey,
      ),
      home: RootPage(),
    );
  }
}
<!-- root_page.dart文件 -->
class _RootPageState extends State<RootPage> {
  int _currentIndex = 0;
  //配置四个页面
  List <Widget> _pages = [ChatPage(), FriendsPage(), DiscoverPage(), MinePage()];
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Container(
      child: Scaffold(
        body: _pages[_currentIndex],
        bottomNavigationBar: BottomNavigationBar(
          // 设置BottomBar选中字体大小
          selectedFontSize: 22.0,
运行效果

本地资源文件

这里主要是学习Android的资源配置,下面图中的label用于展示工程名,icon展示项目图标,ic.lanucher不用添加.png后缀

安卓资源配置

Android里面的图片资源没有@2x@3x@4x的概念,安卓里面是mipmap-hdpimipmap-xhdpi等类型。
其中xhdpi等价于iOS中的@2x图片资源,
xxhdpi等价于@3x
xxxhdpi等价于@4x
mdpi等价于@1.5x
hdpi等价于@1.0x
v21等价于@0.75x

安卓图片资源类型
安卓icon图片引用

下面把AppIcon60x60@2x.png资源放入mipmap-xhdpi目录下,注意图片资源不能使用驼峰命名,这里改成了app_icon.png,而且图片资源不能拖入目录,需要复制粘贴到目录

安卓配置图片资源
安卓启动图片引用

安卓启动图片在launch_background.xml文件中配置,需要把<item> <bitmap android:gravity="center" android:src="@mipmap/launch_image" /> </item> 注释放开,推荐把启动图片放入-hdpi目录下,不需要添加.png后缀

安卓启动图片配置
项目图片资源引用
截屏2021-11-21 下午1.00.50.png

注意⚠️:注释放开之后,assets一定要与上面uses-material-design: true左对齐,pubspec.yaml文件对格式要求很严格

image.png
BottomNavigationBarItem(
                // 默认图标
                icon:  Image(
                    height: 20,
                    width: 20,
                    image: AssetImage('images/badge.png')
                ),
                // 选中图标
                activeIcon: Image(
                    height: 20,
                    width: 20,
                    image: AssetImage('images/badgeSelect.png')
                ),
                label: '微信'),
解决 Gradle 卡住问题

那么在首次运行的时候, 你会发现卡在如下的地方了, 原因是GradleMaven仓库在国外......然后你就懂了.

Running Gradle task 'assembleDebug'

解决它比较简单的操作就是镜像, 配置如下:

  1. 修改项目下的build.gradle文件
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/jcenter' }
maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }
image.png
  1. 修改flutter 安装目录中的 flutter.gradle文件
buildscript {
    repositories {
        //google()
        //mavenCentral()
        maven { url 'https://maven.aliyun.com/repository/google' }
        maven { url 'https://maven.aliyun.com/repository/jcenter' }
        maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:4.1.0'
    }
}
上一篇下一篇

猜你喜欢

热点阅读