Skip to content

Instantly share code, notes, and snippets.

@liudonghua123
Created April 24, 2020 10:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save liudonghua123/6c2579d12c87389d9da6b06afa4a68a6 to your computer and use it in GitHub Desktop.
Save liudonghua123/6c2579d12c87389d9da6b06afa4a68a6 to your computer and use it in GitHub Desktop.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SamplePage(),
),
);
}
}
class SamplePage extends StatefulWidget {
SamplePage({Key key}) : super(key: key);
@override
_SamplePageState createState() => _SamplePageState();
}
class _SamplePageState extends State<SamplePage> with TickerProviderStateMixin {
TabController _tabController;
var tabData = ['tab1', 'tab2'];
@override
void initState() {
_tabController = TabController(length: tabData.length, vsync: this);
_tabController.addListener(() {
if (_tabController.indexIsChanging) {
setState(() {});
}
});
super.initState();
}
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
/// some widget above tab header
Container(
height: 100,
alignment: Alignment.center,
child: Text('Header'),
),
/// tab header
TabBar(
controller: _tabController,
tabs: [
...tabData.map(
(item) => Tab(
child: Text(item),
),
),
],
),
/// tab content
AnimatedSwitcher(
duration: Duration(milliseconds: 500),
switchInCurve: Curves.easeInOut,
switchOutCurve: Curves.easeInOut,
transitionBuilder: (Widget child, Animation<double> animation) {
var direction = _tabController.index > _tabController.previousIndex
? AxisDirection.left
: AxisDirection.right;
return SlideTransitionX(
child: child,
direction: direction,
position: animation,
);
},
child: _tabController.index == 0
? tabContent('tab1', 50)
: tabContent('tab2', 5),
),
/// some widget below tab content
Container(
height: 100,
alignment: Alignment.center,
child: Text('Footer'),
),
],
));
}
Widget tabContent(
String title,
int length,
) {
return Column(
key: ValueKey<int>(length),
children: [
...List.generate(
length,
(index) => ListTile(
title: Text('${title} item ${index}'),
trailing: Icon(Icons.access_alarm),
),
),
],
);
}
}
/// code copied from https://book.flutterchina.club/chapter9/animated_switcher.html
class SlideTransitionX extends AnimatedWidget {
SlideTransitionX({
Key key,
@required Animation<double> position,
this.transformHitTests = true,
this.direction = AxisDirection.down,
this.child,
}) : assert(position != null),
super(key: key, listenable: position) {
// 偏移在内部处理
switch (direction) {
case AxisDirection.up:
_tween = Tween(begin: Offset(0, 1), end: Offset(0, 0));
break;
case AxisDirection.right:
_tween = Tween(begin: Offset(-1, 0), end: Offset(0, 0));
break;
case AxisDirection.down:
_tween = Tween(begin: Offset(0, -1), end: Offset(0, 0));
break;
case AxisDirection.left:
_tween = Tween(begin: Offset(1, 0), end: Offset(0, 0));
break;
}
}
Animation<double> get position => listenable;
final bool transformHitTests;
final Widget child;
//退场(出)方向
final AxisDirection direction;
Tween<Offset> _tween;
@override
Widget build(BuildContext context) {
Offset offset = _tween.evaluate(position);
if (position.status == AnimationStatus.reverse) {
switch (direction) {
case AxisDirection.up:
offset = Offset(offset.dx, -offset.dy);
break;
case AxisDirection.right:
offset = Offset(-offset.dx, offset.dy);
break;
case AxisDirection.down:
offset = Offset(offset.dx, -offset.dy);
break;
case AxisDirection.left:
offset = Offset(-offset.dx, offset.dy);
break;
}
}
return FractionalTranslation(
translation: offset,
transformHitTests: transformHitTests,
child: child,
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment