Skip to content

Commit

Permalink
feat: Fixes issue #412: ✨ Add support for RTL directionality
Browse files Browse the repository at this point in the history
  • Loading branch information
shubham-jitiya-simform committed Jan 17, 2025
1 parent 469cc29 commit 501518b
Show file tree
Hide file tree
Showing 18 changed files with 402 additions and 131 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# [1.4.1 - Unreleased]

- Adds clear method to `EventController`.
- Adds support of directionality. [#412](https://github.com/SimformSolutionsPvtLtd/flutter_calendar_view/issues/412)

# [1.4.0 - 7 Jan 2025](https://github.com/SimformSolutionsPvtLtd/flutter_calendar_view/tree/1.4.0)

Expand Down
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -352,9 +352,30 @@ WeekView(
],
);
```

Above code will create `WeekView` with only five days, from monday to friday.

### Support for RTL
Wrap your widget with `Directionality` widget and use `textDirection` to give RTL or LTR direction.

```dart
Directionality(
textDirection: TextDirection.rtl,
child: ResponsiveWidget(
webWidget: WebHomePage(
selectedView: CalendarView.week,
),
mobileWidget: Scaffold(
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
elevation: 8,
onPressed: () => context.pushRoute(CreateEventPage()),
),
body: WeekViewWidget(),
),
),
);
```

## Main Contributors

<table>
Expand Down
1 change: 1 addition & 0 deletions example/lib/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class AppConstants {
AppConstants._();

static final List<String> weekTitles = ['M', 'T', 'W', 'T', 'F', 'S', 'S'];
static final ltr = '\u202A'; // Use this to force text direction to LTR

static OutlineInputBorder inputBorder = OutlineInputBorder(
borderRadius: BorderRadius.circular(7),
Expand Down
74 changes: 40 additions & 34 deletions example/lib/pages/create_event_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,44 +12,50 @@ class CreateEventPage extends StatelessWidget {

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
centerTitle: false,
leading: IconButton(
onPressed: context.pop,
icon: Icon(
Icons.arrow_back,
color: AppColors.black,
// TODO(Shubham): Remove temporary Directionality widget
return Directionality(
textDirection: TextDirection.rtl,
child: Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
centerTitle: false,
leading: IconButton(
onPressed: context.pop,
icon: Icon(
Icons.arrow_back,
color: AppColors.black,
),
),
),
title: Text(
event == null ? "Create New Event" : "Update Event",
style: TextStyle(
color: AppColors.black,
fontSize: 20.0,
fontWeight: FontWeight.bold,
title: Text(
event == null ? "Create New Event" : "Update Event",
style: TextStyle(
color: AppColors.black,
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
),
),
body: SingleChildScrollView(
physics: ClampingScrollPhysics(),
child: Padding(
padding: EdgeInsets.all(20.0),
child: AddOrEditEventForm(
onEventAdd: (newEvent) {
if (this.event != null) {
CalendarControllerProvider.of(context)
.controller
.update(this.event!, newEvent);
} else {
CalendarControllerProvider.of(context).controller.add(newEvent);
}
body: SingleChildScrollView(
physics: ClampingScrollPhysics(),
child: Padding(
padding: EdgeInsets.all(20.0),
child: AddOrEditEventForm(
onEventAdd: (newEvent) {
if (this.event != null) {
CalendarControllerProvider.of(context)
.controller
.update(this.event!, newEvent);
} else {
CalendarControllerProvider.of(context)
.controller
.add(newEvent);
}

context.pop(true);
},
event: event,
context.pop(true);
},
event: event,
),
),
),
),
Expand Down
10 changes: 7 additions & 3 deletions example/lib/pages/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ class HomePage extends StatelessWidget {

@override
Widget build(BuildContext context) {
return ResponsiveWidget(
mobileWidget: MobileHomePage(),
webWidget: WebHomePage(),
// TODO(Shubham): Remove temporary wrapped widget
return Directionality(
textDirection: TextDirection.rtl,
child: ResponsiveWidget(
mobileWidget: MobileHomePage(),
webWidget: WebHomePage(),
),
);
}
}
28 changes: 14 additions & 14 deletions example/lib/widgets/add_event_form.dart
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class _AddOrEditEventFormState extends State<AddOrEditEventForm> {
key: _form,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
controller: _titleController,
Expand Down Expand Up @@ -255,15 +256,12 @@ class _AddOrEditEventFormState extends State<AddOrEditEventForm> {
hintText: "Event Description",
),
),
Align(
alignment: Alignment.centerLeft,
child: Text(
'Repeat',
style: TextStyle(
color: AppColors.black,
fontWeight: FontWeight.w500,
fontSize: 17,
),
Text(
'Repeat',
style: TextStyle(
color: AppColors.black,
fontWeight: FontWeight.w500,
fontSize: 17,
),
),
Row(
Expand Down Expand Up @@ -392,7 +390,7 @@ class _AddOrEditEventFormState extends State<AddOrEditEventForm> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Reoccurrence ends on: ',
'${AppConstants.ltr}Reoccurrence ends on: ',
style: TextStyle(
color: AppColors.black,
fontWeight: FontWeight.w500,
Expand Down Expand Up @@ -519,7 +517,7 @@ class _AddOrEditEventFormState extends State<AddOrEditEventForm> {
Row(
children: [
Text(
"Event Color: ",
"${AppConstants.ltr}Event Color: ",
style: TextStyle(
color: AppColors.black,
fontSize: 17,
Expand All @@ -537,9 +535,11 @@ class _AddOrEditEventFormState extends State<AddOrEditEventForm> {
SizedBox(
height: 15,
),
CustomButton(
onTap: _createEvent,
title: widget.event == null ? "Add Event" : "Update Event",
Center(
child: CustomButton(
onTap: _createEvent,
title: widget.event == null ? "Add Event" : "Update Event",
),
),
],
),
Expand Down
5 changes: 3 additions & 2 deletions example/lib/widgets/calendar_configs.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:calendar_view/calendar_view.dart';
import 'package:example/constants.dart';
import 'package:flutter/material.dart';

import '../app_colors.dart';
Expand Down Expand Up @@ -43,7 +44,7 @@ class CalendarConfig extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Active View:",
"${AppConstants.ltr}Active View:",
style: TextStyle(
fontSize: 20.0,
color: AppColors.black,
Expand Down Expand Up @@ -89,7 +90,7 @@ class CalendarConfig extends StatelessWidget {
height: 40,
),
Text(
"Add Event: ",
"${AppConstants.ltr}Add Event: ",
style: TextStyle(
fontSize: 20.0,
color: AppColors.black,
Expand Down
22 changes: 14 additions & 8 deletions example/lib/widgets/day_view_widget.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:calendar_view/calendar_view.dart';
import 'package:example/constants.dart';
import 'package:flutter/material.dart';

import '../pages/event_details_page.dart';
Expand All @@ -23,7 +24,10 @@ class DayViewWidget extends StatelessWidget {
heightPerMinute: 3,
timeLineBuilder: _timeLineBuilder,
scrollPhysics: const BouncingScrollPhysics(),
eventArranger: SideEventArranger(maxWidth: 30),
eventArranger: SideEventArranger(
maxWidth: 30,
directionality: Directionality.of(context),
),
hourIndicatorSettings: HourIndicatorSettings(
color: Theme.of(context).dividerColor,
),
Expand All @@ -43,14 +47,14 @@ class DayViewWidget extends StatelessWidget {
),
);
},
onEventLongTap: (events, date) {
SnackBar snackBar = SnackBar(content: Text("on LongTap"));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
},
halfHourIndicatorSettings: HourIndicatorSettings(
color: Theme.of(context).dividerColor,
lineStyle: LineStyle.dashed,
),
onEventLongTap: (events, date) {
SnackBar snackBar = SnackBar(content: Text("on LongTap"));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
},
verticalLineOffset: 0,
timeLineWidth: 65,
showLiveTimeLineInAllDays: true,
Expand All @@ -71,9 +75,10 @@ class DayViewWidget extends StatelessWidget {
Positioned.fill(
top: -8,
right: 8,
left: 8,
child: Text(
"${date.hour}:${date.minute}",
textAlign: TextAlign.right,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black.withAlpha(50),
fontStyle: FontStyle.italic,
Expand All @@ -92,9 +97,10 @@ class DayViewWidget extends StatelessWidget {
Positioned.fill(
top: -8,
right: 8,
left: 8,
child: Text(
"$hour ${date.hour ~/ 12 == 0 ? "am" : "pm"}",
textAlign: TextAlign.right,
"${AppConstants.ltr} $hour ${date.hour ~/ 12 == 0 ? "am" : "pm"}",
textAlign: TextAlign.center,
),
),
],
Expand Down
41 changes: 39 additions & 2 deletions example/lib/widgets/week_view_widget.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:calendar_view/calendar_view.dart';
import 'package:example/constants.dart';
import 'package:flutter/material.dart';

import '../pages/event_details_page.dart';
Expand All @@ -14,15 +15,37 @@ class WeekViewWidget extends StatelessWidget {
return WeekView(
key: state,
width: width,
headerStringBuilder: (DateTime date, {DateTime? secondaryDate}) =>
_weekStringBuilder(
date,
secondaryDate: secondaryDate,
textDirection: Directionality.of(context),
),
showWeekends: true,
showLiveTimeLineInAllDays: true,
eventArranger: SideEventArranger(maxWidth: 30),
timeLineWidth: 65,
eventArranger: SideEventArranger(
maxWidth: 30,
directionality: Directionality.of(context),
),
timeLineWidth: 68,
scrollPhysics: const BouncingScrollPhysics(),
liveTimeIndicatorSettings: LiveTimeIndicatorSettings(
color: Colors.redAccent,
timeBackgroundViewWidth: 68,
offset: 0,
showTime: true,
showBullet: true,
showTimeBackgroundView: true,
),
// halfHourIndicatorSettings: HourIndicatorSettings(
// lineStyle: LineStyle.solid,
// color: Colors.red,
// ),
// hourIndicatorSettings: HourIndicatorSettings(
// lineStyle: LineStyle.dashed,
// dashSpaceWidth: 4,
// // color: Colors.red,
// ),
onTimestampTap: (date) {
SnackBar snackBar = SnackBar(
content: Text("On tap: ${date.hour} Hr : ${date.minute} Min"),
Expand All @@ -45,4 +68,18 @@ class WeekViewWidget extends StatelessWidget {
},
);
}

// TODO(Shubham): Include in readme to guide how to support RTL for string like below
String _weekStringBuilder(DateTime date,
{DateTime? secondaryDate, TextDirection? textDirection}) {
final dateString = "${date.day} / ${date.month} / ${date.year}";
final secondaryDateString = secondaryDate != null
? "${secondaryDate.day} / ${secondaryDate.month} / ${secondaryDate.year}"
: "";
if (textDirection == TextDirection.rtl) {
return "${AppConstants.ltr}${secondaryDateString} to ${dateString}";
} else {
return "${AppConstants.ltr}${dateString} to ${secondaryDateString}";
}
}
}
9 changes: 8 additions & 1 deletion lib/src/components/_internal_components.dart
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ class _LiveTimeIndicatorState extends State<LiveTimeIndicator> {
/// to set dy offset of live time indicator
final startMinutes = widget.startHour * 60;

/// To support LTR & RTL we need to manage X position of point-1 to draw line
/// according to position of timeline add and subtract its width
final offsetX = Directionality.of(context) == TextDirection.ltr
? widget.liveTimeIndicatorSettings.offset + widget.timeLineWidth
: widget.liveTimeIndicatorSettings.offset - widget.timeLineWidth;

/// Check if live time is not between startHour and endHour if it is then
/// don't show live time indicator
///
Expand All @@ -111,9 +117,10 @@ class _LiveTimeIndicatorState extends State<LiveTimeIndicator> {
size: Size(widget.width, widget.liveTimeIndicatorSettings.height),
painter: CurrentTimeLinePainter(
color: widget.liveTimeIndicatorSettings.color,
textDirection: Directionality.of(context),
height: widget.liveTimeIndicatorSettings.height,
offset: Offset(
widget.timeLineWidth + widget.liveTimeIndicatorSettings.offset,
offsetX,
(_currentTime.getTotalMinutes - startMinutes) *
widget.heightPerMinute,
),
Expand Down
Loading

0 comments on commit 501518b

Please sign in to comment.