use the same sample flutter app as ios

pull/2787/head
Matt Boetger 2 months ago
parent 8bee9e4270
commit b6b642c1e2

@ -12,7 +12,6 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import dev.flutter.example.androidView.databinding.AndroidCardBinding
import io.flutter.embedding.android.FlutterView
import io.flutter.plugin.common.MethodChannel
import java.util.*
import kotlin.random.Random
@ -29,12 +28,10 @@ class ListAdapter(context: Context, private val flutterViewEngine: FlutterViewEn
// that the Flutter cells change position when scrolling back.
var previousFlutterCells = TreeSet<Int>();
private val matchParentLayout = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
private val wrapContentLayout = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
private val random = Random.Default
private val flutterView = FlutterView(context)
private val flutterChannel = MethodChannel(flutterViewEngine.engine.dartExecutor, "dev.flutter.example/cell")
private var flutterCell: Cell? = null
/**
@ -77,7 +74,7 @@ class ListAdapter(context: Context, private val flutterViewEngine: FlutterViewEn
// Add the Flutter card and hide the Android card for the cells chosen to be Flutter
// cells.
cell.binding.root.addView(flutterView, matchParentLayout)
cell.binding.root.addView(flutterView, wrapContentLayout)
cell.binding.androidCard.visibility = View.GONE
// Keep track of the cell so we know which one to restore back to the "Android cell"
@ -89,9 +86,6 @@ class ListAdapter(context: Context, private val flutterViewEngine: FlutterViewEn
// This is what makes the Flutter cell start rendering.
flutterViewEngine.attachFlutterView(flutterView)
// Tell Flutter which index it's at so Flutter could show the cell number too in its
// own widget tree.
flutterChannel.invokeMethod("setCellNumber", position)
} else {
// If it's not selected as a Flutter cell, just show the Android card.
cell.binding.androidCard.visibility = View.VISIBLE

@ -45,7 +45,7 @@ class MainActivity : AppCompatActivity() {
engine.dartExecutor.executeDartEntrypoint(
DartExecutor.DartEntrypoint(
FlutterInjector.instance().flutterLoader().findAppBundlePath(),
"showCell"))
"main"))
flutterViewEngine = FlutterViewEngine(engine)
// The activity and FlutterView have different lifecycles.

@ -1,88 +0,0 @@
// 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 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:sensors_plus/sensors_plus.dart';
// This is on alternate entrypoint for this module to display Flutter UI in
// a (multi-)view integration scenario.
void main() {
runApp(const Cell());
}
class Cell extends StatefulWidget {
const Cell({super.key});
@override
State<StatefulWidget> createState() => _CellState();
}
const String text = '''Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum facilisis vel quam nec scelerisque. Nullam leo sapien, ornare blandit dui ac, varius condimentum leo. Vestibulum quis sem vulputate, varius dui nec, malesuada sem. Aliquam tincidunt pretium dolor, quis ullamcorper nunc consequat quis. Donec at dui in ex pharetra pretium. Quisque molestie massa vel tellus scelerisque feugiat. Ut sed consect etur neque.
''';
class _CellState extends State<Cell> with WidgetsBindingObserver {
static const double gravity = 9.81;
static final AccelerometerEvent defaultPosition = AccelerometerEvent(
0,
0,
0,
DateTime.now(),
);
int cellNumber = 0;
Random? _random;
AppLifecycleState? appLifecycleState;
@override
void initState() {
const channel = MethodChannel('dev.flutter.example/cell');
channel.setMethodCallHandler((call) async {
if (call.method == 'setCellNumber') {
setState(() {
cellNumber = call.arguments as int;
_random = Random(cellNumber);
});
}
});
// Keep track of what the current platform lifecycle state is.
WidgetsBinding.instance.addObserver(this);
super.initState();
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
setState(() {
appLifecycleState = state;
});
}
// Show a random bright color.
Color randomLightColor() {
_random ??= Random(cellNumber);
return Color.fromARGB(
255,
_random!.nextInt(50) + 205,
_random!.nextInt(50) + 205,
_random!.nextInt(50) + 205,
);
}
@override
Widget build(BuildContext context) {
return Text(text * ((cellNumber % 4) + 1),
textDirection: TextDirection.ltr,
style: TextStyle(fontSize: 20.0));
}
}

@ -1,180 +1,52 @@
// Copyright 2019 The Flutter team. All rights reserved.
// Copyright 2014 The Flutter Authors. 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';
import 'package:url_launcher/url_launcher.dart' as launcher;
import 'cell.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: const MyApp()));
runApp(const ResizeApp());
}
/// This is on alternate entrypoint for this module to display Flutter UI in
/// a (multi-)view integration scenario.
// This is unfortunately in this file due to
// https://github.com/flutter/flutter/issues/72630.
@pragma("vm:entry-point")
void showCell() {
runApp(const Cell());
}
/// A simple model that uses a [MethodChannel] as the source of truth for the
/// state of a 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<void>('requestCounter');
}
final _channel = const MethodChannel('dev.flutter.example/counter');
int _count = 0;
int get count => _count;
void increment() {
_channel.invokeMethod<void>('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 {
const MyApp({super.key});
class ResizeApp extends StatefulWidget {
const ResizeApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Module Title',
theme: ThemeData(colorSchemeSeed: Colors.blue),
routes: {
'/': (context) => const FullScreenView(),
'/mini': (context) => const Contents(),
},
);
}
State<ResizeApp> createState() => _ResizeAppState();
}
/// Wraps [Contents] in a Material [Scaffold] so it looks correct when displayed
/// full-screen.
class FullScreenView extends StatelessWidget {
const FullScreenView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Full-screen Flutter with plugin')),
body: const Contents(showExit: true),
);
class _ResizeAppState extends State<ResizeApp> {
int _listSize = 1;
void _addToList() {
setState(() {
_listSize++;
});
}
}
/// 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, opening the Flutter documentation via the url_launcher plugin, and
/// (optionally) close the Flutter view.
class Contents extends StatelessWidget {
final bool showExit;
const Contents({this.showExit = false, super.key});
@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,
),
),
),
const 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.headlineSmall,
),
const SizedBox(height: 16),
Consumer<CounterModel>(
builder: (context, model, child) {
return Text(
'Taps: ${model.count}',
style: Theme.of(context).textTheme.headlineSmall,
);
},
),
const SizedBox(height: 16),
Consumer<CounterModel>(
builder: (context, model, child) {
return FilledButton(
onPressed: () => model.increment(),
child: const Text('Tap me!'),
);
},
),
FilledButton(
onPressed: () async {
// Use the url_launcher plugin to open the Flutter docs in
// a browser.
final url = Uri.parse('https://flutter.dev/docs');
if (await launcher.canLaunchUrl(url)) {
await launcher.launchUrl(url);
}
},
child: const Text('Open Flutter Docs'),
),
if (showExit) ...[
const SizedBox(height: 16),
FilledButton(
onPressed: () => SystemNavigator.pop(),
child: const Text('Exit this screen'),
return Center(
heightFactor: 1,
child: Directionality(
textDirection: TextDirection.ltr,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
for (int i = 0; i < _listSize; i++)
Container(color: HSVColor.fromAHSV(1, (10.0 * i), 1, 1).toColor(), height: 50, width: 200,
child: Center(
child: Text(
'Flutter Widget $i',
style: const TextStyle(fontSize: 16, color: Colors.black),
),
],
],
),
),
],
)),
TextButton(
onPressed: _addToList,
child: Text('Listception!'),
)
],
),
),
);
}
}
}
Loading…
Cancel
Save