Skip to content

Commit ff71d79

Browse files
authored
Merge pull request #1 from app-bootstrap/feat/add-tabbar
feat: add tabbar
2 parents c151a93 + 7a4dd68 commit ff71d79

File tree

19 files changed

+444
-49
lines changed

19 files changed

+444
-49
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
# flutter-app-bootstrap
22

33
---
4+
5+
## Screenshot
6+
7+
<img src="./screenshot/flutter_01.png" width="25%"/><img src="./screenshot/flutter_02.png" width="25%"/><img src="./screenshot/flutter_03.png" width="25%"/><img src="./screenshot/flutter_04.png" width="25%"/>

ios/Flutter/Debug.xcconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
12
#include "Generated.xcconfig"

ios/Flutter/Release.xcconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
12
#include "Generated.xcconfig"

ios/Podfile

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Uncomment this line to define a global platform for your project
2+
# platform :ios, '9.0'
3+
4+
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5+
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6+
7+
project 'Runner', {
8+
'Debug' => :debug,
9+
'Profile' => :release,
10+
'Release' => :release,
11+
}
12+
13+
def parse_KV_file(file, separator='=')
14+
file_abs_path = File.expand_path(file)
15+
if !File.exists? file_abs_path
16+
return [];
17+
end
18+
pods_ary = []
19+
skip_line_start_symbols = ["#", "/"]
20+
File.foreach(file_abs_path) { |line|
21+
next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
22+
plugin = line.split(pattern=separator)
23+
if plugin.length == 2
24+
podname = plugin[0].strip()
25+
path = plugin[1].strip()
26+
podpath = File.expand_path("#{path}", file_abs_path)
27+
pods_ary.push({:name => podname, :path => podpath});
28+
else
29+
puts "Invalid plugin specification: #{line}"
30+
end
31+
}
32+
return pods_ary
33+
end
34+
35+
target 'Runner' do
36+
# Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
37+
# referring to absolute paths on developers' machines.
38+
system('rm -rf .symlinks')
39+
system('mkdir -p .symlinks/plugins')
40+
41+
# Flutter Pods
42+
generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig')
43+
if generated_xcode_build_settings.empty?
44+
puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first."
45+
end
46+
generated_xcode_build_settings.map { |p|
47+
if p[:name] == 'FLUTTER_FRAMEWORK_DIR'
48+
symlink = File.join('.symlinks', 'flutter')
49+
File.symlink(File.dirname(p[:path]), symlink)
50+
pod 'Flutter', :path => File.join(symlink, File.basename(p[:path]))
51+
end
52+
}
53+
54+
# Plugin Pods
55+
plugin_pods = parse_KV_file('../.flutter-plugins')
56+
plugin_pods.map { |p|
57+
symlink = File.join('.symlinks', 'plugins', p[:name])
58+
File.symlink(p[:path], symlink)
59+
pod p[:name], :path => File.join(symlink, 'ios')
60+
}
61+
end
62+
63+
post_install do |installer|
64+
installer.pods_project.targets.each do |target|
65+
target.build_configurations.each do |config|
66+
config.build_settings['ENABLE_BITCODE'] = 'NO'
67+
end
68+
end
69+
end

ios/Runner.xcodeproj/project.pbxproj

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
1313
3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
1414
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
15+
3BEFD63AD901C35F38610CCA /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AE43DE62550FDBB2234ACE65 /* libPods-Runner.a */; };
1516
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
1617
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
1718
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
@@ -55,6 +56,7 @@
5556
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
5657
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
5758
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
59+
AE43DE62550FDBB2234ACE65 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; };
5860
/* End PBXFileReference section */
5961

6062
/* Begin PBXFrameworksBuildPhase section */
@@ -64,12 +66,28 @@
6466
files = (
6567
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
6668
3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
69+
3BEFD63AD901C35F38610CCA /* libPods-Runner.a in Frameworks */,
6770
);
6871
runOnlyForDeploymentPostprocessing = 0;
6972
};
7073
/* End PBXFrameworksBuildPhase section */
7174

7275
/* Begin PBXGroup section */
76+
2CBAC9D7B99EE604AA85B992 /* Pods */ = {
77+
isa = PBXGroup;
78+
children = (
79+
);
80+
name = Pods;
81+
sourceTree = "<group>";
82+
};
83+
7A505596141997A52B835C41 /* Frameworks */ = {
84+
isa = PBXGroup;
85+
children = (
86+
AE43DE62550FDBB2234ACE65 /* libPods-Runner.a */,
87+
);
88+
name = Frameworks;
89+
sourceTree = "<group>";
90+
};
7391
9740EEB11CF90186004384FC /* Flutter */ = {
7492
isa = PBXGroup;
7593
children = (
@@ -90,7 +108,8 @@
90108
9740EEB11CF90186004384FC /* Flutter */,
91109
97C146F01CF9000F007C117D /* Runner */,
92110
97C146EF1CF9000F007C117D /* Products */,
93-
CF3B75C9A7D2FA2A4C99F110 /* Frameworks */,
111+
2CBAC9D7B99EE604AA85B992 /* Pods */,
112+
7A505596141997A52B835C41 /* Frameworks */,
94113
);
95114
sourceTree = "<group>";
96115
};
@@ -133,12 +152,14 @@
133152
isa = PBXNativeTarget;
134153
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
135154
buildPhases = (
155+
B2604DE5BF8C33F8D2ED99DE /* [CP] Check Pods Manifest.lock */,
136156
9740EEB61CF901F6004384FC /* Run Script */,
137157
97C146EA1CF9000F007C117D /* Sources */,
138158
97C146EB1CF9000F007C117D /* Frameworks */,
139159
97C146EC1CF9000F007C117D /* Resources */,
140160
9705A1C41CF9048500538489 /* Embed Frameworks */,
141161
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
162+
10433EC847558DA837CA5C54 /* [CP] Embed Pods Frameworks */,
142163
);
143164
buildRules = (
144165
);
@@ -198,6 +219,28 @@
198219
/* End PBXResourcesBuildPhase section */
199220

200221
/* Begin PBXShellScriptBuildPhase section */
222+
10433EC847558DA837CA5C54 /* [CP] Embed Pods Frameworks */ = {
223+
isa = PBXShellScriptBuildPhase;
224+
buildActionMask = 2147483647;
225+
files = (
226+
);
227+
inputFileListPaths = (
228+
);
229+
inputPaths = (
230+
"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
231+
"${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework",
232+
);
233+
name = "[CP] Embed Pods Frameworks";
234+
outputFileListPaths = (
235+
);
236+
outputPaths = (
237+
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
238+
);
239+
runOnlyForDeploymentPostprocessing = 0;
240+
shellPath = /bin/sh;
241+
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
242+
showEnvVarsInLog = 0;
243+
};
201244
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
202245
isa = PBXShellScriptBuildPhase;
203246
buildActionMask = 2147483647;
@@ -226,6 +269,28 @@
226269
shellPath = /bin/sh;
227270
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
228271
};
272+
B2604DE5BF8C33F8D2ED99DE /* [CP] Check Pods Manifest.lock */ = {
273+
isa = PBXShellScriptBuildPhase;
274+
buildActionMask = 2147483647;
275+
files = (
276+
);
277+
inputFileListPaths = (
278+
);
279+
inputPaths = (
280+
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
281+
"${PODS_ROOT}/Manifest.lock",
282+
);
283+
name = "[CP] Check Pods Manifest.lock";
284+
outputFileListPaths = (
285+
);
286+
outputPaths = (
287+
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
288+
);
289+
runOnlyForDeploymentPostprocessing = 0;
290+
shellPath = /bin/sh;
291+
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
292+
showEnvVarsInLog = 0;
293+
};
229294
/* End PBXShellScriptBuildPhase section */
230295

231296
/* Begin PBXSourcesBuildPhase section */

ios/Runner.xcworkspace/contents.xcworkspacedata

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/component/list.dart

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import 'package:flutter/material.dart';
2+
import 'dart:io' show Platform;
3+
4+
import '../constants.dart' as CONSTANTS;
5+
import '../utils.dart' as Utils;
6+
7+
class ListComponent extends StatelessWidget {
8+
ListComponent({Key key}) : super(key: key);
9+
10+
@override
11+
Widget build(BuildContext context) {
12+
String os = Platform.operatingSystem;
13+
String osString = Platform.isIOS ? '${os[0]}${os.substring(1).toUpperCase()}' : '${os[0].toUpperCase()}${os.substring(1)}';
14+
return new Container(
15+
padding: const EdgeInsets.all(20.0),
16+
child: Column(
17+
mainAxisAlignment: MainAxisAlignment.center,
18+
children: <Widget>[
19+
Text(
20+
'$osString Flutter Bootstrap',
21+
style: new TextStyle(fontSize: 20.0, color: Colors.black),
22+
),
23+
new Container(
24+
width: MediaQuery.of(context).size.width,
25+
margin: const EdgeInsets.only(top: 80.0),
26+
decoration: new BoxDecoration(
27+
color: Color(Utils.getColorHexFromStr(CONSTANTS.COLOR_1)),
28+
borderRadius: new BorderRadius.circular(4.0),
29+
),
30+
child: FlatButton(
31+
child: Text(
32+
'list',
33+
textAlign: TextAlign.center,
34+
style: new TextStyle(
35+
fontSize: 20.0,
36+
color: Color(Utils.getColorHexFromStr('#ffffff'))),
37+
),
38+
onPressed: () {
39+
Navigator.pushNamed(context, '/list');
40+
}))
41+
],
42+
),
43+
);
44+
}
45+
}

lib/component/logout.dart

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import 'package:flutter/material.dart';
2+
import 'dart:io' show Platform;
3+
4+
import '../constants.dart' as CONSTANTS;
5+
import '../utils.dart' as Utils;
6+
7+
class LogoutComponent extends StatelessWidget {
8+
LogoutComponent({Key key}) : super(key: key);
9+
10+
@override
11+
Widget build(BuildContext context) {
12+
String os = Platform.operatingSystem;
13+
String osString = '${os[0].toUpperCase()}${os.substring(1)}';
14+
return new Container(
15+
padding: const EdgeInsets.all(20.0),
16+
child: Column(
17+
mainAxisAlignment: MainAxisAlignment.center,
18+
children: <Widget>[
19+
Text(
20+
'$osString Flutter Bootstrap',
21+
style: new TextStyle(fontSize: 20.0, color: Colors.black),
22+
),
23+
new Container(
24+
width: MediaQuery.of(context).size.width,
25+
margin: const EdgeInsets.only(top: 80.0),
26+
decoration: new BoxDecoration(
27+
color: Color(Utils.getColorHexFromStr(CONSTANTS.COLOR_1)),
28+
borderRadius: new BorderRadius.circular(4.0),
29+
),
30+
child: FlatButton(
31+
child: Text(
32+
'Logout',
33+
textAlign: TextAlign.center,
34+
style: new TextStyle(
35+
fontSize: 20.0,
36+
color: Color(Utils.getColorHexFromStr('#ffffff'))),
37+
),
38+
onPressed: () {
39+
Navigator.pushNamed(context, '/login');
40+
}))
41+
],
42+
),
43+
);
44+
}
45+
}

lib/constants.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const String ENV = "test";
2+
const String TEST = "TEST";
3+
const String HOME = "HOME";
4+
const String PERSONAL = "PERSONAL";
5+
const String TEST_URL = "https://www.baidu.com";
6+
const String TEST_TITLE = "Baidu";
7+
const String WEBVIEW = "Webview";
8+
const String USERNAME_TIPS = "please input username";
9+
const String PASSWORD_TIPS = "please input password";
10+
const String COLOR_1 = "#00bcd4";
11+
const String COLOR_2 = "#ff4081";
12+
const String DATAHUB_HOST = "http://localhost:7001";
13+
const String DATAHUB_HUBNAME_1 = "bootstrap";

lib/main.dart

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
22

33
import 'page/home.dart';
44
import 'page/login.dart';
5+
import 'page/list.dart';
56

67
void main() => runApp(MyApp());
78

@@ -11,21 +12,25 @@ class MyApp extends StatelessWidget {
1112
Widget build(BuildContext context) {
1213
return MaterialApp(
1314
title: 'Flutter Demo',
14-
theme: ThemeData(
15-
primarySwatch: Colors.blue,
16-
),
1715
home: LoginPage(title: 'Home Page'),
16+
debugShowCheckedModeBanner: true,
17+
debugShowMaterialGrid: false,
1818
onGenerateRoute: (RouteSettings settings) {
1919
switch (settings.name) {
2020
case '/home':
2121
return new MyCustomRoute(
22-
builder: (_) => HomePage(title: 'Home Page'),
22+
builder: (_) => HomePage(),
2323
settings: settings,
2424
);
2525

2626
case '/login':
2727
return new MyCustomRoute(
28-
builder: (_) => LoginPage(title: 'Login Page'),
28+
builder: (_) => LoginPage(),
29+
settings: settings,
30+
);
31+
case '/list':
32+
return new MyCustomRoute(
33+
builder: (_) => ListPage(),
2934
settings: settings,
3035
);
3136
}
@@ -44,4 +49,4 @@ class MyCustomRoute<T> extends MaterialPageRoute<T> {
4449
if (settings.isInitialRoute) return child;
4550
return new FadeTransition(opacity: animation, child: child);
4651
}
47-
}
52+
}

0 commit comments

Comments
 (0)