主要思路:利用Ticker定时切换TabBarView
1,搭建界面
public class MovePictore : StatefulWidget { public ListAllImage; public MovePictore(List allImage) { AllImage = allImage; } public override State createState() { return new MovePictoreState(AllImage); } } class MovePictoreState : SingleTickerProviderStateMixin { public List AllImage; TabController tabController; public MovePictoreState(List allImage) { AllImage = allImage; } public override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar(title: new Container( child: new Text("轮播图实现"), alignment: Alignment.center ) ), body: new Stack( children: new List () { new TabBarView( controller: tabController, children: AllImage ), new Align( alignment:new Alignment(0, 1), child:new TabPageSelector( color: Colors.white, selectedColor: Colors.black, controller: tabController, indicatorSize:30 ) ) } ) ); } public override void initState() { base.initState(); tabController = new TabController(length: 10, vsync: this); } public override void dispose() { tabController.dispose(); base.dispose(); } }
2.添加 Ticker定时器
class MovePictoreState : SingleTickerProviderStateMixin{ public List AllImage; TabController tabController; private TimeSpan lastTime;//上次切换时间 Ticker ticker;//定时器 int index = 0;//当前Tag索引 int timeout;//间隔时间 public MovePictoreState(List allImage) { AllImage = allImage; } public override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar(title: new Container( child: new Text("轮播图实现"), alignment: Alignment.center ) ), body: new Stack( children: new List () { new TabBarView( controller: tabController, children: AllImage ), new Align( alignment:new Alignment(0, 1), child:new TabPageSelector( color: Colors.white, selectedColor: Colors.black, controller: tabController, indicatorSize:30 ) ) } ) ); } public override void initState() { base.initState(); tabController = new TabController(length: 10, vsync: this); ticker = new Ticker(tickCallback); ticker.start(); } /// /// 每帧都调用 /// /// 距离开始的时间 private void tickCallback(TimeSpan elapsed) { if (null != lastTime && elapsed.Seconds >= lastTime.Seconds) { if (elapsed.Seconds - lastTime.Seconds > timeout) { lastTime = elapsed; index++; tabController.animateTo(index % 10); } } else { lastTime = elapsed; } } public override void dispose() { tabController.dispose(); base.dispose(); } }
3、点击切换
修改 TabPageSelectorIndicator类和TabPageSelector部分方法,添加了点击回调
public class TabPageSelectorIndicator : StatelessWidget { public TabPageSelectorIndicator( System.Action<int> gestureTapCallback, int index, Key key = null, Color backgroundColor = null, Color borderColor = null, float? size = null ) : base(key: key) { D.assert(backgroundColor != null); D.assert(borderColor != null); D.assert(size != null); this.backgroundColor = backgroundColor; this.borderColor = borderColor; this.size = size.Value; this.gestureTapCallback = gestureTapCallback; this.Index = index; } public readonly Color backgroundColor; public readonly int Index; public readonly Color borderColor; public readonly float size; System.Action<int> gestureTapCallback; public override Widget build(BuildContext context) { return new GestureDetector( child: new Container( width: this.size, height: this.size, margin: EdgeInsets.all(4.0f), decoration: new BoxDecoration( color: this.backgroundColor, border: Border.all(color: this.borderColor), shape: BoxShape.circle ) ), onTap: () => { if (null != gestureTapCallback) { gestureTapCallback.Invoke(Index); } } ); } } public class TabPageSelector : StatelessWidget { private System.Action<int> iconClick; public TabPageSelector( System.Action<int> iconClick = null, Key key = null, TabController controller = null, float indicatorSize = 12.0f, Color color = null, Color selectedColor = null ) : base(key: key) { D.assert(indicatorSize > 0.0f); this.controller = controller; this.indicatorSize = indicatorSize; this.color = color; this.selectedColor = selectedColor; this.iconClick = iconClick; } public readonly TabController controller; public readonly float indicatorSize; public readonly Color color; public readonly Color selectedColor; Widget _buildTabIndicator( int tabIndex, TabController tabController, ColorTween selectedColorTween, ColorTween previousColorTween) { Color background = null; if (tabController.indexIsChanging) { float t = 1.0f - TabsUtils._indexChangeProgress(tabController); if (tabController.index == tabIndex) { background = selectedColorTween.lerp(t); } else if (tabController.previousIndex == tabIndex) { background = previousColorTween.lerp(t); } else { background = selectedColorTween.begin; } } else { float offset = tabController.offset; if (tabController.index == tabIndex) { background = selectedColorTween.lerp(1.0f - offset.abs()); } else if (tabController.index == tabIndex - 1 && offset > 0.0) { background = selectedColorTween.lerp(offset); } else if (tabController.index == tabIndex + 1 && offset < 0.0) { background = selectedColorTween.lerp(-offset); } else { background = selectedColorTween.begin; } } return new TabPageSelectorIndicator(iconClick, tabIndex, backgroundColor: background, borderColor: selectedColorTween.end, size: this.indicatorSize ); } public override Widget build(BuildContext context) { Color fixColor = this.color ?? Colors.transparent; Color fixSelectedColor = this.selectedColor ?? Theme.of(context).accentColor; ColorTween selectedColorTween = new ColorTween(begin: fixColor, end: fixSelectedColor); ColorTween previousColorTween = new ColorTween(begin: fixSelectedColor, end: fixColor); TabController tabController = this.controller ?? DefaultTabController.of(context); D.assert(() => { if (tabController == null) { throw new UIWidgetsError( "No TabController for " + this.GetType() + ".\n" + "When creating a " + this.GetType() + ", you must either provide an explicit TabController " + "using the \"controller\" property, or you must ensure that there is a " + "DefaultTabController above the " + this.GetType() + ".\n" + "In this case, there was neither an explicit controller nor a default controller." ); } return true; }); Animation<float> animation = new CurvedAnimation( parent: tabController.animation, curve: Curves.fastOutSlowIn ); return new AnimatedBuilder( animation: animation, builder: (BuildContext subContext, Widget child) => { Listchildren = new List (); for (int tabIndex = 0; tabIndex < tabController.length; tabIndex++) { children.Add(this._buildTabIndicator( tabIndex, tabController, selectedColorTween, previousColorTween) ); } return new Row( mainAxisSize: MainAxisSize.min, children: children ); } ); } }
class MovePictoreState : SingleTickerProviderStateMixin{ public List AllImage; TabController tabController; private TimeSpan lastTime;//上次切换时间 Ticker ticker;//定时器 int index = 0;//当前Tag索引 int timeout=2;//间隔时间 bool isClick;//是否点击 public MovePictoreState(List allImage) { AllImage = allImage; } void click(int i) { isClick = true; index = i; tabController.animateTo(index); } public override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar(title: new Container( child: new Text("轮播图实现"), alignment: Alignment.center ) ), body: new Stack( children: new List () { new TabBarView( controller: tabController, children: AllImage ), new Align( alignment:new Alignment(0, 1), child:new TabPageSelector( iconClick:click, color: Colors.white, selectedColor: Colors.black, controller: tabController, indicatorSize:30 ) ) } ) ); } public override void initState() { base.initState(); tabController = new TabController(length: AllImage.Count, vsync: this); ticker = new Ticker(tickCallback); ticker.start(); } /// /// 每帧都调用 /// /// 距离开始的时间 private void tickCallback(TimeSpan elapsed) { if (isClick) { //如何如果点击就跳过本次计时 lastTime = elapsed; isClick = false; } else { if (null != lastTime && elapsed.Seconds >= lastTime.Seconds) { if (elapsed.Seconds - lastTime.Seconds > timeout) { lastTime = elapsed; index++; tabController.animateTo(index % AllImage.Count); } } else { lastTime = elapsed; } } } public override void dispose() { tabController.dispose(); base.dispose(); } }
4,完善版
public class MovePictore : StatefulWidget { ListAllImage; int timeout; public MovePictore(List allImage, int timeout = 1) { AllImage = allImage; this.timeout = timeout; } public override State createState() { return new MovePictoreState(AllImage, timeout); } } class MovePictoreState : SingleTickerProviderStateMixin { public List AllImage; TabController tabController; private TimeSpan lastTime;//上次切换时间 Ticker ticker;//定时器 int index = 0;//当前Tag索引 int timeout = 1;//间隔时间 bool isClick;//是否点击 public MovePictoreState(List allImage, int timeout = 1) { AllImage = allImage; this.timeout = timeout; } void click(int i) { isClick = true; index = i; tabController.animateTo(index); } public override Widget build(BuildContext context) { return new Stack( children: new List () { new TabBarView( controller: tabController, children: AllImage ), new Align( alignment:new Alignment(0, 1), child:new TabPageSelector( iconClick:click, color: Colors.white, selectedColor: Colors.black, controller: tabController, indicatorSize:30 ) ) } ); } public override void initState() { base.initState(); tabController = new TabController(length: AllImage.Count, vsync: this); ticker = new Ticker(tickCallback); ticker.start(); } /// /// 每帧都调用 /// /// 距离开始的时间 private void tickCallback(TimeSpan elapsed) { if (isClick) { //如何如果点击就跳过本次计时 lastTime = elapsed; isClick = false; } else { if (null != lastTime && elapsed.Seconds >= lastTime.Seconds) { if (elapsed.Seconds - lastTime.Seconds > timeout) { lastTime = elapsed; index++; tabController.animateTo(index % AllImage.Count); } } else { lastTime = elapsed; } } } public override void dispose() { tabController.dispose(); ticker.stop(); ticker.dispose(); base.dispose(); } }