OpenFlutter / flutter_screenutil

Flutter screen adaptation, font adaptation, get screen information
https://pub.dartlang.org/packages/flutter_screenutil
Apache License 2.0
3.88k stars 496 forks source link

键盘弹起或收起,会重新执行 builder: (BuildContext context, Widget? child) 导致运行卡顿 #495

Closed lurongshuang closed 1 year ago

lurongshuang commented 1 year ago

代码

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_video_demo/app_theme.dart';
class MyApp extends StatelessWidget {
  static const double screenWidth = 750 / 2;
  static const double screenHeight = 1624 / 2;
  Size designSize = const Size(screenWidth, screenHeight);

  @override
  Widget build(BuildContext context) {
    return ScreenUtilInit(
      designSize: designSize,
      builder: (BuildContext context, Widget? child) {
        return MaterialApp(
          title: 'Draggable Demo',
          theme: appThemeData,
          home: LoginPage(),
        );
      },
    );
  }
}

class LoginPage extends StatefulWidget {
  @override
  _LoginPageState createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> with WidgetsBindingObserver , AutomaticKeepAliveClientMixin {
  TextEditingController _usernameController = TextEditingController();
  TextEditingController _passwordController = TextEditingController();

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    super.dispose();
    WidgetsBinding.instance.removeObserver(this);
  }

  // @override
  // bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext context) {
    // super.build(context); // Ensure that the State object is kept alive

    return Scaffold(
      appBar: AppBar(
        title: Text('Login'),
      ),
      resizeToAvoidBottomInset: false,
      body:
      SingleChildScrollView(
        child: Padding(
          padding: EdgeInsets.all(16.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              TextField(
                controller: _usernameController,
                decoration: InputDecoration(
                  labelText: 'Username',
                ),
              ),
              SizedBox(height: 16.0),
              TextField(
                controller: _passwordController,
                decoration: InputDecoration(
                  labelText: 'Password',
                ),
                obscureText: true,
              ),
              SizedBox(height: 16.0),
              ElevatedButton(
                onPressed: () {
                  // Perform login logic here
                  String username = _usernameController.text;
                  String password = _passwordController.text;
                  // TODO: Add your login implementation
                },
                child: Text('Login'),
              ),
            ],
          ),
        ),
      ),
    );
  }

  @override
  // TODO: implement wantKeepAlive
  bool get wantKeepAlive => true;
}

三个版本都无效

flutter_screenutil: ^5.8.3

flutter_screenutil:

git:

url: https://github.com/OpenFlutter/flutter_screenutil

ref: dev

flutter_screenutil: ^5.9.0-beta

pumppmup1 commented 1 year ago

Same here

Mounir-Bouaiche commented 1 year ago

@lurongshuang @pumppmup1 , Of course it will, it's a basic Builder after all. That's why there is child parameter and it's passed in builder method. You should use flutter_screenutil: ^5.9.0-beta, and be sure you use child only as you won't need builder. see example below:

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    //Set the fit size (Find your UI design, look at the dimensions of the device screen and fill it in,unit in dp)
    return ScreenUtilInit(
      designSize: const Size(360, 690),
      minTextAdapt: true,
      splitScreenMode: true,
      // Use builder only if you need to use library outside ScreenUtilInit context
      builder: (_ , child) {
        return MaterialApp(
          debugShowCheckedModeBanner: false,
          title: 'First Method',
          // You can use the library anywhere in the app even in theme
          theme: ThemeData(
            primarySwatch: Colors.blue,
            // to use 1.sp (ScreenUtil) the library needs to be initialized, and rebuild materialapp theme to respond to changes
            // as it wont be updated automatically, it's impossible to know what's hapening outside the context
            textTheme: Typography.englishLike2018.apply(fontSizeFactor: 1.sp),
          ),
          home: child,
        );
      },
      child: const HomePage(title: 'First Method'),
    );
  }
}

Example above will be:

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    //Set the fit size (Find your UI design, look at the dimensions of the device screen and fill it in,unit in dp)
    return ScreenUtilInit(
      designSize: const Size(360, 690),
      minTextAdapt: true,
      splitScreenMode: true,
      // Don't use builder if you don't use ScreenUtil in this bloc
      child:  MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'First Method',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: const HomePage(title: 'First Method'),
      ),
    );
  }
}
vovaklh commented 1 year ago

@Mounir-Bouaiche What if I use MaterialApp.router?

Mounir-Bouaiche commented 1 year ago

@Mounir-Bouaiche What if I use MaterialApp.router?

@vovaklh , you shouldn't use any function that doesn't depend on ScreenUtil, call all your functions outside ScreenUtilInit builder bloc. I've provided example in previous issue.

Akhilgktradebrains commented 9 months ago

widgets getting rebuild on key board appearance and pop ...any solution?

Widget build(BuildContext context) { print("main rebulded"); super.build(context); subscribeToTopics(context); if (initialRoute != RoutesPath.loginPath) addSession();

return MultiProvider(
    providers: [
      ChangeNotifierProvider(
        create: (context) => ConnectivityProvider(),
        child: const BottomNavView(),
      ),
      ChangeNotifierProvider<PortfolioProvider>(
        create: (context) => PortfolioProvider(),
      )
    ],
    child: 
                // AnnotatedRegion(
                //   value: SystemUiOverlayStyle(
                //   statusBarColor: Colors.transparent, //top status bar
                //   systemNavigationBarColor:Colors.black, // navigation bar color, the one Im looking for
                //   statusBarIconBrightness: Brightness.dark, // status bar icons' color
                //   systemNavigationBarIconBrightness:
                //   Brightness.dark, //navigation bar icons' color
                //   ),
                // child:
               ScreenUtilInit(
        designSize: const Size(360, 690),
        minTextAdapt: true,
        splitScreenMode: true,

        child: Consumer<AppTheme>(builder: (context, appTheme, _) {
            return MaterialApp(
              debugShowCheckedModeBanner: false,
              title: "Portal",
              theme: appTheme.light(),
              darkTheme: appTheme.dark(),
              themeMode: appTheme.currentTheme(),
              onGenerateRoute: Routes.generateRoute,
              initialRoute: initialRoute,

              // ),
            );})
            )
         // }),

        );

} }

amoyastudio commented 8 months ago

Yes , this worked for me too: https://github.com/OpenFlutter/flutter_screenutil/issues/495#issuecomment-1598513177