如何为自定义标签栏类型的小部件制作动画?

问题描述 投票:0回答:2

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

这是当前代码:

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()),
    );
  }
}

这是当前输出

flutter flutter-animation
2个回答
2
投票

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
        },
      ),
    );
  }
}

试试这段代码,希望对您有所帮助,如果有帮助,请了解标签栏小部件和控制器。


-1
投票

如果你需要制作一个自定义的tabbar widget,你可以使用layoutBuilder,动画定位,对于白色部分,改变它的x值即可

© www.soinside.com 2019 - 2024. All rights reserved.