[Flutter]重构APP(Android And IOS Double Kill)

831 阅读3分钟

前言

在掘金上看到Flutter的推广,而且题主也是个立志成为全栈开发的男人~

还有个主要的原因是公司里Android和IOS开发同一个APP要业务逻辑、UI界面一致还是需要很多沟通成本的。所以就有了学习Flutter的念头。

技术栈

Dart + Flutter

文件目录


效果展示


模块开发

Android应用图标适配

打开Image Assert设计图标格式

 在AndroidManifest.xml中的application节点下添加图标路径:

android:icon="@mipmap/ic_launcher_foreground"
android:roundIcon="@mipmap/ic_launcher_round"

Android应用名称设置

打开Android项目,在AndroidManifest.xml中的application节点下添加以下属性:

android:label="高分说APP"

Android启动页

这里我们使用了一款dart插件flutter_splash_screen,便于设置启动页

在pubspec.yaml添加依赖

dependencies:
  flutter_splash_screen: ^0.1.0

安装插件依赖

flutter packages get

在MainActivity.java配置启动页展示

public class MainActivity extends FlutterActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        SplashScreen.show(this, true); // 添加到这里
        super.onCreate(savedInstanceState);
        GeneratedPluginRegistrant.registerWith(this);
   

配置Android启动页面( 创建app/src/main/res/layout/launch_screen.xml )

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/background_gradient"
    android:orientation="vertical">
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="40dp"
        android:scaleType="center"
        android:src="@mipmap/name" />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_marginVertical="30dp">
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:src="@mipmap/slogan" />
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="bottom"
        android:orientation="vertical">
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:src="@mipmap/logo" />
    </LinearLayout>
</LinearLayout>

设置非全屏模式下状态栏颜色( 创建app/src/main/res/values/colors.xml )

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--非全屏模式下状态栏颜色主体-->
    <color name="primary_dark">#000000</color>
</resources>

设置透明背景(创建app/src/main/res/values/styles.xml)

<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <!--设置透明背景-->
        <item name="android:windowIsTranslucent">true</item>
    </style>
</resources>

启动APP后会展示启动屏,最后在某个时机下关闭启动屏

import 'package:flutter_splash_screen/flutter_splash_screen.dart';
FlutterSplashScreen.hide();是

启动效果展示如下:


底部导航栏TabNavigator

import 'package:flutter/material.dart';
import 'package:gfs_app/page/home_page.dart';
import 'package:gfs_app/page/mall_page.dart';
import 'package:gfs_app/page/task_page.dart';

/// 底部导航栏
class TabNavigator extends StatefulWidget {
  @override
  _TabNavigatorState createState() => _TabNavigatorState();
}

class _TabNavigatorState extends State<TabNavigator> {
  int _currentIndex = 0;
  final _defaultColor = Color(0xFFCCCCCC);
  final _activeColor = Color(0xFF0086FF);
  final PageController _controller = PageController(initialPage: 0);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PageView(
        controller: _controller,
        children: <Widget>[HomePage(), TaskPage(), MallPage()],
        // 禁止左右滑动效果
        physics: NeverScrollableScrollPhysics(),
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _currentIndex,
        // fixed - 显示文字和图标
        type: BottomNavigationBarType.fixed,
        items: [
          _navBarItem('首页', Icons.home, 0),
          _navBarItem('作业', Icons.assignment, 1),
          _navBarItem('商城', Icons.shopping_cart, 2),
        ],
        onTap: _clickNavItem,
      ),
      floatingActionButton: Builder(
        builder: (BuildContext context) {
          return FloatingActionButton(
              child: IconButton(
                  icon: Icon(Icons.call, color: Colors.white)),
              onPressed: null);
        },
      ),
    );
  }
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
  _navBarItem(String title, IconData icon, int index) {
    return BottomNavigationBarItem(
        icon: Icon(icon, color: _defaultColor),
        activeIcon: Icon(icon, color: _activeColor),
        title: Text(title,
            style: TextStyle(
                color: _currentIndex == index ? _activeColor : _defaultColor)));
  }
  /// 点击NavBar事件
  _clickNavItem(int index) {
    setState(() {
      // 更新当前导航栏的下标
      _currentIndex = index;
      // 路由到指定页面
      _controller.jumpToPage(index);
    });
  }
}

项目骨架使用了Material库提供的Scaffold容器Widget,body初始化页面,bottomNavigationBar设置底部导航栏;

body: 路由页面使用PageView实例化HomePage首页、TaskPage作业、MallPage作业三个页面(tip: 动态初始化可使用PageView.builder),并注入PageController控制路由的切换;

bottomNavigationBar: 底部导航栏用BottomNavigationBar实例化,NavBarItem用BottomNavigationBarItem去实例化,通过onTap事件监听切换页面路由,更新当前的导航栏下标。

写完代码运行如下: