'Search text in WebView using Flutter
I currently have an application where I have to read books in epub format, I tried to use libraries like epub_kitty, but I had many errors with other libraries that I need. Anyway, I need my flutter application to search for a phrase within a webview, select (check) phrases for the user to open and view later, and bookmark the book.
One option that I’m currently testing is to take the html part of my epub and use my webview to show it to the user, but I don’t know how to do the functionality I imagined for the application (I’m currently trying to do the text search part inside the html, I'm trying to use a javascript code inside my webview but it isn't working), any ideas?
Solution 1:[1]
The only way I can think that might work is using the Javascript... here's an example
final Completer<WebViewController> _controller = Completer<WebViewController>();
Column(
children: [
FutureBuilder<WebViewController>(
future: _controller.future,
builder: (context, AsyncSnapshot<WebViewController> controller) {
if (controller.hasData) {
return FlatButton(
child: Text('Find "information"'),
onPressed: () {
controller.data.evaluateJavascript('self.find("information")');
});
}
return SizedBox(height: 40);
},
),
Container(
height: 400,
child: WebView(
initialUrl: 'https://flutter.dev',
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
_controller.complete(webViewController);
},
),
)
],
)
As you can see, by using the evaluateJavascript you can run the code you need to find the text. As for what you need, you can create a more complex function and add it to your html if needed. Then you can just invoke it from here.
Solution 2:[2]
Youcan userunJavascriptReturningResult or runJavascript method over webviewcontroller
Return true if find a result or false (non-case search)
_controller!.runJavascriptReturningResult("self.find('bootstrap')")
.then((value) => print(value));
Case Sensitive Search
_controller!.runJavascript("self.find('Hi',{'CaseSensitive':true})");
Syntax window.find(aString, aCaseSensitive, aBackwards, aWrapAround, aWholeWord, aSearchInFrames, aShowDialog); Copy to Clipboard aString The text string for which to search.
aCaseSensitive A boolean value. If true, specifies a case-sensitive search.
aBackwards A boolean value. If true, specifies a backward search.
aWrapAround A boolean value. If true, specifies a wrap around search.
aWholeWord Unimplemented A boolean value. If true, specifies a whole word search. This is not implemented; see bug 481513.
aSearchInFrames A boolean value. If true, specifies a search in frames.
Returns true if the string is found; otherwise, false.
SampleCode
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: Center(
child: Column(
children: [
Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: TextField(
onChanged: (v) {
// _controller!
// .runJavascriptReturningResult(
// "self.find('${_textcontrol.text}')")
// .then((value) => print(value));
},
controller: _textcontrol,
decoration: InputDecoration(
hintText: 'Search', border: OutlineInputBorder()),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 55,
child: ElevatedButton(
onPressed: () {
var casesensitive =
"self.find('${_textcontrol.text}',{'CaseSensitive':true})";
var noncase = "self.find('${_textcontrol.text}')";
_controller!.runJavascript(noncase);
// .then((value) => print(value));
},
child: Icon(
Icons.search,
size: 45,
)),
),
)
],
),
)),
Expanded(
child: MyHomePage(
title: '',
))
],
),
),
),
);
}
}
WebViewController? _controller;
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
Color appBarcolor = Colors.blue;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
var _textcontrol = TextEditingController();
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
super.initState();
if (Platform.isAndroid) WebView.platform = AndroidWebView();
}
@override
Widget build(BuildContext context) {
return controller();
}
WebView controller() {
return WebView(
javascriptMode: JavascriptMode.unrestricted,
initialUrl: 'https://getbootstrap.com/',
onWebViewCreated: (WebViewController webViewController) {
_controller = webViewController;
},
navigationDelegate: (NavigationRequest request) {
setState(() {
widget.appBarcolor = Colors.black87;
});
return NavigationDecision.navigate;
},
);
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Frank |
| Solution 2 | lava |

