我正在设法实现共面/不规则的卡片收集布局。这是关于材料设计文档https://imgur.com/miHhpFs
上的卡片布局的我尝试使用GridView.count布局,但无法弄清楚如何取消项目。我还发现,有一些用户创建的库,例如https://pub.dev/packages/flutter_staggered_grid_view,可以为我想做的事情提供帮助,但是我更喜欢一种正式的解决方案,因为这种布局在材料设计文档中。
答案 0 :(得分:0)
我不知道创建此文件的“官方解决方案”是什么,但我相信这将类似于“使用三个滚动控制器创建三个列表视图,其中一个与其他两个偏移,然后同步其滚动控制器,说明偏移量。”
我不知道这是否行得通,所以我创建了此dartpad进行测试: https://dartpad.dev/f9c8f00b78899d3c8c4a426d3466a8a3
以防万一飞镖无法正常工作,这是我使用的代码:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: ScrollSync(),
);
}
}
class ScrollSync extends StatefulWidget {
@override
_ScrollSyncState createState() => _ScrollSyncState();
}
class _ScrollSyncState extends State<ScrollSync> {
CustomScrollController _controller1 =
CustomScrollController(keepScrollOffset: true);
CustomScrollController _controller2 = CustomScrollController(
initialScrollOffset: 150.0, keepScrollOffset: true);
CustomScrollController _controller3 =
CustomScrollController(keepScrollOffset: true);
@override
void initState() {
_controller1.addListener(() =>
_controller2.jumpToWithoutGoingIdleAndKeepingBallistic(
_controller1.offset, "1 listen 2"));
_controller1.addListener(() =>
_controller3.jumpToWithoutGoingIdleAndKeepingBallistic(
_controller1.offset, "1 listen 3"));
_controller2.addListener(() =>
_controller1.jumpToWithoutGoingIdleAndKeepingBallistic(
_controller2.offset, "2 listen 1"));
_controller2.addListener(() =>
_controller3.jumpToWithoutGoingIdleAndKeepingBallistic(
_controller2.offset, "2 listen 3"));
_controller3.addListener(() =>
_controller1.jumpToWithoutGoingIdleAndKeepingBallistic(
_controller3.offset, "3 listen 1"));
_controller3.addListener(() =>
_controller2.jumpToWithoutGoingIdleAndKeepingBallistic(
_controller3.offset, "3 listen 2"));
super.initState();
}
@override
void dispose() {
_controller1.dispose();
_controller2.dispose();
_controller3.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Scroll Sync"),
),
body: Row(
children: [
Flexible(
flex: 1,
child: ListView.builder(
controller: _controller1,
scrollDirection: Axis.vertical,
itemBuilder: (_, index) => Container(
color: Colors.blueGrey,
width: 150,
height: 300,
margin: EdgeInsets.all(10.0),
child: Center(
child: Text(
"$index",
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.display2,
),
),
),
),
),
Flexible(
flex: 1,
child: ListView.builder(
controller: _controller2,
itemBuilder: (_, index) => Container(
height: 300,
color: Colors.blueGrey,
margin: EdgeInsets.all(10.0),
child: Center(
child: Text(
"$index",
style: Theme.of(context)
.textTheme
.display2
.copyWith(color: Colors.white),
),
),
),
),
),
Flexible(
flex: 1,
child: ListView.builder(
controller: _controller3,
itemBuilder: (_, index) => Container(
height: 300,
color: Colors.blueGrey,
margin: EdgeInsets.all(10.0),
child: Center(
child: Text(
"$index",
style: Theme.of(context)
.textTheme
.display2
.copyWith(color: Colors.black),
),
),
),
),
),
],
),
);
}
}
class CustomScrollController extends ScrollController {
CustomScrollController(
{double initialScrollOffset = 0.0,
keepScrollOffset = true,
debugLabel,
String controller})
: super(
initialScrollOffset: initialScrollOffset,
keepScrollOffset: keepScrollOffset,
debugLabel: debugLabel,
);
@override
_SilentScrollPosition createScrollPosition(
ScrollPhysics physics,
ScrollContext context,
ScrollPosition oldPosition,
) {
return _SilentScrollPosition(
physics: physics,
context: context,
oldPosition: oldPosition,
initialPixels: initialScrollOffset,
);
}
void jumpToWithoutGoingIdleAndKeepingBallistic(
double value, String controller) {
assert(positions.isNotEmpty, 'ScrollController not attached.');
for (_SilentScrollPosition position
in new List<ScrollPosition>.from(positions))
position.jumpToWithoutGoingIdleAndKeepingBallistic(value, controller);
}
}
class _SilentScrollPosition extends ScrollPositionWithSingleContext {
_SilentScrollPosition({
ScrollPhysics physics,
ScrollContext context,
ScrollPosition oldPosition,
double initialPixels,
}) : super(
physics: physics,
context: context,
oldPosition: oldPosition,
initialPixels: initialPixels,
);
void jumpToWithoutGoingIdleAndKeepingBallistic(
double value, String controller) {
print(controller);
print(value);
print(pixels);
if (controller[0] == "2") {
if (pixels + 150.0 != value) {
forcePixels(value - 150.0);
}
} else if (controller[9] == "2") {
if (pixels - 150.0 != value) {
forcePixels(value + 150.0);
}
} else if (pixels != value) {
forcePixels(value);
}
}
}