插件合集:https://github.com/Solido/awesome-flutter
1.效果
2.依赖:snaplist: ^0.1.8
3.入口代码
import 'package:flutter/material.dart';
import 'package:flutter_widget_project/span_list_widget/horizontal_explicit.dart';
import 'package:flutter_widget_project/span_list_widget/horizontal_tab.dart';
import 'package:flutter_widget_project/span_list_widget/vertical_tab.dart';
import 'package:snaplist/snaplist.dart';
class SpanListPage extends StatefulWidget {
@override
_SpanListPageState createState() => _SpanListPageState();
}
class _SpanListPageState extends State<SpanListPage> with TickerProviderStateMixin{
TabController _controller ;
List<String> urls = [
"https://image.tmdb.org/t/p/w370_and_h556_bestv2/2uNW4WbgBXL25BAbXGLnLqX71Sw.jpg",
"https://image.tmdb.org/t/p/w370_and_h556_bestv2/lNkDYKmrVem1J0aAfCnQlJOCKnT.jpg",
"https://image.tmdb.org/t/p/w370_and_h556_bestv2/wrFpXMNBRj2PBiN4Z5kix51XaIZ.jpg",
"https://image.tmdb.org/t/p/w370_and_h556_bestv2/r6pPUVUKU5eIpYj4oEzidk5ZibB.jpg",
"https://image.tmdb.org/t/p/w370_and_h556_bestv2/x1txcDXkcM65gl7w20PwYSxAYah.jpg",
"https://image.tmdb.org/t/p/w370_and_h556_bestv2/ptSrT1JwZFWGhjSpYUtJaasQrh.jpg",
"https://image.tmdb.org/t/p/w370_and_h556_bestv2/wMq9kQXTeQCHUZOG4fAe5cAxyUA.jpg",
"https://image.tmdb.org/t/p/w370_and_h556_bestv2/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg",
];
@override
void initState() {
// TODO: implement initState
super.initState();
_controller = TabController(length: 3 , vsync: this);
}
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
title: Text("SpanList"),
bottom: TabBar(
tabs: <Widget>[
Tab(text: "Horizontal",),
Tab(text: "Explicit",),
Tab(text: "Vertical",),
],
),
),
body: TabBarView(
physics: NeverScrollableScrollPhysics(),
children: <Widget>[
HorizontalTab(
images: urls, loadMore: _loadMoreItems,
),
HorizontalExplicitTab(
images: urls, loadMore: _loadMoreItems,
),
VerticalTab(images: urls, loadMore: _loadMoreItems)
],
),
),
);
}
void _loadMoreItems() {
setState(() {
urls = new List.from(urls)..addAll(urls);
});
}
}
4.横向滑动
import 'package:flutter/material.dart';
import 'package:snaplist/snaplist.dart';
///
///横向滑动
///
class HorizontalTab extends StatefulWidget {
final List<String> images;
final VoidCallback loadMore;
const HorizontalTab({Key key, this.images, this.loadMore}) : super(key: key);
@override
_HorizontalTabState createState() => _HorizontalTabState();
}
class _HorizontalTabState extends State<HorizontalTab> {
@override
Widget build(BuildContext context) {
///显示内容的大小
Size cardSize = Size(300 , 460);
return SnapList(
sizeProvider: (index , data){
return cardSize;
},
///初始位置距离屏幕的距离
padding: EdgeInsets.only(left: (MediaQuery.of(context).size.width - cardSize.width)/2),
///内容之间的边距
separatorProvider: (index , data)=> Size(10 , 10 ),
///内容组件
builder: (context , index , data){
return ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(16)),
child: Image.network(widget.images[index] , fit: BoxFit.fill,),
);
},
count: widget.images.length,
///更新数据
positionUpdate: (index){
if(index == widget.images.length - 1){
widget.loadMore();
}
},
);
}
}
5。纵向滑动
import 'package:flutter/material.dart';
import 'package:snaplist/snaplist.dart';
class VerticalTab extends StatelessWidget {
final List<String> images;
final VoidCallback loadMore;
const VerticalTab({Key key, this.images, this.loadMore}) : super(key: key);
@override
Widget build(BuildContext context) {
final Size cardSize = Size(250.0, 250.0);
return SnapList(
padding: EdgeInsets.only(
top: (MediaQuery.of(context).size.height - 180 - cardSize.height) / 2),
sizeProvider: (index, data) => cardSize,
separatorProvider: (index, data) => Size(50.0, 50.0),
positionUpdate: (int index){
if(index==images.length-1){
loadMore();
}
},
builder: (context, index, data) {
return ClipOval(
child: Image.network(
images[index],
fit: BoxFit.cover,
),
);
},
count: images.length,
axis: Axis.vertical,
);
}
}
6.点击随机跳动
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:snaplist/snaplist.dart';
class HorizontalExplicitTab extends StatelessWidget {
final List<String> images;
final VoidCallback loadMore;
const HorizontalExplicitTab({Key key, this.images, this.loadMore})
: super(key: key);
@override
Widget build(BuildContext context) {
final Size cardSize = Size(300.0, 460.0);
final random = new Random();
final controller = SnaplistController(initialPosition: 2);
return Stack(
children: <Widget>[
SnapList(
padding: EdgeInsets.only(
left: (MediaQuery.of(context).size.width - cardSize.width) / 2),
sizeProvider: (index, data) => cardSize,
separatorProvider: (index, data) => Size(10.0, 10.0),
positionUpdate: (int index) {
if (index == images.length - 1) {
loadMore();
}
},
builder: (context, index, data) {
return ClipRRect(
borderRadius: new BorderRadius.circular(16.0),
child: Image.network(
images[index],
fit: BoxFit.fill,
),
);
},
count: images.length,
snaplistController: controller,
),
///随机跳转
Positioned(
child: FloatingActionButton(
child: Icon(Icons.adjust),
onPressed: () =>
controller.setPosition(random.nextInt(images.length)),
),
bottom: 10,
right: 10,
)
],
);
}
}