前言
在掘金上看到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事件监听切换页面路由,更新当前的导航栏下标。
写完代码运行如下: