Reputation: 223
I am trying to program a weekview like in the google calendar for flutter. I want to display a timetable where the events begin and end at individual times (e.g. 9:34, 17:11) and at exactly the times they should be displayed in the calendar. So not rounded up or down to the full hour as I currently implemented it with a table widget.
What would be the best way to achieve such an view. I don't know where to start. The horizontal scrolling itself isn't so important. But the vertical one is my problem. How do I place these event widgets at a specific position in a scrollable list?
I appreciate every kind of answer. It would help me very much.
Upvotes: 3
Views: 7867
Reputation: 1536
I'm a bit late here but I've created a library that can offer you exactly what you want :
It's called FlutterWeekView and here are some links if you're still interested :
Preview :
Upvotes: 0
Reputation: 30103
Here is a poor mans version, using a CustomScrollView
and simple Stack
s with Positioned
children.
Things are getting more difficult if you also want horizontal scrolling. For really complex layouts with animations, you may need a custom layout.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Playground',
home: TestPage(),
);
}
}
class TestPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Calendar'),
),
body: WeekView(),
);
}
}
const headerHeight = 50.0;
const hourHeight = 100.0;
class WeekView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: <Widget>[
SliverPersistentHeader(
delegate: WeekViewHeaderDelegate(),
pinned: true,
),
SliverToBoxAdapter(
child: _buildGrid(),
)
],
);
}
Widget _buildGrid() {
return SizedBox(
height: hourHeight * 24,
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: List.generate(7, (d) => _buildColumn(d)),
),
);
}
Widget _buildColumn(int d) {
return Expanded(
child: Stack(
children: <Widget>[
Positioned(
left: 0.0,
top: d * 25.0,
right: 0.0,
height: 50.0 * (d + 1),
child: Container(
margin: EdgeInsets.symmetric(horizontal: 2.0),
color: Colors.orange[100 + d * 100],
),
)
],
),
);
}
}
class WeekViewHeaderDelegate extends SliverPersistentHeaderDelegate {
@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
return Container(
color: Colors.red.withOpacity(0.5),
child: Center(
child: Text('HEADER'),
),
);
}
@override
double get maxExtent => headerHeight;
@override
double get minExtent => headerHeight;
@override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
return false;
}
}
Upvotes: 6