flutter_portal icon indicating copy to clipboard operation
flutter_portal copied to clipboard

LeaderLayer anchor must come before FollowerLayer in paint order, but the reverse was true.pen

Open ElsayedDev opened this issue 2 years ago • 47 comments

When I used TextField widget

the following error occurred

════════ Exception caught by scheduler library ═════════════════════════════════ The following assertion was thrown during a scheduler callback: LeaderLayer anchor must come before FollowerLayer in paint order, but the reverse was true. 'package:flutter/src/rendering/layer.dart': package:flutter/…/rendering/layer.dart:1 Failed assertion: line 2502 pos 7: 'leader._lastOffset != null'

ElsayedDev avatar Apr 29 '22 12:04 ElsayedDev

Please use v1.0.0 which I have fixed the bug :)

fzyzcjy avatar Apr 29 '22 12:04 fzyzcjy

I already using it. image

ElsayedDev avatar Apr 29 '22 12:04 ElsayedDev

I see. Then that is bug of flutter 2.10 stable, which will be solved in 2.13

fzyzcjy avatar Apr 29 '22 12:04 fzyzcjy

see https://github.com/fzyzcjy/flutter_portal/issues/56#issuecomment-1070959360 . Though that post is about how I fix bug of this repo, that post also tells you why this error message is a bug of flutter

fzyzcjy avatar Apr 29 '22 12:04 fzyzcjy

Thanks

ElsayedDev avatar Apr 29 '22 12:04 ElsayedDev

I got something similar when I tried to compose portal-target > portal > portal-target. portal-target inside portal-target worked but inner one was in background instead of foreground.

════════ Exception caught by scheduler library ═════════════════════════════════
LeaderLayer anchor must come before FollowerLayer in paint order, but the reverse was true.
'package:flutter_portal/src/enhanced_composited_transform/flutter_src/rendering_layer.dart':
package:flutter_portal/…/flutter_src/rendering_layer.dart:1
Failed assertion: line 383 pos 7: '_debugCheckLeaderBeforeFollower(forwardLayers, inverseLayers)'

With some experimentation, I found a workaround for nesting level of two, not sure about higher nesting.

Use portal-target inside portal-target without any portal between them in the hierarchy and use below anchor on inner portal-target:

anchor: const Aligned(
    follower: Alignment.center,
    target: Alignment.center,
    alignToPortal: AxisFlag(x: true, y: true),
    portal: Alignment.center,
)

ghost avatar May 02 '22 18:05 ghost

I got something similar when I tried to compose portal-target > portal > portal-target. portal-target inside portal-target worked but inner one was in background instead of foreground.

I have had this error also when having this nest, but I have fixed it. Could you please give a reproducible sample, and ensure it fails in 1.0.0?

fzyzcjy avatar May 03 '22 08:05 fzyzcjy

I got something similar when I tried to compose portal-target > portal > portal-target. portal-target inside portal-target worked but inner one was in background instead of foreground.

I have had this error also when having this nest, but I have fixed it. Could you please give a reproducible sample, and ensure it fails in 1.0.0?

I tried to change flutter channel to beta but it's still the same problem..

ElsayedDev avatar May 03 '22 08:05 ElsayedDev

Interesting. Could you please reproducible sample, possibly by giving a github repo

fzyzcjy avatar May 03 '22 08:05 fzyzcjy

please check this file https://github.com/ElsayedDev/errors/blob/main/portal_text_field_bug.dart

ElsayedDev avatar May 03 '22 08:05 ElsayedDev

I see. could you please make it shorter to ease debugging

fzyzcjy avatar May 03 '22 08:05 fzyzcjy

I got something similar when I tried to compose portal-target > portal > portal-target. portal-target inside portal-target worked but inner one was in background instead of foreground.

I have had this error also when having this nest, but I have fixed it. Could you please give a reproducible sample, and ensure it fails in 1.0.0?

Oh, it could be me then, I was trying to do some weird stuff. I will try to untangle my codebase and reproduce the error in a new app.

ghost avatar May 04 '22 04:05 ghost

Take your time.

fzyzcjy avatar May 04 '22 06:05 fzyzcjy

@ElsayedDev is your problem fixed? if so how? I'm facing the same issue right now myself

NeatFastro avatar May 31 '22 08:05 NeatFastro

Here's the minimal reproducible example. when user taps on the TextField the the assertion fails, the only solution I was able to find was to comment out the assertion in the flutter sdk source code

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

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return const Portal(
      child: MaterialApp(
        title: 'Flutter portal layers bug',
        home: MyHomePage(title: 'Flutter Demo Home Page'),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool _showPortal = false;

  void _togglePortal() {
    setState(() => _showPortal = !_showPortal);
  }

  ElevatedButton _buildPortalChild() {
    return ElevatedButton(
      onPressed: _togglePortal,
      child: const Text('Toggle portal'),
    );
  }

  Widget _buildPortalFollower() {
    return SizedBox(
      width: 400,
      height: 300,
      child: Card(
        child: Center(
          child: TextFormField(
            decoration: const InputDecoration(
              label: Text('Text form field'),
              border: OutlineInputBorder(),
            ),
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: PortalTarget(
          visible: _showPortal,
          anchor: const Aligned(
            follower: Alignment.topCenter,
            target: Alignment.bottomCenter,
          ),
          portalFollower: _buildPortalFollower(),
          child: _buildPortalChild(),
        ),
      ),
    );
  }
}

NeatFastro avatar May 31 '22 11:05 NeatFastro

environment: sdk: ">=2.17.0 <3.0.0"

flutter version: 3.0.0 and flutter_portal: ^1.1.0

NeatFastro avatar May 31 '22 11:05 NeatFastro

Good reproduction! So, to make reproducible sample smaller, does _showPortal matter here? Or can we remove that button and _showPortal logic?

Similar applies to TextFormField.decoration - can we remove it?

And TextFormField, can we use TextField. etc

And remove the Card

fzyzcjy avatar May 31 '22 12:05 fzyzcjy

Once it gets so simple, we can use things like https://docs.flutter.dev/testing/code-debugging debugDumpLayerTree etc to see what is happening (with a very small tree - clean and easy-to-debug result)

fzyzcjy avatar May 31 '22 12:05 fzyzcjy

Idk about that, all I care about is when this is going to be fixed or is there any workaround?

NeatFastro avatar May 31 '22 12:05 NeatFastro

To fix it or make a workaround, needs to find the cause of bug, which needs a good reproducible sample :)

fzyzcjy avatar May 31 '22 12:05 fzyzcjy

Good reproduction! So, to make reproducible sample smaller, does _showPortal matter here? Or can we remove that button and _showPortal logic?

Similar applies to TextFormField.decoration - can we remove it?

And TextFormField, can we use TextField. etc

And remove the Card

Nope these do not matter it was for the easier understanding of the behaviour from the user perspective

NeatFastro avatar May 31 '22 12:05 NeatFastro

To fix it or make a workaround, needs to find the cause of bug, which needs a good reproducible sample :)

I might have to downgrade to flutter 2.10.x which did not had this problem, ah but now I'm using the new super param fields of the constructor, it's going to be a lot of work

NeatFastro avatar May 31 '22 12:05 NeatFastro

do you want be to simplify the code?

NeatFastro avatar May 31 '22 13:05 NeatFastro

do you want be to simplify the code?

Yes. Simplest code possible makes it easy to debug and fix.

fzyzcjy avatar May 31 '22 13:05 fzyzcjy

flutter 2.10.x which did not had this problem

So, you mean this problem is stably reproduce in 3.0 while not in 2.10?

fzyzcjy avatar May 31 '22 13:05 fzyzcjy

Good reproduction! So, to make reproducible sample smaller, does _showPortal matter here? Or can we remove that button and _showPortal logic?

Similar applies to TextFormField.decoration - can we remove it?

And TextFormField, can we use TextField. etc

And remove the Card

Here's you go.

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

void main() => runApp(
      Portal(
        child: MaterialApp(
          home: Material(
            child: Center(
              child: PortalTarget(
                anchor: const Aligned(
                  follower: Alignment.topCenter,
                  target: Alignment.bottomCenter,
                ),
                portalFollower: SizedBox(
                  width: 400,
                  height: 300,
                  child: TextFormField(),
                ),
                child: const Text('Portal child'),
              ),
            ),
          ),
        ),
      ),
    );

NeatFastro avatar May 31 '22 13:05 NeatFastro

Great! The next step is to add a reproducible sample in https://github.com/fzyzcjy/flutter_portal/blob/master/test/widget_test.dart. Maybe you need pumpWidget and tester.tap

fzyzcjy avatar May 31 '22 13:05 fzyzcjy

Just to be clear, you want me to write a test for this use case right?

NeatFastro avatar May 31 '22 13:05 NeatFastro

Yes. Just copy-and-paste your sample and make minor additions like tap. The steps are:

  • [x] reproduce it stablely
  • [ ] add the reproduction to tests/...dart, then it should stablely fails
  • [ ] find the cause by logging/debugging into this test
  • [ ] fix it 🎉

fzyzcjy avatar May 31 '22 13:05 fzyzcjy

Ah man I don't got that much time, that's why I'm a bit salty.

NeatFastro avatar May 31 '22 13:05 NeatFastro