Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 4dada26

Browse files
Create dark mode support
1 parent c614091 commit 4dada26

File tree

9 files changed

+232
-96
lines changed

9 files changed

+232
-96
lines changed

‎lib/app.dart

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_news_app/feature/presentation/page/home/home_page.dart';
3+
import 'package:hive/hive.dart';
4+
import 'package:hive_flutter/hive_flutter.dart';
35

46
class App extends StatelessWidget {
57
@override
68
Widget build(BuildContext context) {
7-
return MaterialApp(
8-
debugShowCheckedModeBanner: false,
9-
title: 'News App',
10-
home: HomePage(),
9+
return ValueListenableBuilder(
10+
valueListenable: Hive.box('settings').listenable(),
11+
builder: (context, box, widget) {
12+
var isDarkMode = box.get('darkMode') ?? false;
13+
return MaterialApp(
14+
debugShowCheckedModeBanner: false,
15+
title: 'News App',
16+
theme: ThemeData(
17+
brightness: isDarkMode ? Brightness.dark : Brightness.light,
18+
),
19+
home: HomePage(),
20+
);
21+
},
1122
);
1223
}
1324
}

‎lib/feature/presentation/page/home/home_page.dart

Lines changed: 89 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@ import 'package:flutter_news_app/feature/data/model/categorynews/category_news_m
88
import 'package:flutter_news_app/feature/data/model/topheadlinesnews/top_headlines_news_response_model.dart';
99
import 'package:flutter_news_app/feature/presentation/bloc/topheadlinesnews/bloc.dart';
1010
import 'package:flutter_news_app/feature/presentation/page/search/search_page.dart';
11+
import 'package:flutter_news_app/feature/presentation/page/settings/settings_page.dart';
1112
import 'package:flutter_news_app/feature/presentation/widget/widget_failure_message.dart';
1213
import 'package:flutter_news_app/feature/presentation/widget/widget_item_news.dart';
1314
import 'package:flutter_news_app/injection_container.dart';
1415
import 'package:flutter_screenutil/flutter_screenutil.dart';
16+
import 'package:hive/hive.dart';
17+
import 'package:hive_flutter/hive_flutter.dart';
1518
import 'package:intl/intl.dart';
1619
import 'package:url_launcher/url_launcher.dart';
1720

@@ -76,62 +79,87 @@ class _HomePageState extends State<HomePage> {
7679
}
7780
}
7881
},
79-
child: Stack(
80-
children: [
81-
Container(
82-
width: double.infinity,
83-
height: double.infinity,
84-
color: Color(0xFFEFF5F5),
85-
),
86-
SafeArea(
87-
child: Container(
88-
width: double.infinity,
89-
color: Color(0xFFEFF5F5),
90-
padding: EdgeInsets.symmetric(
91-
vertical: 24.h,
82+
child: ValueListenableBuilder(
83+
valueListenable: Hive.box('settings').listenable(),
84+
builder: (context, box, widget) {
85+
var isDarkMode = box.get('darkMode') ?? false;
86+
return Stack(
87+
children: [
88+
Container(
89+
width: double.infinity,
90+
height: double.infinity,
91+
color: isDarkMode ? null : Color(0xFFEFF5F5),
9292
),
93-
child: Column(
94-
crossAxisAlignment: CrossAxisAlignment.start,
95-
children: <Widget>[
96-
Padding(
97-
padding: EdgeInsets.symmetric(horizontal: 48.w),
98-
child: Row(
99-
children: <Widget>[
100-
Expanded(
101-
child: Text(
102-
'Daily News',
103-
style: TextStyle(
104-
fontSize: 48.sp,
93+
SafeArea(
94+
child: Container(
95+
width: double.infinity,
96+
color: isDarkMode ? null : Color(0xFFEFF5F5),
97+
padding: EdgeInsets.symmetric(
98+
vertical: 24.h,
99+
),
100+
child: Column(
101+
crossAxisAlignment: CrossAxisAlignment.start,
102+
children: <Widget>[
103+
Padding(
104+
padding: EdgeInsets.symmetric(horizontal: 48.w),
105+
child: Row(
106+
children: <Widget>[
107+
Expanded(
108+
child: Text(
109+
'Daily News',
110+
style: TextStyle(
111+
fontSize: 48.sp,
112+
),
113+
),
105114
),
106-
),
107-
),
108-
GestureDetector(
109-
onTap: () {
110-
Navigator.push(
111-
context,
112-
MaterialPageRoute(builder: (context) => SearchPage()),
113-
);
114-
},
115-
child: Hero(
116-
tag: 'iconSearch',
117-
child: Icon(Icons.search),
118-
),
115+
GestureDetector(
116+
onTap: () {
117+
Navigator.push(
118+
context,
119+
MaterialPageRoute(builder: (context) => SearchPage()),
120+
);
121+
},
122+
child: Hero(
123+
tag: 'iconSearch',
124+
child: Icon(
125+
Icons.search,
126+
size: 64.w,
127+
),
128+
),
129+
),
130+
SizedBox(width: 48.w),
131+
GestureDetector(
132+
onTap: () {
133+
Navigator.push(
134+
context,
135+
MaterialPageRoute(
136+
builder: (context) => SettingsPage(),
137+
),
138+
);
139+
},
140+
child: Icon(
141+
Icons.settings,
142+
size: 64.w,
143+
),
144+
),
145+
],
119146
),
120-
],
121-
),
122-
),
123-
WidgetDateToday(),
124-
SizedBox(height: 24.h),
125-
WidgetCategoryNews(listCategories: listCategories),
126-
SizedBox(height: 24.h),
127-
Expanded(
128-
child: Platform.isIOS ? _buildWidgetContentNewsIOS() : _buildWidgetContentNewsAndroid(),
147+
),
148+
WidgetDateToday(),
149+
SizedBox(height: 24.h),
150+
WidgetCategoryNews(
151+
listCategories: listCategories, indexDefaultSelected: indexCategorySelected),
152+
SizedBox(height: 24.h),
153+
Expanded(
154+
child: Platform.isIOS ? _buildWidgetContentNewsIOS() : _buildWidgetContentNewsAndroid(),
155+
),
156+
],
129157
),
130-
],
158+
),
131159
),
132-
),
133-
),
134-
],
160+
],
161+
);
162+
},
135163
),
136164
),
137165
),
@@ -404,8 +432,12 @@ class _HomePageState extends State<HomePage> {
404432

405433
class WidgetCategoryNews extends StatefulWidget {
406434
final List<CategoryNewsModel> listCategories;
435+
final int indexDefaultSelected;
407436

408-
WidgetCategoryNews({@required this.listCategories});
437+
WidgetCategoryNews({
438+
@required this.listCategories,
439+
@required this.indexDefaultSelected,
440+
});
409441

410442
@override
411443
_WidgetCategoryNewsState createState() => _WidgetCategoryNewsState();
@@ -416,7 +448,7 @@ class _WidgetCategoryNewsState extends State<WidgetCategoryNews> {
416448

417449
@override
418450
void initState() {
419-
indexCategorySelected = 0;
451+
indexCategorySelected = widget.indexDefaultSelected;
420452
super.initState();
421453
}
422454

@@ -439,12 +471,11 @@ class _WidgetCategoryNewsState extends State<WidgetCategoryNews> {
439471
if (indexCategorySelected == index) {
440472
return;
441473
}
442-
setState(() {
443-
indexCategorySelected = index;
444-
});
474+
setState(() => indexCategorySelected = index);
445475
var topHeadlinesNewsBloc = BlocProvider.of<TopHeadlinesNewsBloc>(context);
446-
topHeadlinesNewsBloc
447-
.add(ChangeCategoryTopHeadlinesNewsEvent(indexCategorySelected: indexCategorySelected));
476+
topHeadlinesNewsBloc.add(
477+
ChangeCategoryTopHeadlinesNewsEvent(indexCategorySelected: index),
478+
);
448479
},
449480
child: Container(
450481
child: AnimatedContainer(

‎lib/feature/presentation/page/search/search_page.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ class _SearchPageState extends State<SearchPage> {
4242
@override
4343
Widget build(BuildContext context) {
4444
ScreenUtil.init(context);
45+
var theme = Theme.of(context);
46+
var isDarkTheme = theme.brightness == Brightness.dark;
4547
return Scaffold(
4648
body: BlocProvider<TopHeadlinesNewsBloc>(
4749
create: (context) => topHeadlinesNewsBloc,
@@ -50,11 +52,11 @@ class _SearchPageState extends State<SearchPage> {
5052
Container(
5153
width: double.infinity,
5254
height: double.infinity,
53-
color: Color(0xFFEFF5F5),
55+
color: isDarkTheme ?null:Color(0xFFEFF5F5),
5456
),
5557
SafeArea(
5658
child: Container(
57-
color: Color(0xFFEFF5F5),
59+
color: isDarkTheme ?null:Color(0xFFEFF5F5),
5860
width: double.infinity,
5961
padding: EdgeInsets.symmetric(
6062
vertical: 24.h,
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_screenutil/flutter_screenutil.dart';
3+
import 'package:hive/hive.dart';
4+
import 'package:hive_flutter/hive_flutter.dart';
5+
6+
class SettingsPage extends StatefulWidget {
7+
@override
8+
_SettingsPageState createState() => _SettingsPageState();
9+
}
10+
11+
class _SettingsPageState extends State<SettingsPage> {
12+
@override
13+
Widget build(BuildContext context) {
14+
ScreenUtil.init(context);
15+
return Scaffold(
16+
appBar: WidgetAppBar(),
17+
body: Container(
18+
width: double.infinity,
19+
padding: EdgeInsets.all(48.w),
20+
child: Column(
21+
crossAxisAlignment: CrossAxisAlignment.start,
22+
children: <Widget>[
23+
Text(
24+
'Interface',
25+
style: TextStyle(
26+
fontSize: 48.sp,
27+
fontWeight: FontWeight.bold,
28+
),
29+
),
30+
Row(
31+
children: <Widget>[
32+
Expanded(
33+
child: Column(
34+
crossAxisAlignment: CrossAxisAlignment.start,
35+
children: <Widget>[
36+
Text(
37+
'Use dark mode',
38+
style: TextStyle(
39+
fontSize: 42.sp,
40+
),
41+
),
42+
Text(
43+
'Get that whiteness out',
44+
style: TextStyle(
45+
fontSize: 36.sp,
46+
color: Colors.grey,
47+
),
48+
),
49+
],
50+
),
51+
),
52+
ValueListenableBuilder(
53+
valueListenable: Hive.box('settings').listenable(),
54+
builder: (context, box, widget) {
55+
var isDarkMode = box.get('darkMode') ?? false;
56+
return Switch(
57+
value: isDarkMode,
58+
onChanged: (value) async {
59+
isDarkMode = value;
60+
await box.put('darkMode', isDarkMode);
61+
},
62+
);
63+
},
64+
),
65+
],
66+
),
67+
],
68+
),
69+
),
70+
);
71+
}
72+
}
73+
74+
class WidgetAppBar extends PreferredSize {
75+
@override
76+
Widget build(BuildContext context) {
77+
return ValueListenableBuilder(
78+
valueListenable: Hive.box('settings').listenable(),
79+
builder: (context, box, widget) {
80+
var isDarkMode = box.get('darkMode') ?? false;
81+
return isDarkMode
82+
? AppBar(
83+
title: Text('Settings'),
84+
)
85+
: AppBar(
86+
title: Text('Settings'),
87+
);
88+
},
89+
);
90+
}
91+
92+
@override
93+
Size get preferredSize {
94+
return Size.fromHeight(kToolbarHeight);
95+
}
96+
}

‎lib/injection_container.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@ import 'package:flutter_news_app/feature/data/repository/news/news_repository_im
99
import 'package:flutter_news_app/feature/domain/repository/news/news_repository.dart';
1010
import 'package:flutter_news_app/feature/domain/usecase/gettopheadlinesnews/get_top_headlines_news.dart';
1111
import 'package:flutter_news_app/feature/domain/usecase/searchtopheadlinesnews/search_top_headlines_news.dart';
12+
import 'package:flutter_news_app/feature/presentation/bloc/topheadlinesnews/bloc.dart';
1213
import 'package:get_it/get_it.dart';
1314

14-
import 'feature/presentation/bloc/topheadlinesnews/bloc.dart';
15-
1615
final sl = GetIt.instance;
1716

1817
Future<void> init() async {

‎lib/main_development.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@ import 'package:flutter_news_app/app.dart';
33
import 'package:flutter_news_app/config/base_url_config.dart';
44
import 'package:flutter_news_app/config/flavor_config.dart';
55
import 'package:flutter_news_app/injection_container.dart' as di;
6+
import 'package:hive/hive.dart';
7+
import 'package:hive_flutter/hive_flutter.dart';
68

79
void main() async {
810
WidgetsFlutterBinding.ensureInitialized();
11+
await Hive.initFlutter();
12+
await Hive.openBox('settings');
913
FlavorConfig(
1014
flavor: Flavor.DEVELOPMENT,
1115
values: FlavorValues(baseUrl: BaseUrlConfig().baseUrlDevelopment),

‎lib/main_production.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@ import 'package:flutter_news_app/app.dart';
33
import 'package:flutter_news_app/config/base_url_config.dart';
44
import 'package:flutter_news_app/config/flavor_config.dart';
55
import 'package:flutter_news_app/injection_container.dart' as di;
6+
import 'package:hive/hive.dart';
7+
import 'package:hive_flutter/hive_flutter.dart';
68

79
void main() async {
810
WidgetsFlutterBinding.ensureInitialized();
11+
await Hive.initFlutter();
12+
await Hive.openBox('settings');
913
FlavorConfig(
1014
flavor: Flavor.PRODUCTION,
1115
values: FlavorValues(baseUrl: BaseUrlConfig().baseUrlProduction),

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /