Flutter3 TV 一百行自定义实现 tabbar tabview 联动

系统自带的 tabbar 焦点 在 TV端无法很好的使用

  • 使用card_swiper 组件作为tabview
import 'package:card_swiper/card_swiper.dart';
import 'package:flutter/material.dart';

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

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<StatefulWidget> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<String> tabs = ['推荐', '最新', '电影', '动漫', '综艺', '少综', '分类'];
  int selectedIndex = 0;
  late List<BoxDecoration> _decorations;
  final BoxDecoration holder_decoration = BoxDecoration(
    border: Border.all(width: 3, color: Colors.deepOrange),
    borderRadius: BorderRadius.all(
      Radius.circular(5),
    ),
  );
  final BoxDecoration transparent_decoration = BoxDecoration(
    border: Border.all(width: 3, color: Colors.transparent),
    borderRadius: BorderRadius.all(
      Radius.circular(5),
    ),
  );
  final SwiperController _controller = new SwiperController();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Container(
          padding: EdgeInsets.only(top: 30),
          child: Container(
            child: Column(
              children: [
                Row(
                  children: List.generate(
                    tabs.length,
                    (i) => Expanded(child: focusCard(i)),
                  ),
                ),
                Expanded(
                  child: Container(
                    decoration: BoxDecoration(color: Colors.white),
                    child: Swiper(
                      itemCount: tabs.length,
                      itemBuilder: (BuildContext context, int i) =>
                          MyCustomWidget(index: i),
                      loop: false,
                      controller: _controller,
                    ),
                  ),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }

  Widget focusCard(index) {
    return Focus(
      onFocusChange: (focused) {
        setState(() {
          _decorations[index] =
              focused ? holder_decoration : transparent_decoration;
          _controller.move(index);
        });
      },
      child: Container(
        padding: EdgeInsets.only(left: 20, right: 20, bottom: 10),
        decoration: _decorations[index],
        margin: EdgeInsets.all(2),
        child: Text(tabs[index]),
      ),
    );
  }
}

class MyCustomWidget extends StatefulWidget {
  final int index;

  const MyCustomWidget({super.key, required this.index});

  @override
  State<MyCustomWidget> createState() => _MyCustomWidgetState();
}

class _MyCustomWidgetState extends State<MyCustomWidget> {
  int selectedIndex = -1;
  final BoxDecoration holder_decoration = BoxDecoration(
    border: Border.all(width: 3, color: Colors.deepOrange),
    borderRadius: BorderRadius.all(
      Radius.circular(5),
    ),
  );
  final BoxDecoration transparent_decoration = BoxDecoration(
    border: Border.all(width: 3, color: Colors.transparent),
    borderRadius: BorderRadius.all(
      Radius.circular(5),
    ),
  );

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Expanded(
          child: focusCard(0),
        ),
        Expanded(
          child: Column(
            children: [
              Expanded(
                child: focusCard(1),
              ),
              Expanded(
                child: focusCard(2),
              ),
            ],
          ),
        ),
        Expanded(
          child: Column(
            children: [
              Expanded(
                child: focusCard(3),
              ),
              Expanded(
                child: focusCard(4),
              ),
            ],
          ),
        ),
      ],
    );
  }

  Widget focusCard(index) {
    return Focus(
      onFocusChange: (focused) {
        setState(() {
          selectedIndex = focused ? index : selectedIndex;
        });
      },
      child: Container(
        decoration:
            index == selectedIndex ? holder_decoration : transparent_decoration,
        margin: EdgeInsets.all(2),
        child: Card(
          child: Center(
            child: Text(
              index == selectedIndex
                  ? '${widget.index}_${index}_Focused'
                  : '${widget.index}_${index}_UnFocused',
            ),
          ),
        ),
      ),
    );
  }
}
posted @ 2024-01-26 16:36  vx_guanchaoguo0  阅读(92)  评论(0编辑  收藏  举报