flutter 如何动画自定义标签栏的小部件?

ykejflvf  于 2023-05-08  发布在  Flutter
关注(0)|答案(2)|浏览(157)

所以我有这个小部件,它允许用户从两个或多个标签中选择一个标签。这在功能上很好,但我想以这样一种方式动画它,当用户单击其他非活动标签时,白色背景会滑动到该标签,而不是立即出现在那里。有没有什么方法可以用当前的代码实现这一点,或者我需要相应地更新我的代码?

当前代码如下:

import 'package:flutter/material.dart';

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

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

  final GlobalKey headerKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(home: HomePage());
  }
}

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

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int active = 1;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('App bar')),
      body: Column(
        children: [
          const SizedBox(
            height: 20,
          ),
          const Text('Select one'),
          const SizedBox(
            height: 20,
          ),
          SelectOne(),
        ],
      ),
    );
  }
}

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

  @override
  State<SelectOne> createState() => _SelectOneState();
}

class _SelectOneState extends State<SelectOne> {
  // tab bar values
  final List<String> values = ['one', 'two'];

  // active value
  late String activeValue;

  @override
  void initState() {
    super.initState();

    // setting the active value
    activeValue = values[0];
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        color: Theme.of(context).primaryColor,
        borderRadius: BorderRadius.circular(100),
        border: Border.all(
          color: Theme.of(context).primaryColor,
          width: 2,
        ),
      ),
      child: Row(
          children: values.map(
        (value) {
          // whether the item is selected or not
          final bool isSelected = value == activeValue;

          return Expanded(
            child: GestureDetector(
              onTap: () {
                // setting the active value
                setState(() {
                  activeValue = value;
                });
              },
              child: Container(
                alignment: Alignment.center,
                padding: const EdgeInsets.all(6),
                decoration: BoxDecoration(
                  color: isSelected ? Colors.white : null,
                  borderRadius: BorderRadius.circular(100),
                ),
                child: Text(
                  value,
                  style: Theme.of(context).textTheme.bodyMedium!.copyWith(
                        fontWeight: isSelected ? FontWeight.w500 : null,
                        color: isSelected ? Colors.black : Colors.white,
                      ),
                ),
              ),
            ),
          );
        },
      ).toList()),
    );
  }
}

此处为当前输出

jjhzyzn0

jjhzyzn01#

Flutter中内置了一个名为Tabbar的小部件,您应该使用它

import 'package:flutter/material.dart';

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

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

  final GlobalKey headerKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(home: HomePage());
  }
}

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('App bar')),
      body: Column(
        children: [
          const SizedBox(height: 20),
          const Text('Select one'),
          const SizedBox(height: 20),
          const SelectOne(),
        ],
      ),
    );
  }
}

class SelectOne extends StatefulWidget {
  const SelectOne({Key? key}) : super(key: key);

  @override
  State<SelectOne> createState() => _SelectOneState();
}

class _SelectOneState extends State<SelectOne> with SingleTickerProviderStateMixin {
  late TabController _tabController;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: 2, vsync: this);
  }

  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        color: Theme.of(context).primaryColor,
        borderRadius: BorderRadius.circular(100),
        border: Border.all(
          color: Theme.of(context).primaryColor,
          width: 2,
        ),
      ),
      child: TabBar(
        controller: _tabController,
        tabs: [
          Tab(text: 'one'),
          Tab(text: 'two'),
        ],
        labelStyle: Theme.of(context).textTheme.bodyMedium!.copyWith(
          fontWeight: FontWeight.w500,
          color: Colors.black,
        ),
        unselectedLabelStyle: Theme.of(context).textTheme.bodyMedium!.copyWith(
          fontWeight: null,
          color: Colors.white,
        ),
        indicator: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(100),
        ),
        onTap: (index) {
          // Handle tab selection
        },
      ),
    );
  }
}

试试这个代码,我希望它能帮助你,如果这有帮助,然后学习标签栏小部件和控制器。

lrl1mhuk

lrl1mhuk2#

如果你需要制作一个自定义的标签栏小部件,你可以使用layoutBuilder,用animated positioned来处理白色部分,只需要改变它的x值

相关问题