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 5c30cc0
Show file tree
Hide file tree
Showing 16 changed files with 284 additions and 84 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
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
14 changes: 10 additions & 4 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 Down Expand Up @@ -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
33 changes: 31 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,14 +15,27 @@ 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,
),
onTimestampTap: (date) {
SnackBar snackBar = SnackBar(
Expand All @@ -45,4 +59,19 @@ 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
36 changes: 22 additions & 14 deletions lib/src/components/day_view_components.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import 'package:flutter/material.dart';

import '../calendar_event_data.dart';
import '../constants.dart';
import '../extensions.dart';
import '../typedefs.dart';

Expand Down Expand Up @@ -63,7 +64,6 @@ class RoundedEventTile extends StatelessWidget {
borderRadius: borderRadius,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
if (title.isNotEmpty)
Expand Down Expand Up @@ -97,6 +97,7 @@ class RoundedEventTile extends StatelessWidget {
Expanded(
child: Text(
"+${totalEvents - 1} more",
textAlign: TextAlign.center,
style: (descriptionStyle ??
TextStyle(
color: backgroundColor.accent.withAlpha(200),
Expand Down Expand Up @@ -134,17 +135,19 @@ class DefaultTimeLineMark extends StatelessWidget {
final timeString = (timeStringBuilder != null)
? timeStringBuilder!(date)
: date.minute != 0
? "$hour:${date.minute}"
: "$hour ${date.hour ~/ 12 == 0 ? "am" : "pm"}";
? "${Constants.ltr}$hour:${date.minute}"
: "${Constants.ltr}$hour ${date.hour ~/ 12 == 0 ? "am" : "pm"}";
return Transform.translate(
offset: Offset(0, -7.5),
child: Padding(
padding: const EdgeInsets.only(right: 7.0),
padding: const EdgeInsets.only(right: 7.0, left: 7.0),
child: Text(
timeString,
textAlign: TextAlign.right,
textAlign: Directionality.of(context) == TextDirection.ltr
? TextAlign.right
: TextAlign.left,
style: markingStyle ??
TextStyle(
const TextStyle(
fontSize: 15.0,
),
),
Expand Down Expand Up @@ -212,14 +215,19 @@ class FullDayEventView<T> extends StatelessWidget {
margin: const EdgeInsets.all(5.0),
padding: const EdgeInsets.all(1.0),
height: 24,
child: Text(
events[index].title,
style: titleStyle ??
TextStyle(
fontSize: 16,
color: events[index].color.accent,
),
maxLines: 1,
child: Align(
alignment: Directionality.of(context) == TextDirection.ltr
? Alignment.centerLeft
: Alignment.centerRight,
child: Text(
events[index].title,
style: titleStyle ??
TextStyle(
fontSize: 16,
color: events[index].color.accent,
),
maxLines: 1,
),
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
Expand Down
1 change: 1 addition & 0 deletions lib/src/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class Constants {

static final Random _random = Random();
static final int _maxColor = 256;
static final ltr = '\u202A'; // Use this to force text direction LTR

static const int hoursADay = 24;
static const int minutesADay = 1440;
Expand Down
7 changes: 6 additions & 1 deletion lib/src/day_view/_internal_day_view_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ class _InternalDayViewPageState<T extends Object?>
widget.halfHourIndicatorSettings.dashSpaceWidth,
startHour: widget.startHour,
endHour: widget.endHour,
textDirection: Directionality.of(context),
),
),
if (widget.showQuarterHours)
Expand All @@ -287,6 +288,8 @@ class _InternalDayViewPageState<T extends Object?>
widget.quarterHourIndicatorSettings.dashWidth,
dashSpaceWidth: widget
.quarterHourIndicatorSettings.dashSpaceWidth,
textDirection: Directionality.of(context),
timelineWidth: widget.timeLineWidth,
),
),
widget.dayDetectorBuilder(
Expand All @@ -297,7 +300,9 @@ class _InternalDayViewPageState<T extends Object?>
minuteSlotSize: widget.minuteSlotSize,
),
Align(
alignment: Alignment.centerRight,
alignment: Directionality.of(context) == TextDirection.ltr
? Alignment.centerRight
: Alignment.centerLeft,
child: EventGenerator<T>(
height: widget.height,
date: widget.date,
Expand Down
6 changes: 5 additions & 1 deletion lib/src/day_view/day_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,7 @@ class DayViewState<T extends Object?> extends State<DayView<T>> {
_halfHourIndicatorSettings = widget.halfHourIndicatorSettings ??
HourIndicatorSettings(
height: widget.heightPerMinute,
lineStyle: LineStyle.dashed,
color: Constants.defaultBorderColor,
offset: 5,
);
Expand Down Expand Up @@ -731,10 +732,13 @@ class DayViewState<T extends Object?> extends State<DayView<T>> {
int startHour,
int endHour,
) {
final directionality = Directionality.of(context);
return HourLinePainter(
lineColor: lineColor,
lineHeight: lineHeight,
offset: offset,
timelineWidth: widget.timeLineWidth,
textDirection: directionality,
offset: directionality == TextDirection.ltr ? offset : 0,
minuteHeight: minuteHeight,
verticalLineOffset: verticalLineOffset,
showVerticalLine: showVerticalLine,
Expand Down
Loading

0 comments on commit 5c30cc0

Please sign in to comment.