Find Interaction Controller
Supported Platforms: AndroidiOSmacOS
FindInteractionController
represents the controller used by the WebView
to add text-finding capabilities, such as the "Find on page" feature.
Basic Usage
Set the findInteractionController
of the WebView
to control the text-finding feature.
To start search text, use findInteractionController.findAll(string find)
and then use findInteractionController.findNext(bool forward)
to move forward (true
) or backward (false
).
You can access the active find session with findInteractionController.getActiveFindSession()
with info about the search after completion.
The findAll
method will not wait for the completion of the search.
In this case, you can wait for a little time, for example await Future.delayed(Duration(seconds: 1)))
, before accessing the active FindSession
.
Also, you can listen for the FindInteractionController.onFindResultReceived
event that is an event fired as find-on-page operations progress.
This event will not be called if InAppWebViewSettings.isFindInteractionEnabled
is true
.
Only on iOS, setting InAppWebViewSettings.isFindInteractionEnabled
to true
, enables the web view's built-in find interaction native UI.
With this option enabled, you can use the other FindInteractionController
methods to control the iOS native UI.
Example:
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
await InAppWebViewController.setWebContentsDebuggingEnabled(kDebugMode);
}
runApp(const MaterialApp(home: MyApp()));
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final GlobalKey webViewKey = GlobalKey();
InAppWebViewController? webViewController;
InAppWebViewSettings settings = InAppWebViewSettings();
late FindInteractionController findInteractionController;
final searchController = TextEditingController();
var textFound = "";
void initState() {
super.initState();
findInteractionController = FindInteractionController(
onFindResultReceived: (controller, activeMatchOrdinal, numberOfMatches,
isDoneCounting) async {
if (isDoneCounting) {
setState(() {
textFound = numberOfMatches > 0
? '${activeMatchOrdinal + 1} of $numberOfMatches'
: '';
});
if (numberOfMatches == 0) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(
'No matches found for "${await findInteractionController.getSearchText()}"'),
));
}
}
},
);
}
Widget build(BuildContext context) {
var isFindInteractionEnabled = settings.isFindInteractionEnabled ?? false;
return Scaffold(
appBar: AppBar(
title: const Text('Find Interaction Controller'),
actions: defaultTargetPlatform != TargetPlatform.iOS
? []
: [
(isFindInteractionEnabled)
? IconButton(
icon: const Icon(Icons.search),
onPressed: () async {
if (await findInteractionController
.isFindNavigatorVisible() ??
false) {
await findInteractionController
.dismissFindNavigator();
} else {
await findInteractionController
.presentFindNavigator();
}
},
)
: Container(),
TextButton(
style:
TextButton.styleFrom(foregroundColor: Colors.white),
onPressed: () async {
if (isFindInteractionEnabled) {
searchController.text =
await findInteractionController.getSearchText() ??
'';
}
await findInteractionController.clearMatches();
isFindInteractionEnabled =
settings.isFindInteractionEnabled =
!isFindInteractionEnabled;
await webViewController?.setSettings(
settings: settings);
setState(() {
textFound = '';
});
await findInteractionController
.setSearchText(searchController.text);
if (isFindInteractionEnabled) {
await findInteractionController
.presentFindNavigator();
}
},
child: Text(!isFindInteractionEnabled
? 'Native UI'
: 'Custom UI'),
)
]),
body: Column(children: <Widget>[
isFindInteractionEnabled
? Container()
: TextField(
decoration: InputDecoration(
prefixIcon: const Icon(Icons.search),
suffixText: textFound,
suffixIcon: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const SizedBox(
width: 10,
),
IconButton(
icon: const Icon(Icons.arrow_upward),
onPressed: () {
findInteractionController.findNext(forward: false);
},
),
IconButton(
icon: const Icon(Icons.arrow_downward),
onPressed: () {
findInteractionController.findNext();
},
),
],
),
),
controller: searchController,
keyboardType: TextInputType.text,
onSubmitted: (value) {
if (value == '') {
findInteractionController.clearMatches();
setState(() {
textFound = '';
});
} else {
findInteractionController.findAll(find: value);
}
},
),
Expanded(
child: InAppWebView(
key: webViewKey,
initialUrlRequest: URLRequest(url: WebUri("https://flutter.dev/")),
findInteractionController: findInteractionController,
initialSettings: settings,
onWebViewCreated: (InAppWebViewController controller) {
webViewController = controller;
},
)),
]));
}
}
This is the result:
- Android
- iOS