mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

Fixes https://github.com/flutter/flutter/issues/159444 Fixes https://github.com/flutter/flutter/issues/146089 This adds callbacks to TabBar for onHover and onFocusChange. They pipe through to the underlying Inkwell widget that is wrapped around each Tab of the TabBar during build. #### Alternatives - I did consider adding these callbacks to Tab instead, but felt that going through TabBar would be better. If implemented in Tab, the user would need to define callbacks for each tab. This PR makes it so there is only need for one callback, and the associated Tab index is provided. Also, since the Inkwell is applied in the TabBar, it's kludgy to have to extract that from the Tabs _in_ TabBar later to pass on to the Inkwell. 👃 - Digging in to the requests in the linked issues, the user wants to change various stylings in response to these events. WidgetStateProperties were considered, but there are so many potential styling properties that going this route would require greatly increasing the API surface here. Tab.child allows the user to provide whatever widget they would like to have as the content. Being able to modify Tab.child in response to these events is a better way go instead of exposing a ton of different properties. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
65 lines
1.9 KiB
Dart
65 lines
1.9 KiB
Dart
// Copyright 2014 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
/// Flutter code sample for [TabBar.onFocusChange].
|
|
|
|
void main() => runApp(const TabBarApp());
|
|
|
|
class TabBarApp extends StatelessWidget {
|
|
const TabBarApp({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return MaterialApp(theme: ThemeData(useMaterial3: true), home: const TabBarExample());
|
|
}
|
|
}
|
|
|
|
class TabBarExample extends StatefulWidget {
|
|
const TabBarExample({super.key});
|
|
|
|
@override
|
|
State<TabBarExample> createState() => _TabBarExampleState();
|
|
}
|
|
|
|
class _TabBarExampleState extends State<TabBarExample> {
|
|
final List<Color> tabColors = <Color>[Colors.purple, Colors.purple, Colors.purple];
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return DefaultTabController(
|
|
initialIndex: 1,
|
|
length: 3,
|
|
child: Scaffold(
|
|
appBar: AppBar(
|
|
title: const Text('TabBar Sample'),
|
|
bottom: TabBar(
|
|
onHover: (bool value, int index) {
|
|
setState(() {
|
|
tabColors[index] = switch (value) {
|
|
true => Colors.pink,
|
|
false => Colors.purple,
|
|
};
|
|
});
|
|
},
|
|
tabs: <Widget>[
|
|
Tab(icon: Icon(Icons.cloud_outlined, color: tabColors[0])),
|
|
Tab(icon: Icon(Icons.beach_access_sharp, color: tabColors[1])),
|
|
Tab(icon: Icon(Icons.brightness_5_sharp, color: tabColors[2])),
|
|
],
|
|
),
|
|
),
|
|
body: const TabBarView(
|
|
children: <Widget>[
|
|
Center(child: Text("It's cloudy here")),
|
|
Center(child: Text("It's rainy here")),
|
|
Center(child: Text("It's sunny here")),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|