1
0
mirror of https://github.com/flutter/samples.git synced 2025-11-10 06:48:26 +00:00

Graduating add-to-app (#180)

This commit is contained in:
Andrew Brogdon
2019-12-12 10:45:11 -05:00
committed by GitHub
parent 3c11ff596c
commit 400f305ecd
163 changed files with 0 additions and 0 deletions

41
add_to_app/flutter_module/.gitignore vendored Normal file
View File

@@ -0,0 +1,41 @@
.DS_Store
.dart_tool/
.packages
.pub/
.idea/
.vagrant/
.sconsign.dblite
.svn/
*.swp
profile
DerivedData/
.generated/
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3
xcuserdata
*.moved-aside
*.pyc
*sync/
Icon?
.tags*
build/
.android/
.ios/
.flutter-plugins

View File

@@ -0,0 +1,10 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: 532a8fed41a4f6595965f02f3edf9666ba5ebf44
channel: master
project_type: module

View File

@@ -0,0 +1,10 @@
# flutter_module
An example Flutter module used in the Flutter add-to-app samples.
## Getting Started
For more information, see the Add-to-App guide at
[flutter.dev](https://flutter.dev):
https://github.com/flutter/flutter/wiki/Add-Flutter-to-existing-apps

View File

@@ -0,0 +1,161 @@
// Copyright 2019 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
/// The entrypoint for the flutter module.
void main() {
// This call ensures the Flutter binding has been set up before creating the
// MethodChannel-based model.
WidgetsFlutterBinding.ensureInitialized();
final model = CounterModel();
runApp(
ChangeNotifierProvider.value(
value: model,
child: MyApp(),
),
);
}
/// A simple model that uses a [MethodChannel] as the source of truth for the
/// state of the counter.
///
/// Rather than storing app state data within the Flutter module itself (where
/// the native portions of the app can't access it), this module passes messages
/// back to the containing app whenever it needs to increment or retrieve the
/// value of the counter.
class CounterModel extends ChangeNotifier {
CounterModel() {
_channel.setMethodCallHandler(_handleMessage);
_channel.invokeMethod('requestCounter');
}
final _channel = MethodChannel('dev.flutter.example/counter');
int _count = 0;
int get count => _count;
void increment() {
_channel.invokeMethod('incrementCounter');
}
Future<dynamic> _handleMessage(MethodCall call) async {
if (call.method == 'reportCounter') {
_count = call.arguments as int;
notifyListeners();
}
}
}
/// The "app" displayed by this module.
///
/// It offers two routes, one suitable for displaying as a full screen and
/// another designed to be part of a larger UI.class MyApp extends StatelessWidget {
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Module Title',
routes: {
'/': (context) => FullScreenView(),
'/mini': (context) => Contents(),
},
);
}
}
/// Wraps [Contents] in a Material [Scaffold] so it looks correct when displayed
/// full-screen.
class FullScreenView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Full-screen Flutter'),
),
body: const Contents(showExit: true),
);
}
}
/// The actual content displayed by the module.
///
/// This widget displays info about the state of a counter and how much room (in
/// logical pixels) it's been given. It also offers buttons to increment the
/// counter and (optionally) close the Flutter view.
class Contents extends StatelessWidget {
final bool showExit;
const Contents({this.showExit = false});
@override
Widget build(BuildContext context) {
final mediaInfo = MediaQuery.of(context);
return SizedBox.expand(
child: Stack(
children: [
Positioned.fill(
child: DecoratedBox(
decoration: BoxDecoration(
color: Theme.of(context).scaffoldBackgroundColor,
),
),
),
Positioned.fill(
child: Opacity(
opacity: .25,
child: FittedBox(
fit: BoxFit.cover,
child: FlutterLogo(),
),
),
),
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Window is ${mediaInfo.size.width.toStringAsFixed(1)} x '
'${mediaInfo.size.height.toStringAsFixed(1)}',
style: Theme.of(context).textTheme.headline,
),
SizedBox(height: 16),
Consumer<CounterModel>(
builder: (context, model, child) {
return Text(
'Taps: ${model.count}',
style: Theme.of(context).textTheme.headline,
);
},
),
SizedBox(height: 16),
Consumer<CounterModel>(
builder: (context, model, child) {
return RaisedButton(
onPressed: () => model.increment(),
child: Text('Tap me!'),
);
},
),
if (showExit) ...[
SizedBox(height: 16),
RaisedButton(
onPressed: () => SystemNavigator.pop(),
child: Text('Exit this screen'),
),
],
],
),
),
],
),
);
}
}

View File

@@ -0,0 +1,195 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
archive:
dependency: transitive
description:
name: archive
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.11"
args:
dependency: transitive
description:
name: args
url: "https://pub.dartlang.org"
source: hosted
version: "1.5.2"
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.4.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.5"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.2"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.14.11"
convert:
dependency: transitive
description:
name: convert
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
crypto:
dependency: transitive
description:
name: crypto
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
image:
dependency: transitive
description:
name: image
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.4"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.6"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.8"
path:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.4"
pedantic:
dependency: transitive
description:
name: pedantic
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0+1"
petitparser:
dependency: transitive
description:
name: petitparser
url: "https://pub.dartlang.org"
source: hosted
version: "2.4.0"
provider:
dependency: "direct main"
description:
name: provider
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.0+1"
quiver:
dependency: transitive
description:
name: quiver
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.5"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
source_span:
dependency: transitive
description:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.5.5"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.3"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.5"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.11"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.6"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.8"
xml:
dependency: transitive
description:
name: xml
url: "https://pub.dartlang.org"
source: hosted
version: "3.5.0"
sdks:
dart: ">=2.6.0-dev <3.0.0"

View File

@@ -0,0 +1,30 @@
name: flutter_module
description: An example Flutter module.
version: 1.0.0+1
environment:
sdk: ">=2.6.0-dev <3.0.0"
dependencies:
flutter:
sdk: flutter
provider: ^3.1.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
# This section identifies your Flutter project as a module meant for
# embedding in a native host app. These identifiers should _not_ ordinarily
# be changed after generation - they are used to ensure that the tooling can
# maintain consistency when adding or modifying assets and plugins.
# They also do not have any bearing on your native host application's
# identifiers, which may be completely independent or the same as these.
module:
androidX: true
androidPackage: dev.flutter.example.flutter_module
iosBundleIdentifier: dev.flutter.example.flutterModule

View File

@@ -0,0 +1,34 @@
// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility that Flutter provides. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_module/main.dart';
void main() {
testWidgets('MiniView smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(
MaterialApp(
home: Contents(),
),
);
// Verify that our counter starts at 0.
expect(find.text('Taps: 0'), findsOneWidget);
expect(find.text('Taps: 1'), findsNothing);
// Tap the '+' icon and trigger a frame.
await tester.tap(find.text('Tap me!'));
await tester.pump();
// Verify that our counter has incremented.
expect(find.text('Taps: 0'), findsNothing);
expect(find.text('Taps: 1'), findsOneWidget);
});
}