teratail header banner
teratail header banner
質問するログイン新規登録

質問編集履歴

1

追記

2021/02/27 03:23

投稿

ts21
ts21

スコア32

title CHANGED
@@ -1,1 +1,1 @@
1
- [Flutter]SharedPreferencesでWebview保持したい
1
+ [Flutter]再起動後も同じ画面表示させたい
body CHANGED
@@ -1,117 +1,217 @@
1
1
  ### 前提・実現したいこと
2
- アプリを開いた段階で、過去に閲覧したwebページをそのまま表示させたいです。
3
- その前段階としてWebviewの実装に手間取っています。
4
2
 
5
- setting画面→view画面に遷移します。
6
- 最初にsetting画面にWebview表示したURL入力します。
3
+ FlutterWebviewを用たアプリケーション開発ています。
7
- connectボタンを押すと、view画面にURLをパラメータとして画面遷移します。
8
- ![イメージ説明](25f9af793eb72813b23e8171fa503316.png)
9
4
 
10
- view画面ではURLのページ表示するはずですが、下の画像のように真っ白な画面になっていま
5
+ setting画面とview画面があり以下3つ実装したいのですが、[3]が実装できていません
11
- ![イメージ説明](0dfbd75e54b8abdc6ac59520f9b99e5b.png)
12
- appbarのテキストから、パラメータ自体は受け取っていることがわかります。
13
6
 
7
+ [1]setting画面からview画面に遷移する
8
+ [2]setting画面で入力したURLをview画面で表示させたい
9
+ [3]その表示させた画面は再起動後もview画面で表示される
10
+
11
+ ###実装方法
12
+ まず、setting画面の入力フォームにWebviewで表示させたいwebページのURLを入力します。
13
+ 下の画面がsetting画面で、このときtwitterのURLを入力しています。
14
+ ![イメージ説明](9e30287bb74c5acb1ea3c0d31c8b1ca3.png)
15
+
16
+ setting画面で受け取ったURLは一度`SharedPreferences`で保存(save)して、view画面で受け取ります。
17
+
18
+ view画面では、下のようにtwitterが確認できました
19
+
20
+ ![イメージ説明](d1fd19c4a255289c09df9604055f1d1e.png)
21
+
22
+ しかしエミュレータを再起動するとview画面にtwitterの画面が表示されず、[3]の実装ができていないことがわかりました。
23
+
14
- ### 該当のソースコード
24
+ ### setting画面のソースコード
15
- view画面のview.dartは以下のようにコーディングしました。
25
+
16
26
  ```dart
27
+
17
28
  import 'package:flutter/material.dart';
18
- import 'package:webview_flutter/webview_flutter.dart';
29
+ import 'view.dart';
19
30
  import 'package:shared_preferences/shared_preferences.dart';
20
31
  import 'Widgets/drawer.dart';
21
32
 
22
- class ViewScreen extends StatefulWidget {
33
+ class SettingScreen extends StatefulWidget {
23
- static const routeName = '/view';
34
+ static const routeName = '/setting';
24
- final String url;
25
35
 
26
- viewScreen({Key key, @required this.url}) : super(key: key);
27
-
28
36
  @override
29
- State<StatefulWidget> createState() => ViewScreenState();
37
+ State<StatefulWidget> createState() => SettingScreenState();
30
38
  }
31
39
 
32
- class ViewScreenState extends State<ViewScreen> {
40
+ class SettingScreenState extends State<SettingScreen> {
41
+ static const routeName = '/setting';
33
- String _view = "message";
42
+ final _formKey = GlobalKey<FormState>();
43
+ String input;
34
44
 
35
- void _load() async {
45
+ void _save(String url) async {
36
46
  SharedPreferences pref = await SharedPreferences.getInstance();
37
- setState(() {
38
- _view = pref.getString('url') ?? '';
47
+ pref.setString('url', url);
39
- });
40
48
  }
41
49
 
42
50
  @override
51
+ Widget build(BuildContext context) {
43
- void initState() {
52
+ return Scaffold(
44
- super.initState();
53
+ drawer: DrawerScreen(),
54
+ body: Form(
55
+ key: _formKey,
56
+ child: Column(
57
+ crossAxisAlignment: CrossAxisAlignment.center,
58
+ children: [
45
- _load();
59
+ Padding(
60
+ padding: const EdgeInsets.all(16.0),
61
+ child: Container(
62
+ child: Text('setting'),
63
+ ),
64
+ ),
65
+ TextFormField(
66
+ decoration: const InputDecoration(
67
+ labelText: 'URL *',
68
+ ),
69
+ onSaved: (String value) {
70
+ input = value;
71
+ },
72
+ ),
73
+ Padding(
74
+ padding: const EdgeInsets.symmetric(vertical: 16.0),
75
+ child: _sendButton(context),
76
+ ),
77
+ ],
78
+ ),
79
+ ));
46
80
  }
47
81
 
48
- @override
49
- Widget build(BuildContext context) {
82
+ Widget _sendButton(BuildContext context) {
50
- return Scaffold(
83
+ return RaisedButton(
51
- appBar: AppBar(
52
- title: Text(_view),
53
- ),
54
- drawer: DrawerScreen(),
55
- body: WebView(
56
- initialUrl: _view,
84
+ onPressed: () {
57
- javascriptMode: JavascriptMode.unrestricted,
58
- javascriptChannels: Set.from([
85
+ this._formKey.currentState.save();
59
- JavascriptChannel(
60
- name: "getData",
86
+ if (input == "") {
87
+ _showDialog(context);
88
+ } else {
89
+ _save(input);
61
- onMessageReceived: (JavascriptMessage result) {
90
+ Navigator.of(context).push(MaterialPageRoute(
91
+ builder: (context) => ViewScreen(url: input),
92
+ fullscreenDialog: true));
93
+ }
62
- }),
94
+ },
63
- ]),
95
+ child: Text('connect'),
64
- ),
65
96
  );
66
97
  }
98
+
99
+ void _showDialog(BuildContext context) {
100
+ showDialog(
101
+ context: context,
102
+ builder: (BuildContext context) {
103
+ return AlertDialog(
104
+ title: Text("エラー"),
105
+ content: Text("指定されたURLに接続できません"),
106
+ actions: <Widget>[
107
+ FlatButton(
108
+ child: Text("OK"),
109
+ onPressed: () {
110
+ Navigator.of(context).pop();
111
+ },
112
+ ),
113
+ ],
114
+ );
115
+ });
116
+ }
67
117
  }
68
118
 
69
119
  ```
70
120
 
71
- ### 試したこと
121
+ ###view画面のソースコード
72
- ネットワークの設定が要るのかと思い`https://twitter.com/home`を直接`initialUrl`に(Webviewで表示させたいURLを`String`で設定する部分)書き込むと接続はできました。
73
122
 
74
- また、` SharedPreferences`を使わずに以下のように書くと、求める結果が得られました
75
-
76
123
  ```dart
77
124
  import 'package:assets_audio_player/assets_audio_player.dart';
78
125
  import 'package:flutter/material.dart';
79
126
  import 'package:webview_flutter/webview_flutter.dart';
127
+ import 'package:shared_preferences/shared_preferences.dart';
80
128
  import 'Widgets/drawer.dart';
81
129
 
82
130
  class ViewScreen extends StatefulWidget {
83
131
  static const routeName = '/view';
84
132
  final String url;
85
133
 
86
- ViewScreen({Key key, @required this.url}) : super(key: key);
134
+ ViewScreen({Key key, @required this.url}) : super(key: key);
87
135
 
88
136
  @override
89
- State<StatefulWidget> createState() =>ViewScreenState();
137
+ State<StatefulWidget> createState() => ViewScreenState();
90
138
  }
91
139
 
92
- classViewScreenState extends State<ViewScreen> {
140
+ class ViewScreenState extends State<ViewScreen> {
141
+ Future<String> _future;
142
+ String _view = "message";
143
+
144
+ Future<String> _load() async {
145
+ SharedPreferences pref = await SharedPreferences.getInstance();
146
+ _view = pref.getString('url') ?? '';
147
+ return Future.value(_view);
148
+ }
149
+
93
150
  @override
151
+ void initState() {
152
+ super.initState();
153
+ _future = _load();
154
+ }
155
+
156
+ @override
94
157
  Widget build(BuildContext context) {
95
- return Scaffold(
158
+ return Scaffold(
96
- appBar: AppBar(
97
- title: Text(widget.url),
98
- ),
99
- drawer: _drawer(context),
159
+ drawer: DrawerScreen(),
160
+ body: FutureBuilder(
161
+ future: _future,
162
+ builder: (context, AsyncSnapshot<String> snapshot) {
163
+ switch (snapshot.connectionState) {
164
+ case ConnectionState.none:
165
+ return Text('none');
166
+ case ConnectionState.waiting:
167
+ return Center(child: CircularProgressIndicator());
168
+ case ConnectionState.active:
169
+ return Text('');
170
+ case ConnectionState.done:
171
+ if (snapshot.hasError) {
172
+ return Text(
173
+ '${snapshot.error}',
174
+ style: TextStyle(color: Colors.red),
175
+ );
176
+ } else {
100
- body: WebView(
177
+ return WebView(
101
- initialUrl: widget.url,
178
+ initialUrl: _view,
102
- javascriptMode: JavascriptMode.unrestricted,
179
+ javascriptMode: JavascriptMode.unrestricted,
103
- javascriptChannels: Set.from([
180
+ javascriptChannels: Set.from([
104
- JavascriptChannel(
181
+ JavascriptChannel(
105
- name: "getData",
182
+ name: "getData",
106
- onMessageReceived: (JavascriptMessage result) {
183
+ onMessageReceived: (JavascriptMessage result) {
184
+ if (result.message == "play sound") {
185
+ AssetsAudioPlayer().open(
186
+ Audio("assets/announce.wav"),
187
+ );
188
+ }
107
- }),
189
+ }),
108
- ]),
190
+ ]),
109
- ),
191
+ );
192
+ }
193
+ }
194
+ }));
195
+ }
196
+ }
197
+
198
+ Future<void> main() async {
199
+ WidgetsFlutterBinding.ensureInitialized();
200
+ SharedPreferences pref = await SharedPreferences.getInstance();
201
+ await pref.setString('url', '');
202
+ runApp(MyApp());
203
+ }
204
+
205
+ class MyApp extends StatelessWidget {
206
+ @override
207
+ Widget build(BuildContext context) {
208
+ return MaterialApp(
209
+ home: ViewScreen(),
110
210
  );
111
211
  }
112
212
  }
113
213
 
114
214
  ```
115
- ![イメージ説明](8e27898e1181384b3faecd44efe09720.png)
116
215
 
117
- 心当たりある方は、ご指摘ただけると幸いす。
216
+ [1]~[2]実装自体がよくなしょうか?
217
+ どなたかご指摘ください