Can’t switch Focus between a widget and its parent

I’m working at a Android TV adpated app and here is my layout,
a list item with a delete btn as trailing

to run it on tv, i need to make sure that we can switch focus to everything, but in this layout, i cant switch focus from whole item to that trailing btn by using any Arrow key.

at the begining, i figured out a way, here is my code

class ListItem extends HookWidget {
  final (int, PlayableItem) e;

  const ListItem(
    this.e, {
    super.key,
  });

  @override
  Widget build(BuildContext context) {
    // whole item focusNode
    final itemFocusNode = useFocusNode();
    // trailing focusNode
    final trailingFocusNode = useFocusNode();

    // item focus state
    final itemFocused = useState(false);

    //change color by item focusState
    final foregroundColor = useState(Colors.black);
    final bgColor = useState(Colors.transparent);

    itemFocusNode.addListener(() {
      itemFocused.value = itemFocusNode.hasFocus;
      if (itemFocusNode.hasFocus) {
        foregroundColor.value = Colors.white;
        bgColor.value = Theme.of(context).primaryColor;
      } else {
        foregroundColor.value = Colors.black;
        bgColor.value = Colors.transparent;
      }
    });

    return Stack(
      alignment: Alignment.center,
      children: [
        InkWell(
          // for Tap and Enter interaction
          focusNode: itemFocusNode,
          onTap: () {
            /// to support touch screen Tap and keyboard Enter key
            /// seems only inkwell can do this
          },
          focusColor: bgColor.value, // when whole item is focused, bg is blue, otherwise transparent
          child: Focus(
              // to switch focus manually
              onKeyEvent: (node, event) {
                switch (event.logicalKey) {
                  case LogicalKeyboardKey.arrowRight:
                    // switch focus here
                    itemFocusNode.unfocus();
                    trailingFocusNode.requestFocus();
                    break;
                  default:
                    break;
                }
                return KeyEventResult.ignored;
              },
              child: Container()), // ignored child
        ),
        Align(
          alignment: Alignment.centerRight,
          child: Padding(
            padding: const EdgeInsets.only(right: 8.0),
            child: PBInkWell(
              /// my own inkwell to implement outline border as focused bg.
              focusNode: trailingFocusNode, // trailing focusNode
              focusBorderType: FocusBorderType.rect,
              onTap: () => ListController.find().removeFile(e.$1),
              builder: (context, isFocused, child) => SvgPicture.asset(
                "assets/images/delete.svg",
                width: 20,
                colorFilter: itemFocused.value
                    ? const ColorFilter.mode(Colors.white, BlendMode.srcIn)
                    : isFocused
                        ? ColorFilter.mode(Theme.of(context).primaryColor, BlendMode.srcIn)
                        : null,
              ),
            ),
          ),
        )
      ],
    );
  }
}

with this code, i can switch focus from whole item to it’s trailing, and by flutter default behavior, i dont need to handle the reverse version, from trailing to its parent, it can be easily switched by ‘Arrow Left’ key without any extra code.

Everything seems okay buuuuuuuuuuuuuuuuut, as you can see, this is a list and btw i’m using ReorderableListView to support reordering on touch screen, my problem is

After jumping down to an item, it works well, but after jumping up, it doesnt work.

a gif showing that issue

in this gif, i’m using only Arrow key on keyboard to control, and while jumping up to focus on the first item, i actually hit Arrow Right key so many times and it just not working. But jumping down to the second item, it works well

here is my listview code, it’s inside a drawer

class PlayerDrawer extends HookWidget {
  const PlayerDrawer({super.key});

  @override
  Widget build(BuildContext context) {
    final isReorderMode = useState(fasle);

    return Container(
      color: Colors.white.withAlpha((255 * 0.9).round()),
      width: 300,
      child: Column(
        children: [
          ListTile(
            style: ListTileStyle.list,
            leading: Text("Play List", style: Theme.of(context).textTheme.titleLarge),
            trailing: Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                if (!isReorderMode.value)
                  PBInkWell(
                    onTap: ListController.find().removeAll,
                    builder: (context, isFocused, child) => Padding(
                      padding: const EdgeInsets.symmetric(horizontal: 6.0, vertical: 2.0),
                      child: Text("Clear All",
                          style: TextStyle(
                            color: isFocused ? Theme.of(context).primaryColor : Colors.black,
                          )),
                    ),
                  ),
                Obx(() {
                  final isUsingKeyboard = ListController.find().isUseKeyboard.value;
                  
                  return isUsingKeyboard
                      ? const SizedBox()
                      : PBInkWell(
                          onTap: ListController.find().switchMode,
                          builder: (context, isFocused, child) => Padding(
                            padding: const EdgeInsets.symmetric(horizontal: 6.0, vertical: 2.0),
                            child: Text(isReorderMode.value ? "Done" : "Sort",
                                style: TextStyle(
                                  color: isFocused ? Theme.of(context).primaryColor : Colors.black,
                                )),
                          ),
                        );
                }),
              ],
            ),
          ),
          Expanded(
            child: Obx(() {
              final list = ListController.find().data;
              return ReorderableListView(
                onReorder: ListController.find().reorderFileList,
                children: buildList(context, list),
              );
            }),
          ),
        ],
      ),
    );
  }

  List<Widget> buildList(BuildContext context, List<PlayableItem> list) {
    return list.indexed
        .map(
          (e) => ListItem(
            e,
            key: ValueKey("${e.$1}-${e.$2.uri}"),
          ),
        )
        .toList();
  }
}

let me know if you need to see more code.

btw, this is output of flutter doctor -v

[✓] Flutter (Channel stable, 3.19.6, on macOS 14.3.1 23D60 darwin-arm64, locale zh-Hans-JP)
    • Flutter version 3.19.6 on channel stable at /Users/inbottest2/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 54e66469a9 (4 个月前), 2024-04-17 13:08:03 -0700
    • Engine revision c4cd48e186
    • Dart version 3.3.4
    • DevTools version 2.31.1

[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    • Android SDK at /Users/inbottest2/Library/Android/sdk
    • Platform android-34, build-tools 34.0.0
    • ANDROID_HOME = /Users/inbottest2/Library/Android/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 17.0.10+0-17.0.10b1087.21-11609105)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 15.4)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 15F31d
    • CocoaPods version 1.15.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2024.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.10+0-17.0.10b1087.21-11609105)

[✓] VS Code (version 1.91.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.94.0

[✓] Connected device (4 available)            
    • AGS3 AL09HN (mobile) • 192.168.22.112:5555       • android-arm64  • Android 10 (API 29)
    • Connected (mobile)   • 00008110-00142D6E2E78801E • ios            • iOS 17.6 21G80
    • macOS (desktop)      • macos                     • darwin-arm64   • macOS 14.3.1 23D60 darwin-arm64
    • Chrome (web)         • chrome                    • web-javascript • Google Chrome 127.0.6533.74

[✓] Network resources
    • All expected network resources are available.

• No issues found!

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật