import 'dart:ui';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: TabBarPage(),
);
}
}
class TabBarPage extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return TabBarPageState();
}
}
class TabBarPageState extends State<TabBarPage> with SingleTickerProviderStateMixin {
TabController _tabController; //需要定义一个Controller
List tabs = ["page 1", "page 2", "page 3", "page 4", "page 5", "page 6"];
#override
void initState() {
super.initState();
print("TabBarPageState initState");
_tabController = TabController(length: tabs.length, vsync: this);
}
#override
void dispose() {
super.dispose();
print("TabBarPageState dispose");
}
#override
Widget build(BuildContext context) {
print("TabBarPageState build");
return Scaffold(
body: TabBarView(
controller: _tabController,
children: getChildWidgets(),
),
bottomNavigationBar: TabBar(
controller: _tabController,
tabs: tabs.map((item) {
return Container(color: Colors.black,child: Text(item, style: TextStyle(color: Colors.white),),);
}).toList(),
),
);
}
List<Widget> getChildWidgets() {
return List<Widget>()..addAll([PageWidget("page 1", Colors.red), PageWidget("page 2", Colors.yellow), PageWidget("page 3", Colors.blue),
PageWidget("page 4", Colors.green), PageWidget("page 5", Colors.deepPurpleAccent), PageWidget("page 6", Colors.tealAccent), ]);
}
}
class PageWidget extends StatefulWidget {
final String title;
final Color bgColor;
PageWidget(this.title, this.bgColor);
#override
_PageWidgetState createState() => _PageWidgetState();
}
class _PageWidgetState extends State<PageWidget> with AutomaticKeepAliveClientMixin{
#override
void initState() {
super.initState();
print("_PageWidgetState initState ${widget.title}");
}
#override
void dispose() {
super.dispose();
print("_PageWidgetState dispose ${widget.title}");
}
#override
Widget build(BuildContext context) {
print("_PageWidgetState build ${widget.title}");
super.build(context);
return Center(
child: Container(
width: double.infinity,
height: double.infinity,
color: widget.bgColor,
child: "page 2" != widget.title ? Text(widget.title) : RawMaterialButton(child: Text(widget.title), onPressed: (){ Navigator.of(context).push(MaterialPageRoute(builder: (context)=>SecondPageWidget("测试", Colors.deepOrangeAccent)));},),
),
);
}
#override
bool get wantKeepAlive => true;
}
class SecondPageWidget extends StatefulWidget {
final String title;
final Color bgColor;
SecondPageWidget(this.title, this.bgColor);
#override
_SecondPageWidgetState createState() => _SecondPageWidgetState();
}
class _SecondPageWidgetState extends State<SecondPageWidget> {
#override
Widget build(BuildContext context) {
print("SecondPageWidget ${widget.title} build");
return Center(
child: Container(
width: double.infinity,
height: double.infinity,
color: widget.bgColor,
child: Text(widget.title),
),
);
}
}
A very simple test, click on the tab on the bottomNavigationBar to switch the page in TabBarView, but it cannot reach 60FPS from the devTools, and the time-consuming is mainly reflected in the SkCanvas::Flush operation on the Raster thread 。
Can you please tell me how to optimize the speed ?
Jump from page 1 to page 2, whether it has a lot to do with RawMaterialButton, then how to optimize ?
Target Platform: android
Target OS version/browser: android 9
Devices: Redmi Note 5
D:\Users\yl4111>flutter doctor
Running "flutter pub get" in flutter_tools... 17.1s
Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 2.2.3, on Microsoft Windows [Version 10.0.18362.30], locale zh-CN)
[√] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[√] Chrome - develop for the web
[√] Android Studio (version 4.1.0)
[√] Connected device (2 available)
Related
With the new version of Flutter, I'm trying to integrate a TopBar menu with submenus that appears when the mouse hover the button.
But I can't let it display when the mouse hover the submenus.
Can you help me please ?
Flutter 3.7.0 • channel stable • https://github.com/flutter/flutter.git
Framework • revision b06b8b2710 (3 days ago) • 2023-01-23 16:55:55 -0800
Engine • revision b24591ed32
Tools • Dart 2.19.0 • DevTools 2.20.1
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() => runApp(const MenuBarApp());
class MyMenuBar extends StatefulWidget implements PreferredSizeWidget {
const MyMenuBar({super.key});
#override
State<MyMenuBar> createState() => _MyMenuBarState();
#override
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
}
class _MyMenuBarState extends State<MyMenuBar> {
final MenuController _menuController = MenuController();
#override
void initState() {
// TODO: implement initState
super.initState();
}
#override
Widget build(BuildContext context) {
return Row(
children: [
MenuAnchor(
controller: _menuController,
style: const MenuStyle(
backgroundColor: MaterialStatePropertyAll<Color>(Colors.black),
padding:
MaterialStatePropertyAll<EdgeInsets>(EdgeInsets.all(8))),
menuChildren: _getMenus(),
builder: (context, controller, child) {
return TextButton(
child: Text("Home"),
onPressed: () {},
onHover: (_) {
if (controller.isOpen) {
Future.delayed(const Duration(milliseconds: 200),
() {
controller.close();
});
} else {
controller.open();
}
});
},
),
],
);
}
List<Widget> _getMenus() {
return [
MenuItemButton(
onHover: (_) {
_menuController.open();
},
child: TextButton(
onPressed: () {},
child: const Text(
"About",
textAlign: TextAlign.left,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 16, fontWeight: FontWeight.w500, color: Colors.white),
),
),
)
];
}
}
class MenuBarApp extends StatelessWidget {
const MenuBarApp({super.key});
#override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(appBar: MyMenuBar()),
);
}
}
What I have been able to do now
You can use MouseRegion to achieve hover effect.
https://api.flutter.dev/flutter/widgets/MouseRegion-class.html
I have the following sample application:
import 'package:flutter/material.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
const title = 'WebSocket Demo';
return const MaterialApp(
title: title,
home: MyHomePage(
title: title,
),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({
super.key,
required this.title,
});
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final TextEditingController _controller = TextEditingController();
late final WebSocketChannel _channel;
#override
void initState() {
_channel = WebSocketChannel.connect(
Uri.parse('wss://ws.postman-echo.com/raw'),
);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Form(
child: TextFormField(
controller: _controller,
decoration: const InputDecoration(labelText: 'Send a message'),
),
),
const SizedBox(height: 24),
StreamBuilder(
stream: _channel.stream,
builder: (context, snapshot) {
return Text(snapshot.hasData ? '${snapshot.data}' : '');
},
)
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _sendMessage,
tooltip: 'Send message',
child: const Icon(Icons.send),
);
}
void _sendMessage() {
if (_controller.text.isNotEmpty) {
_channel.sink.add(_controller.text);
}
}
#override
void dispose() {
_channel.sink.close();
_controller.dispose();
super.dispose();
}
}
everything works fine when run on iOS simulator, in Android emulator and in Chrome. However, same code run as MacOS app doesn't work!
Do I have to change anything in the configuration of the desktop app? Anything in plist.info? Runner Workspace? Anywhere else?
Here is my flutter configuration:
[✓] Flutter (Channel stable, 3.3.3, on macOS 12.6 21G115 darwin-arm, locale de-DE)
[✓] Android toolchain - develop for Android devices (Android SDK version 32.1.0-rc1)
[✓] Xcode - develop for iOS and macOS (Xcode 14.0.1)
Any idea what's going wrong?
I faced quite a similar issue. I make an app using web socket on flutter.
Although I use different web socket library (websocket_universal), it works on iOS and web but not on MacOS.
I follow this comment and it works for my case.
https://github.com/flutter/flutter/issues/47606#issuecomment-568522318
Add
<key>com.apple.security.network.client</key>
<true/>
to file DebugProfile.entitlements under directory macos/Runner/
I'm trying to get AnimatedSwitcher to work in a ReorderableListView, it works in a normal ListView. I'm thinking it has something to do with the keys, but I'm now sure.
Flutter 1.17.0 • channel beta • https://github.com/flutter/flutter.git
Framework • revision e6b34c2b5c (7 days ago) • 2020-05-02 11:39:18 -0700
Engine • revision 540786dd51
Tools • Dart 2.8.1
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => ChangeNumber(),
child: MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
body: SafeArea(
child: Consumer<ChangeNumber>(
builder: (context, value, child) {
return Column(
children: <Widget>[
Container(
height: 100,
child: ReorderableListView(
onReorder: (oldIndex, newIndex) {},
children: <Widget>[
AnimatedSwitcher(
key: ValueKey(value.i),
duration: Duration(seconds: 1),
child: NumberTile(
number: value.i,
key: ValueKey(value.i),
),
),
],
),
),
RaisedButton(
child: Text('Increase'),
onPressed: () => value.i = value.i + 1,
)
],
);
},
),
),
),
),
);
}
}
class NumberTile extends StatelessWidget {
final int number;
NumberTile({this.number, key}) : super(key: key);
#override
Widget build(BuildContext context) {
return ListTile(
title: Text('$number'),
);
}
}
class ChangeNumber extends ChangeNotifier {
int _i = 0;
get i => _i;
set i(int value) {
_i = value;
notifyListeners();
}
}
AnimatedSwitcher will not show effect on Text widget as your Text is inside ListTile inside NumberTile. You have to place the direct widget which you want to animate the switch inside the AnimatedSwitcher. Check this example
I have written the following simple flutter app. I am trying to write this without MaterialApp.
Earlier the error for Directionality was coming which i am able to solve by using Directionality Widget.Even without using Theme it is showing black screen and no output. Kindly correct the error
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main()
{
runApp(MyApp());
}
class MyApp extends StatefulWidget
{
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
double maxbid = 0.0;
void changeBid() {
setState(() {
maxbid += 10.0;
});
}
#override
Widget build(BuildContext context) {
// TODO: implement build
return
Theme(
data: Theme.of(context).copyWith(canvasColor: Colors.white,buttonColor: Colors.blue),
child:
Column(
children: <Widget>[
new Directionality(textDirection: TextDirection.ltr, child: Text("your Current bid is $maxbid",)),
new Directionality(textDirection: TextDirection.ltr, child: FlatButton.icon(
onPressed: changeBid,
label: Text("Click to increase Bid",),
icon: Icon(Icons.add_circle)
)),
],
)
);
}
}
Any Widget need Material over it to build widget, so you can correct it by just wrapping Theme widget with Material Widget.
#override
Widget build(BuildContext context) {
return Material( //added widget
child: Theme(
data: Theme.of(context)
I am trying to integrate paypal payment for my flutter app via a webview.
return new MaterialApp(
routes: {
"/": (_) => new WebviewScaffold(
url: "https://www.paypal.com/cgi-bin/webscr? business=xxxx.com&cmd=_xclick&item_name=Hot+Sauce-12oz.+Bottle&amount=5.95¤cy_code=USD",
appBar: new AppBar(
title: new Text(
"Payment",
),
),
)
},
);
when i run the page, the app closes unexpectedly with the error message
Unsupported value: <FlutterError: 0x1c422d200> of type FlutterError
Lost connection to device.
This is my flutter doctor.
Running flutter doctor...
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel beta, v0.5.1, on Mac OS X 10.13.1 17B1003, locale en-HK)
[✓] Android toolchain - develop for Android devices (Android SDK 26.0.2)
[✓] iOS toolchain - develop for iOS devices (Xcode 9.2)
[✓] Android Studio (version 3.1)
[✓] Connected devices (3 available)
You forget the initialRoute Parameter in the MaterialApp
the right way to do this is :
return new MaterialApp(
initialRoute: '/',
routes: {
"/": (_) => new WebviewScaffold(
url: "https://www.paypal.com/",
appBar: new AppBar(
title: new Text(
"Payment",
),
),
)
},
);
You can try my plugin flutter_inappwebview to integrate PayPal payment for your flutter app via a WebView.
An example with your sample url:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Future main() async {
runApp(new MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: InAppWebViewPage()
);
}
}
class InAppWebViewPage extends StatefulWidget {
#override
_InAppWebViewPageState createState() => new _InAppWebViewPageState();
}
class _InAppWebViewPageState extends State<InAppWebViewPage> {
InAppWebViewController webView;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("InAppWebView")
),
body: Container(
child: Column(children: <Widget>[
Expanded(
child: Container(
child: InAppWebView(
initialUrl: "https://www.paypal.com/cgi-bin/webscr?business=xxxx.com&cmd=_xclick&item_name=Hot+Sauce-12oz.+Bottle&amount=5.95¤cy_code=USD",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
debuggingEnabled: true,
),
),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
},
onLoadStart: (InAppWebViewController controller, String url) {
},
onLoadStop: (InAppWebViewController controller, String url) {
},
),
),
),
]))
);
}
}