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 494 forks source link

添加属性未变化处理避免重复build;修复弹出软键盘报错bug; #382

Closed wittyneko closed 2 years ago

wittyneko commented 2 years ago

Bug Fix: Reaching context that no longer used. (state: DEFUNCT) 改动在弹出软件盘时会出现bug,添加属性未变化处理避免重复build;

lizhuoyuan commented 2 years ago

will test ,ty

Mounir-Bouaiche commented 2 years ago

@wittyneko Test this code:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

void main() => runApp(MaterialApp(home: ThirdPage()));

class MyStatelessElement<T extends TestPage> extends StatelessElement {
  MyStatelessElement(T widget) : super(widget);

  @override
  T get widget => super.widget as T;

  @override
  void mount(Element? parent, Object? newSlot) {
    super.mount(parent, newSlot);
    print('${widget.text()} is mounted');
  }

  @override
  void unmount() {
    print('${widget.text()} is unmounted');
    super.unmount();
  }
}

abstract class TestPage extends StatelessWidget {
  String text();

  Widget goto();

  @override
  StatelessElement createElement() => MyStatelessElement(this);

  @override
  Widget build(BuildContext context) {
    Timer(const Duration(seconds: 3), () {
      Navigator.of(context).pushAndRemoveUntil(
        MaterialPageRoute(builder: (_) => goto()),
        (route) => false,
      );
    });
    return Scaffold(
      body: Center(
        child: Text(
          text(),
          style: TextStyle(fontWeight: FontWeight.w900, fontSize: 32.sp),
        ),
      ),
    );
  }
}

class FirstPage extends TestPage {
  @override
  String text() => 'First Page';

  @override
  Widget goto() => SecondPage();
}

class SecondPage extends TestPage {
  @override
  String text() => 'Second Page';

  @override
  Widget goto() => FirstPage();
}

class ThirdPage extends TestPage {
  @override
  String text() => 'Third Page';

  @override
  Widget goto() => FirstPage();

  @override
  Widget build(BuildContext context) {
    ScreenUtil.init(context);
    return super.build(context);
  }
}
Mounir-Bouaiche commented 2 years ago

I saw your code, and it's really bad, you got a big idea but code is wrong. Sorry, but we have to close your PR.

lizhuoyuan commented 2 years ago

I've tested it. There will be a problem of null checker

wittyneko commented 2 years ago
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

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

class MyApp extends StatelessWidget {
  @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: Size(360, 690),
      minTextAdapt: true,
      splitScreenMode: true,
      builder: (_) {
        return MaterialApp(
          debugShowCheckedModeBanner: false,
          // Use this line to prevent extra rebuilds
          useInheritedMediaQuery: true,
          title: 'First Method',
          // You can use the library anywhere in the app even in theme
          theme: ThemeData(
            primarySwatch: Colors.blue,
            textTheme: TextTheme(bodyText2: TextStyle(fontSize: 30.sp)),
          ),
          home: HomePage(title: 'First Method'),
        );
      },
    );
  }
}

class HomePage extends StatelessWidget {
  final String title;

  const HomePage({Key? key, required this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(title)),
      body: Center(
        child: Column(
          children: [
            TextField(
              autofocus: true,
              style: TextStyle(fontWeight: FontWeight.w900, fontSize: 32.sp),
            )
          ],
        ),
      ),
    );
  }
}

20220429140100

there is an error showing the soft keyboard in the current version.

lizhuoyuan commented 2 years ago
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

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

class MyApp extends StatelessWidget {
  @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: Size(360, 690),
      minTextAdapt: true,
      splitScreenMode: true,
      builder: (_) {
        return MaterialApp(
          debugShowCheckedModeBanner: false,
          // Use this line to prevent extra rebuilds
          useInheritedMediaQuery: true,
          title: 'First Method',
          // You can use the library anywhere in the app even in theme
          theme: ThemeData(
            primarySwatch: Colors.blue,
            textTheme: TextTheme(bodyText2: TextStyle(fontSize: 30.sp)),
          ),
          home: HomePage(title: 'First Method'),
        );
      },
    );
  }
}

class HomePage extends StatelessWidget {
  final String title;

  const HomePage({Key? key, required this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(title)),
      body: Center(
        child: Column(
          children: [
            TextField(
              autofocus: true,
              style: TextStyle(fontWeight: FontWeight.w900, fontSize: 32.sp),
            )
          ],
        ),
      ),
    );
  }
}

20220429140100

there is an error showing the soft keyboard in the current version.

5.5.0 修复了null checker的问题, 但引入了软键盘报错的问题,目前5.5.0包已撤回了. 但您的提交修复了引入了软键盘报错的问题, null checker又出现了,所以暂时不会合并. 但您的修改有助于重复build的问题 , 希望后续可以跟进. 我们会重新考虑解决方案,也期待您有更好的方式

lizhuoyuan commented 2 years ago

@Mounir-Bouaiche try this:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

final GlobalKey<NavigatorState> navigatorKey = new GlobalKey<NavigatorState>();

void main() => runApp(MaterialApp(
  home: ThirdPage(),
  navigatorKey: navigatorKey,
));

class MyStatelessElement<T extends TestPage> extends StatelessElement {
  MyStatelessElement(T widget) : super(widget);

  @override
  T get widget => super.widget as T;

  @override
  void mount(Element? parent, Object? newSlot) {
    super.mount(parent, newSlot);
    print('${widget.text()} is mounted');
  }

  @override
  void unmount() {
    print('${widget.text()} is unmounted');
    super.unmount();
  }
}

abstract class TestPage extends StatelessWidget {
  String text();

  Widget goto();

  @override
  StatelessElement createElement() => MyStatelessElement(this);

  @override
  Widget build(BuildContext context) {
    Timer(const Duration(seconds: 3), () {
      Navigator.of(context).pushAndRemoveUntil(
        MaterialPageRoute(builder: (_) => goto()),
            (route) => false,
      );
    });
    return Scaffold(
      body: Center(
        child: Column(
          children: [
            TextField(
              autofocus: true,
            ),
            Text(
              text(),
              style: TextStyle(fontWeight: FontWeight.w900, fontSize: 32.sp),
            ),
          ],
        ),
      ),
    );
  }
}

class FirstPage extends TestPage {
  @override
  String text() => 'First Page';

  @override
  Widget goto() => SecondPage();
}

class SecondPage extends TestPage {
  @override
  String text() => 'Second Page';

  @override
  Widget goto() => FirstPage();
}

class ThirdPage extends TestPage {
  @override
  String text() => 'Third Page';

  @override
  Widget goto() => FirstPage();

  @override
  Widget build(BuildContext context) {
    ScreenUtil.init(navigatorKey.currentContext!);
    return super.build(context);
  }
}

change context to navigator.currentContext

Mounir-Bouaiche commented 2 years ago

Hi @lizhuoyuan , I don't think Navigator context has a MediaQuery but I'll check. However I got an idea to fix this problem, and I ask you permission to do a breaking change update (version 6) based on performance while we still support and maintain version 5.

Mounir-Bouaiche commented 2 years ago

The easy solution will be like this:

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

void main() {
  runApp(MaterialApp(
    builder: (context, widget) {
      // for first method
      // ScreenUtil.setContext(context);
      // for second method
      ScreenUtil.init(context);
      return widget!;
    },
    home: ThirdPage(),
  ));
}

class MyStatelessElement<T extends TestPage> extends StatelessElement {
  MyStatelessElement(T widget) : super(widget);

  @override
  T get widget => super.widget as T;

  @override
  void mount(Element? parent, Object? newSlot) {
    super.mount(parent, newSlot);
    print('${widget.text()} is mounted');
  }

  @override
  void unmount() {
    print('${widget.text()} is unmounted');
    super.unmount();
  }
}

abstract class TestPage extends StatelessWidget {
  String text();

  Widget goto();

  @override
  StatelessElement createElement() => MyStatelessElement(this);

  @override
  Widget build(BuildContext context) {
    Timer(const Duration(seconds: 3), () {
      Navigator.of(context).pushAndRemoveUntil(
        MaterialPageRoute(builder: (_) => goto()),
        (route) => false,
      );
    });
    return Scaffold(
      body: Center(
        child: Column(
          children: [
            TextField(),
            Text(
              text(),
              style: TextStyle(fontWeight: FontWeight.w900, fontSize: 32.sp),
            ),
          ],
        ),
      ),
    );
  }
}

class FirstPage extends TestPage {
  @override
  String text() => 'First Page';

  @override
  Widget goto() => SecondPage();
}

class SecondPage extends TestPage {
  @override
  String text() => 'Second Page';

  @override
  Widget goto() => FirstPage();
}

class ThirdPage extends TestPage {
  @override
  String text() => 'Third Page';

  @override
  Widget goto() => FirstPage();
}
lizhuoyuan commented 2 years ago

Hi @lizhuoyuan , I don't think Navigator context has a MediaQuery but I'll check. However I got an idea to fix this problem, and I ask you permission to do a breaking change update (version 6) based on performance while we still support and maintain version 5.

nice , I am looking forward to it!

Mounir-Bouaiche commented 2 years ago

Hi @wittyneko , I have recently updated the library. Go check it out and tell us if your problem were solved.

wittyneko commented 2 years ago

@Mounir-Bouaiche Now is no error but can not adjust the layout height with the soft keyboard

Mounir-Bouaiche commented 2 years ago

@Mounir-Bouaiche Now is no error but can not adjust the layout height with the soft keyboard

Since keyboard is an overlay, it's an error to change layout when keyboard is shown. Shrinking and stretching component when keyboard change is a bad UX. However, you can get keyboard height from MediaQueryData's viewInsets.bottom if you somehow need a padding to show what's behind keyboard.