I am personally developing the following Omikuji application for smartphones using Flutter.
[iOS]
https://apps.apple.com/us/app/%E5%A4%A7%E5%BE%A1%E5%BF%83%E3%82%A2%E3%83%97%E3%83%AA/id1627544916
[Android]
https://play.google.com/store/apps/details?id=jp.sikisimanomiti.oomigokoro
In developing the above application, I solved a few minor Dart & Flutter tips that I got stuck on, and I would like to add and summarize them.
- Date format conversion
- Left-align text
- BottomNavigationBarItem hides when BottomNavigationBar has four or more BottomNavigationBarItem
- Counting the number of records in SQLite
- Show Badge on icon
1. Date format conversion
I have saved the creation date and time in SQLite as, for example, “2022-04-18T00:00:00+09:00”, but I want to display it on the app in the format “yyyy/MM/dd(E) HH:mm”.
import 'package:intl/date_symbol_data_local.dart';
import "package:intl/intl.dart";
String createdAt = '2022-04-18T00:00:00+09:00'
DateFormat('yyyy/MM/dd(E) HH:mm', 'ja_JP').format(DateTime.parse(message.createdAt).toLocal());
I could convert “2022-04-18T00:00:00+09:00” to “2022/04/18(Mon) 00:00“.
2. Left-align text
I implemented the following to display text but centered the text.
Column(
children: [
Text(
'title',
style: const TextStyle(
fontWeight: FontWeight.bold
),
textAlign: TextAlign.left
),
Text('body', textAlign: TextAlign.left),
],
)
I found that the textAlign property works only if the area containing the Text widget is larger than the actual text.
And since the Text widget takes up minimal space inside the Column widget, and the crossAxisAlignment property of the Column widget defaults to center, the above implementation would be centered.
Wrapping Text widget as shown below will allow it to be left-aligned.
Column(
children: [
SizedBox(
width: double.infinity,
child: Text(
'title',
style: const TextStyle(
fontWeight: FontWeight.bold
),
textAlign: TextAlign.left
),
),
SizedBox(
width: double.infinity,
child: Text('body', textAlign: TextAlign.left),
)
],
)
3. BottomNavigationBarItem hides when BottomNavigationBar has four or more BottomNavigationBarItem
Currently (as of 7/30/2022), we are implementing a new function to notify users of updates. After adding the “Notification” icon to the BottomNavigationBar, the “Notification” icon is hidden, and when clicking on the “Notification” icon is now shown, but the “Home” icon is hidden.
I found the following specification in the official documentation.
The bottom navigation bar’s type changes how its items are displayed. If not specified, then it’s automatically set to BottomNavigationBarType.fixed when there are less than four items, and BottomNavigationBarType.shifting otherwise.
The length of items must be at least two and each item’s icon and title/label must not be null.
BottomNavigationBarType.fixed, the default when there are less than four items. The selected item is rendered with the selectedItemColor if it’s non-null, otherwise the theme’s ColorScheme.primary color is used for Brightness.light themes and ColorScheme.secondary for Brightness.dark themes. If backgroundColor is null, The navigation bar’s background color defaults to the Material background color, ThemeData.canvasColor (essentially opaque white).
The Flutter official documentation(BottomNavigationBar class)
BottomNavigationBarType.shifting, the default when there are four or more items. If selectedItemColor is null, all items are rendered in white. The navigation bar’s background color is the same as the BottomNavigationBarItem.backgroundColor of the selected item. In this case it’s assumed that each item will have a different background color and that background color will contrast well with white.
Suppose the BottomNavigationBar has four or more BottomNavigationBarItem, and the BottomNavigationBar type is not specified. In that case, the BottomNavigationBar type is automatically set to BottomNavigationBarType.shifting, and BottomNavigationBarType.shifting would render white and hide.
I set BottomNavigationBarType.fixed to BottomNavigationBar’s type and could successfully show the “Notification” icon.
4. Counting the number of records in SQLite
The above application fetches notifications from the API and stores them in the local SQLite for reading/unread messages management. The app lets users know the number of unread notifications as a badge on the icon if there are unread notifications.
To get the number of records from SQLite, Dart/Flutter uses Sqflite.firstIntValue method of the sqflite package is as follows.
import 'package:sqflite/sqflite.dart';
Future<int?> countUnreadMessage(Database db) async {
return Sqflite.firstIntValue(await db.rawQuery('SELECT COUNT(*) FROM messages where read_at IS NULL;'));
}
5. Show Badge on icon
I tried to show the notification icon with Badges to achieve the above notification function, for example, to show Badges and the following package.
However, if I use the default settings, the icon is hidden when there are 10 or 100 unread notifications.
The above package has configurable settings, so we adjusted the margins, position, and text size so that badge does not hide the icons. As a result, I could show the badge excellently.
@override
Widget build(BuildContext context) {
BadgePosition position = BadgePosition.topEnd();
if (_unreadMessageCounter! >= 10 && _unreadMessageCounter! < 100) {
position = BadgePosition.topEnd(top: -8, end: -8);
} else if (_unreadMessageCounter! >= 100) {
position = BadgePosition.topEnd(top: -8, end: -12);
}
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: 'title',
backgroundColor: const Color(0xFFF2D64B),
),
backgroundColor: const Color(0xFFF4F2EC),
body: const HomePage(),
bottomNavigationBar: BottomNavigationBar(
currentIndex: 0,
selectedItemColor: const Color(0xFFC4A50D),
type: BottomNavigationBarType.fixed,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Badge(
badgeContent: Text(_unreadMessageCounter.toString(), style: const TextStyle(color: Colors.white, fontSize: 10),),
padding: const EdgeInsets.only(top: 3, bottom: 5, left: 3, right: 3),
position: position,
showBadge: _unreadMessageCounter! > 0 ? true : false,
key: const Key('news-icon'),
child: const Icon(Icons.notifications_outlined),
),
activeIcon: Badge(
badgeContent: Text(_unreadMessageCounter.toString(), style: const TextStyle(color: Colors.white, fontSize: 10)),
padding: const EdgeInsets.only(top: 3, bottom: 5, left: 3, right: 3),
position: position,
showBadge: _unreadMessageCounter! > 0 ? true : false,
child: const Icon(Icons.notifications_outlined),
),
label: 'news',
),
]
),
);
}
コメント