- Introduction.
- Terms of Use and Display on the PlaPolis Web Site
- Introducing the Flutter plugin: webview_flutter
- Create a new screen to display the Terms of Use and PlaPoli
- WebView display when tapping on the Terms of Use or Plapori link
- Fix navigation in Terms of Use display.
- Make WebView scrollable.
- operation check
Introduction.
Currently developing “Mia,” a talking cat-shaped robot that speaks dialect.
We have created a website for Mia and a Terms of Use/Prapolicy, and now we will make these accessible from the flutter application.
Mia website: https://mia-cat.com/en
Terms of use: https://mia-cat.com/terms-of-service/
Plapoli: https://mia-cat.com/privacy-policy/
I think it would be possible to transition externally from the app to the web page of the terms of use and plasticoli, but I think the WebView display in the app would improve the UX a little.
The app has a user settings screen, and within that screen, there are items for terms of use and plastic polys, so when this item is tapped, the contents of each item are displayed in WebView and can be closed.
Terms of Use and Display on the PlaPolis Web Site
I tried to embed notion, but..,
Let me start with a quiet question. First of all, I thought it would be easier to display the terms of use/prappolli on the website if I could create them in notion and embed them in the website, since the updating process only involves changing the text in notion. I found several services that allow you to embed it in a wordpress shortcode. I actually tried it and confirmed that it works correctly.
Example: Embed Notion Pages (WordPress plugin available): but for a fee
https://www.embednotionpages.com/embeds
However, all the services are paid services, and I thought to myself, “Why pay for a service that merely embeds a page? I thought that I wouldn’t update it that much, so I put it on a fixed page of wordpress this time. By the way, google document can be embedded and updated for free. No additional plug-ins or services are required.
In the future, we would like to consolidate our FAQs and manuals into notion as well, so perhaps we will use a paid notion embed service. If there is a way to do this for free (including implementing it on my own), I would appreciate it if someone could let me know. m(_ _)m
Introducing the Flutter plugin: webview_flutter
There are several plugins that provide webview in Flutter, but two major ones are candidates.
- webview_flutterPolylang
placeholder do not modify
- flutter_inappwebview
→webview_flutter Third-party web view packages offering more advanced functionality
It offers more features than
webview_flutter
, including JavaScript channel support, HTTP request override, custom context menu creation, and user agent customization.
In this case, a simple implementation will suffice, so introduce webview_flutter
Incidentally, there was a Google Codelabs (hands-on content with guidelines and tutorials on various implementations) titled “Adding WebView to your Flutter app”.
https://codelabs.developers.google.com/codelabs/flutter-webview?hl=ja#0
$ flutter pub add webview_flutter
$ flutter pub get
To use the webview_flutter
plugin in Android, the minSDK
must be set to 19 or 20 depending on the view of the Android platform used, so modify the gradle file if the minSDK does not meet the requirements.
// android/app/build.gradle
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.webview_in_flutter"
minSdkVersion 20 // MODIFY
targetSdkVersion 30
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
Create a new screen to display the Terms of Use and PlaPoli
See Usage in package webview_flutter.
https://pub.dev/packages/webview_flutter
Create an instance of WebViewController
, pass that instance to WebViewWidget
as an argument, and display WebViewWidget
in the body of
Scaffold
.
When creating an instance of WebViewController
, several methods can be set.
setJavaScriptMode(JavaScriptMode.unrestricted)
:
Allow JavaScript execution inWebView
setBackgroundColor(const Color(0x00000000))
:
Sets the background color ofWebView
.setNavigationDelegate(NavigationDelegate(...))
: : .- It can allow or deny actions when a page starts loading, completes loading, or encounters an error, as well as allow or deny certain navigation requests. For example,
onNavigationRequest
controls navigation to a specific URL. Here, navigation is prevented if the URL begins withhttps://www.youtube.com/
. loadRequest(Uri.parse('https://flutter.dev'))
: Loads a Web page with the specified URL inWebView
. In this example,https://flutter.dev
is loaded.
controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setBackgroundColor(const Color(0x00000000))
..setNavigationDelegate(
NavigationDelegate(
onProgress: (int progress) {
// Update loading bar.
},
onPageStarted: (String url) {},
onPageFinished: (String url) {},
onWebResourceError: (WebResourceError error) {},
onNavigationRequest: (NavigationRequest request) {
if (request.url.startsWith('https://www.youtube.com/')) {
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
},
),
)
..loadRequest(Uri.parse('https://flutter.dev'));
In this case, since it is simple enough to display the URL ( https://mia-cat.com/terms-of-service) of the Terms of Use, only the loadRequest
method should be used to load the URL.
// lib/screens/home/terms_of_service_screen.dart
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class TermsOfServiceScreen extends StatefulWidget {
const TermsOfServiceScreen({Key? key}) : super(key: key);
@override
_TermsOfServiceScreenState createState() => _TermsOfServiceScreenState();
}
class _TermsOfServiceScreenState extends State {
late WebViewController _controller;
@override
void initState() {
super.initState();
_controller = WebViewController()
..loadRequest(Uri.parse('https://mia-cat.com/terms-of-service/'));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('利用規約')),
body: WebViewWidget(controller: _controller),
);
}
}
After the Terms of Use are successfully displayed, you can return to the settings screen by clicking the “<:Back” button on the left side of the AppBar.
WebView display when tapping on the Terms of Use or Plapori link
This time, use the showModalBottomSheet
function to display the bottom sheet sliding up from the bottom, instead of using navigation.push.
https://api.flutter.dev/flutter/material/showModalBottomSheet.html
isScrollControlled: true
:.
- Setting this option to
true
allows the bottom sheet to be displayed in full screen mode. This allows the height of the bottom sheet to be set freely. Normally, the bottom sheet is only displayed up to half the screen height, but with this option, it can be extended to, for example, 80% of the screen height (specified with heightFactor). Of course, 100% is also possible.
FractionallySizedBox
:.
- This widget is used to define the size of its child widgets as a percentage of its parent’s size. Here,
heightFactor
is set to0.8
, which sets the height ofTermsOfServiceScreen
to 80% of the parent’s height (i.e., screen height).
Widget buildItem(String item, bool isLast) {
final user = ref.watch(userProvider);
return Container(
decoration: BoxDecoration(
),
child: Column(
children: [
ListTile(
title: Row(
),
trailing: const Icon(Icons.chevron_right),
onTap: () async {
switch (item) {
case '利用規約':
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (_) => const FractionallySizedBox(
heightFactor: 0.8,
child: TermsOfServiceScreen(),
),
);
break;
}
},
),
],
),
);
}
Fix navigation in Terms of Use display.
By default, there is a “<” icon on the left side of the AppBar, and clicking this icon will close the Terms of Use screen and return to the Advanced Settings screen.
However, this behavior is a little confusing, so the “<” should be removed and instead the “X (close)” button should be displayed on the right side of the AppBar, and the screen should be changed so that clicking this button will close the screen.
Override and hide the default back button ( <icon
) by placing a Container()
( an empty container that displays nothing) in the leading of the
AppBar
.
And for the right side of the AppBar, use the actions
property of the AppBar
widget, which takes a list of widgets, and these widgets are aligned horizontally on the right side of the AppBar.
icon: const Icon(Icons.close), to display the “Close” button on the right side of the AppBar widget
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('利用規約'),
leading: Container(),
actions: [
IconButton(
icon: const Icon(Icons.close),
onPressed: () {
Navigator.of(context).pop();
},
),
],
),
body: WebViewWidget(controller: _controller),
);
}
It is easier to understand.
Make WebView scrollable.
As it is now, the terms of use are displayed but not scrollable, so make it scrollable.
The showModalBottomSheet function mentioned earlier has a parameter called enableDrag, which is true by default.
If enableDrag
is set to true
in showModalBottomSheet
, the user can drag the entire bottom sheet up and down. This dragging operation may conflict with scrolling operations within WebView. That is, when the user tries to scroll WebView, the gesture is interpreted as a drag operation in the bottom sheet, and as a result, scrolling in WebView may not work correctly.
Therefore, set enableDrag
to false
to disable the bottom sheet drag operation. In this case, users will not be able to close the bottom sheet by dragging, but since we have prepared a close button on the right side of the modal AppBar, the modal hide function by dragging is not necessary.
Widget buildItem(String item, bool isLast) {
final user = ref.watch(userProvider);
return Container(
decoration: BoxDecoration(
),
child: Column(
children: [
ListTile(
title: Row(
),
trailing: const Icon(Icons.chevron_right),
onTap: () async {
switch (item) {
case '利用規約':
showModalBottomSheet(
context: context,
isScrollControlled: true,
enableDrag: false,
builder: (_) => const FractionallySizedBox(
heightFactor: 0.8,
child: TermsOfServiceScreen(),
),
);
break;
}
},
),
],
),
);
}
operation check
After successfully tapping the ListItem of the Terms of Use, the WebView of the Terms of Use is displayed from the bottom of the screen, can be scrolled, and the modal can be closed with the close icon in the upper right corner of the modal.
コメント