1. Giriş
Son Güncelleme: 2021-10-19
WebView Flutter eklentisi ile Android veya iOS Flutter uygulamanıza bir WebView widget'ı ekleyebilirsiniz. iOS'te WebView widget'ı WKWebView, Android'de ise WebView tarafından desteklenir. Eklenti, Flutter widget'larını web görünümünde oluşturabilir. Örneğin, web görünümünde bir açılır menü oluşturmak mümkündür.
Ne oluşturacaksınız?
Bu codelab'de, Flutter SDK'sını kullanarak WebView içeren bir mobil uygulamayı adım adım oluşturacaksınız. Uygulamanız şunları yapabilecek:
- Web içeriğini
WebView
içinde görüntüleme WebView
üzerinde üst üste yerleştirilmiş Flutter widget'larını görüntüleme- Sayfa yükleme ilerleme durumu etkinliklerine tepki verme
WebView
özelliğiniWebViewController
üzerinden kontrol etmeNavigationDelegate
kullanarak web sitelerini engelleme- JavaScript ifadelerini değerlendirme
- JavaScript'ten gelen geri çağırmaları
JavascriptChannels
ile işleme - Çerezleri ayarlama, kaldırma, ekleme veya gösterme
- HTML içeren öğelerden, dosyalardan veya dizelerden HTML yükleme ve görüntüleme
Öğrenecekleriniz
Bu codelab'de, webview_flutter
eklentisini aşağıdakiler de dahil olmak üzere çeşitli şekillerde kullanmayı öğreneceksiniz:
webview_flutter
eklentisini yapılandırma- Sayfa yükleme ilerleme etkinliklerini dinleme
- Sayfa gezinmesini kontrol etme
WebView
'ya geçmişinde ileri ve geri gitme komutu verme- Döndürülen sonuçları kullanma dahil olmak üzere JavaScript'i değerlendirme
- JavaScript'ten Dart kodunu çağırmak için geri çağırmaları kaydetme
- Çerezler nasıl yönetilir?
- Öğelerden, dosyalardan veya HTML içeren dizeden HTML sayfalarını yükleme ve görüntüleme
İhtiyacınız olanlar
- Android Studio 4.1 veya sonraki sürümleri (Android geliştirme için)
- Xcode 12 veya sonraki sürümler (iOS geliştirme için)
- Flutter SDK'sı
- Android Studio veya Visual Studio Code gibi bir kod düzenleyici.
2. Flutter geliştirme ortamınızı kurma
Bu laboratuvarı tamamlamak için iki yazılıma ihtiyacınız var: Flutter SDK ve bir düzenleyici.
Codelab'i aşağıdaki cihazlardan herhangi birini kullanarak çalıştırabilirsiniz:
- Bilgisayarınıza bağlı ve Geliştirici moduna ayarlanmış fiziksel bir Android veya iOS cihaz.
- iOS simülatörü (Xcode araçlarının yüklenmesi gerekir).
- Android Emulator (Android Studio'da kurulum gerektirir).
3. Başlarken
Flutter'ı kullanmaya başlama
Yeni bir Flutter projesi oluşturmanın çeşitli yolları vardır. Hem Android Studio hem de Visual Studio Code bu görev için araçlar sunar. Bağlantılı prosedürleri uygulayarak proje oluşturun veya aşağıdaki komutları kullanışlı bir komut satırı terminalinde çalıştırın.
$ flutter create --platforms=android,ios webview_in_flutter Creating project webview_in_flutter... Resolving dependencies in `webview_in_flutter`... Downloading packages... Got dependencies in `webview_in_flutter`. Wrote 74 files. All done! You can find general documentation for Flutter at: https://docs.flutter.dev/ Detailed API documentation is available at: https://api.flutter.dev/ If you prefer video documentation, consider: https://www.youtube.com/c/flutterdev In order to run your application, type: $ cd webview_in_flutter $ flutter run Your application code is in webview_in_flutter/lib/main.dart.
WebView Flutter eklentisini bağımlılık olarak ekleme
Flutter uygulamasına ek özellikler eklemek için en iyi yöntem Pub paketlerini kullanmaktır. Bu codelab'de projenize webview_flutter
eklentisini ekleyeceksiniz. Terminalde aşağıdaki komutları çalıştırın.
$ cd webview_in_flutter $ flutter pub add webview_flutter Resolving dependencies... Downloading packages... collection 1.18.0 (1.19.0 available) leak_tracker 10.0.5 (10.0.7 available) leak_tracker_flutter_testing 3.0.5 (3.0.7 available) material_color_utilities 0.11.1 (0.12.0 available) + plugin_platform_interface 2.1.8 string_scanner 1.2.0 (1.3.0 available) test_api 0.7.2 (0.7.3 available) + webview_flutter 4.9.0 + webview_flutter_android 3.16.7 + webview_flutter_platform_interface 2.10.0 + webview_flutter_wkwebview 3.15.0 Changed 5 dependencies! 6 packages have newer versions incompatible with dependency constraints. Try `flutter pub outdated` for more information.
pubspec.yaml dosyanızı incelerseniz artık bağımlılıklar bölümünde webview_flutter
eklentisi için bir satır olduğunu görürsünüz.
Android minSDK'yı yapılandırma
Android'de webview_flutter
eklentisini kullanmak için minSDK
ayarını 20
olarak belirlemeniz gerekir. android/app/build.gradle
dosyanızı aşağıdaki gibi değiştirin:
android/app/build.gradle
android {
//...
defaultConfig {
applicationId = "com.example.webview_in_flutter"
minSdk = 20 // Modify this line
targetSdk = flutter.targetSdkVersion
versionCode = flutterVersionCode.toInteger()
versionName = flutterVersionName
}
4. Flutter uygulamasına WebView widget'ı ekleme
Bu adımda, uygulamanıza bir WebView
ekleyeceksiniz. WebView'lar, yerleşik olarak barındırılan görünümlerdir ve uygulama geliştirici olarak bu yerleşik görünümleri uygulamanızda nasıl barındıracağınız konusunda seçim yapabilirsiniz. Android'de, Android'in varsayılanı olan sanal ekranlar ve hibrit kompozisyon arasında seçim yapabilirsiniz. Ancak iOS her zaman karma oluşturmayı kullanır.
Sanal ekranlar ve karma bileşim arasındaki farkların ayrıntılı bir tartışması için Platform Views ile Flutter uygulamanızda yerel Android ve iOS görünümlerini barındırma hakkındaki dokümanları okuyun .
Ekrana bir WebView yerleştirme
lib/main.dart
dosyasının içeriğini aşağıdakiyle değiştirin:
lib/main.dart
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
runApp(
MaterialApp(
theme: ThemeData(useMaterial3: true),
home: const WebViewApp(),
),
);
}
class WebViewApp extends StatefulWidget {
const WebViewApp({super.key});
@override
State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
late final WebViewController controller;
@override
void initState() {
super.initState();
controller = WebViewController()
..loadRequest(
Uri.parse('https://flutter.dev'),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter WebView'),
),
body: WebViewWidget(
controller: controller,
),
);
}
}
Bu kodu iOS veya Android'de çalıştırmak, cihazınızda WebView'ı tam alanlı bir tarayıcı penceresi olarak gösterir. Bu da tarayıcının cihazınızda herhangi bir kenarlık veya kenar boşluğu olmadan tam ekran olarak gösterildiği anlamına gelir. Kaydırdıkça sayfanın biraz tuhaf görünebilecek kısımlarını fark edeceksiniz. Bunun nedeni JavaScript'in devre dışı olması ve flutter.dev adresinin düzgün şekilde oluşturulması için JavaScript'in gerekli olmasıdır.
Uygulamayı çalıştırma
flutter.dev web sitesini görüntüleyen bir WebView'u görmek için Flutter uygulamasını iOS veya Android'de çalıştırın. Alternatif olarak, uygulamayı bir Android emülatöründe veya iOS simülatöründe çalıştırın. İlk WebView URL'sini kendi web sitenizle değiştirebilirsiniz.
$ flutter run
Uygun simülatör veya emülatörün çalıştığını ya da fiziksel bir cihazın bağlı olduğunu varsayarsak uygulamayı derleyip cihazınıza dağıttıktan sonra aşağıdakine benzer bir şey görmeniz gerekir:
5. Sayfa yükleme etkinliklerini dinleme
WebView
widget'ı, uygulamanızın dinleyebileceği çeşitli sayfa yükleme ilerleme durumu etkinlikleri sağlar. WebView
sayfa yükleme döngüsü sırasında üç farklı sayfa yükleme etkinliği tetiklenir: onPageStarted
, onProgress
ve onPageFinished
. Bu adımda bir sayfa yükleme göstergesi uygulayacaksınız. Ayrıca, bu işlem WebView
içerik alanında Flutter içeriği oluşturabileceğinizi gösterir.
Uygulamanıza sayfa yükleme etkinlikleri ekleme
lib/src/web_view_stack.dart
konumunda yeni bir kaynak dosyası oluşturun ve aşağıdaki içerikle doldurun:
lib/src/web_view_stack.dart
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
const WebViewStack({super.key});
@override
State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
var loadingPercentage = 0;
late final WebViewController controller;
@override
void initState() {
super.initState();
controller = WebViewController()
..setNavigationDelegate(NavigationDelegate(
onPageStarted: (url) {
setState(() {
loadingPercentage = 0;
});
},
onProgress: (progress) {
setState(() {
loadingPercentage = progress;
});
},
onPageFinished: (url) {
setState(() {
loadingPercentage = 100;
});
},
))
..loadRequest(
Uri.parse('https://flutter.dev'),
);
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
WebViewWidget(
controller: controller,
),
if (loadingPercentage < 100)
LinearProgressIndicator(
value: loadingPercentage / 100.0,
),
],
);
}
}
Bu kod, WebView
widget'ını Stack
ile sarmış ve sayfa yükleme yüzdesi %100'ün altında olduğunda WebView
widget'ının üzerine koşullu olarak LinearProgressIndicator
yerleştirmiştir. Bu durum, zaman içinde değişen program durumunu içerdiğinden bu durumu StatefulWidget
ile ilişkili bir State
sınıfında sakladınız.
Bu yeni WebViewStack
widget'ını kullanmak için lib/main.dart
öğenizi aşağıdaki şekilde değiştirin:
lib/main.dart
import 'package:flutter/material.dart';
import 'src/web_view_stack.dart';
void main() {
runApp(
MaterialApp(
theme: ThemeData(useMaterial3: true),
home: const WebViewApp(),
),
);
}
class WebViewApp extends StatefulWidget {
const WebViewApp({super.key});
@override
State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter WebView'),
),
body: const WebViewStack(),
);
}
}
Uygulamayı çalıştırdığınızda, ağ koşullarınıza ve tarayıcının, gittiğiniz sayfayı önbelleğe alıp almadığına bağlı olarak WebView
içerik alanının üzerinde bir sayfa yükleme göstergesi görürsünüz.
6. WebViewController ile çalışma
WebView widget'ından WebViewController'a erişme
WebView
widget'ı, WebViewController
ile programatik kontrolü etkinleştirir. Bu denetleyici, WebView
widget'ı oluşturulduktan sonra geri çağırma yoluyla kullanılabilir. Bu denetleyicinin kullanılabilirliğinin eşzamansız olması, onu Dart'ın eşzamansız Completer<T>
sınıfı için uygun bir aday yapar.
lib/src/web_view_stack.dart
uygulamasını şu şekilde güncelleyin:
lib/src/web_view_stack.dart
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
const WebViewStack({required this.controller, super.key}); // MODIFY
final WebViewController controller; // ADD
@override
State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
var loadingPercentage = 0;
// REMOVE the controller that was here
@override
void initState() {
super.initState();
// Modify from here...
widget.controller.setNavigationDelegate(
NavigationDelegate(
onPageStarted: (url) {
setState(() {
loadingPercentage = 0;
});
},
onProgress: (progress) {
setState(() {
loadingPercentage = progress;
});
},
onPageFinished: (url) {
setState(() {
loadingPercentage = 100;
});
},
),
);
// ...to here.
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
WebViewWidget(
controller: widget.controller, // MODIFY
),
if (loadingPercentage < 100)
LinearProgressIndicator(
value: loadingPercentage / 100.0,
),
],
);
}
}
WebViewStack
widget'ı artık çevreleyen widget'ta oluşturulan bir denetleyiciyi kullanıyor. Bu işlem, WebViewWidget
için denetleyicinin uygulamanın diğer bölümleriyle paylaşılmasını sağlar.
Gezinme Kontrolleri Oluşturma
Çalışan bir WebView
olması bir şeydir ancak sayfa geçmişinde ileri ve geri gidebilmek ve sayfayı yeniden yükleyebilmek faydalı bir dizi ekleme olacaktır. Neyse ki WebViewController
ile bu işlevi uygulamanıza ekleyebilirsiniz.
lib/src/navigation_controls.dart
konumunda yeni bir kaynak dosyası oluşturun ve aşağıdaki bilgilerle doldurun:
lib/src/navigation_controls.dart
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class NavigationControls extends StatelessWidget {
const NavigationControls({required this.controller, super.key});
final WebViewController controller;
@override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
IconButton(
icon: const Icon(Icons.arrow_back_ios),
onPressed: () async {
final messenger = ScaffoldMessenger.of(context);
if (await controller.canGoBack()) {
await controller.goBack();
} else {
messenger.showSnackBar(
const SnackBar(content: Text('No back history item')),
);
return;
}
},
),
IconButton(
icon: const Icon(Icons.arrow_forward_ios),
onPressed: () async {
final messenger = ScaffoldMessenger.of(context);
if (await controller.canGoForward()) {
await controller.goForward();
} else {
messenger.showSnackBar(
const SnackBar(content: Text('No forward history item')),
);
return;
}
},
),
IconButton(
icon: const Icon(Icons.replay),
onPressed: () {
controller.reload();
},
),
],
);
}
}
Bu widget, kullanıcının bir dizi IconButton
aracılığıyla WebView
öğesini kontrol etmesini sağlamak için oluşturma sırasında kendisiyle paylaşılan WebViewController
öğesini kullanır.
AppBar'a gezinme kontrolleri ekleme
Güncellenen WebViewStack
ve yeni oluşturulan NavigationControls
ile birlikte, artık tüm bunları güncellenmiş bir WebViewApp
içinde bir araya getirmenin zamanı geldi. Paylaşılan WebViewController
'yı burada oluştururuz. Bu uygulamadaki widget ağacının üst kısmına yakın bir yerde WebViewApp
olduğundan bu seviyede oluşturmak mantıklıdır.
lib/main.dart
dosyasını aşağıdaki gibi güncelleyin:
lib/main.dart
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart'; // ADD
import 'src/navigation_controls.dart'; // ADD
import 'src/web_view_stack.dart';
void main() {
runApp(
MaterialApp(
theme: ThemeData(useMaterial3: true),
home: const WebViewApp(),
),
);
}
class WebViewApp extends StatefulWidget {
const WebViewApp({super.key});
@override
State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
// Add from here...
late final WebViewController controller;
@override
void initState() {
super.initState();
controller = WebViewController()
..loadRequest(
Uri.parse('https://flutter.dev'),
);
}
// ...to here.
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter WebView'),
// Add from here...
actions: [
NavigationControls(controller: controller),
],
// ...to here.
),
body: WebViewStack(controller: controller), // MODIFY
);
}
}
Uygulamanın çalıştırılması, kontrollerin bulunduğu bir web sayfası göstermelidir:
7. NavigationDelegate ile gezinmeyi takip etme
WebView
, uygulamanıza NavigationDelegate,
sağlar. Bu sayede uygulamanız, WebView
widget'ının sayfa gezinmesini izleyip kontrol edebilir. Örneğin, bir kullanıcı bir bağlantıyı tıkladığında WebView,
tarafından bir gezinme başlatıldığında NavigationDelegate
çağrılır. NavigationDelegate
geri çağırma işlevi, WebView
öğesinin gezinmeye devam edip etmeyeceğini kontrol etmek için kullanılabilir.
Özel bir NavigationDelegate kaydetme
Bu adımda, NavigationDelegate
geri çağırma işlevi kaydederek YouTube.com'a gitmeyi engellersiniz. Bu basit uygulamanın, çeşitli Flutter API doküman sayfalarında görünen satır içi YouTube içeriklerini de engellediğini unutmayın.
lib/src/web_view_stack.dart
dosyasını aşağıdaki şekilde güncelleyin:
lib/src/web_view_stack.dart
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
const WebViewStack({required this.controller, super.key});
final WebViewController controller;
@override
State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
var loadingPercentage = 0;
@override
void initState() {
super.initState();
widget.controller.setNavigationDelegate(
NavigationDelegate(
onPageStarted: (url) {
setState(() {
loadingPercentage = 0;
});
},
onProgress: (progress) {
setState(() {
loadingPercentage = progress;
});
},
onPageFinished: (url) {
setState(() {
loadingPercentage = 100;
});
},
// Add from here...
onNavigationRequest: (navigation) {
final host = Uri.parse(navigation.url).host;
if (host.contains('youtube.com')) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Blocking navigation to $host',
),
),
);
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
},
// ...to here.
),
);
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
WebViewWidget(
controller: widget.controller,
),
if (loadingPercentage < 100)
LinearProgressIndicator(
value: loadingPercentage / 100.0,
),
],
);
}
}
Sonraki adımda, NavigationDelegate
öğenizi WebViewController
sınıfını kullanarak test etmenizi sağlayacak bir menü öğesi ekleyeceksiniz. Geri çağırma mantığını yalnızca YouTube.com'a tam sayfa gezinmeyi engelleyecek ve API belgelerindeki satır içi YouTube içeriğine izin verecek şekilde genişletmek okuyucunun sorumluluğundadır.
8. AppBar'a menü düğmesi ekleme
Sonraki birkaç adımda, JavaScript'i değerlendirmek, JavaScript kanallarını çağırmak ve çerezleri yönetmek için kullanılan AppBar
widget'ında bir menü düğmesi oluşturacaksınız. Sonuç olarak, gerçekten de faydalı bir menü.
lib/src/menu.dart
konumunda yeni bir kaynak dosyası oluşturun ve aşağıdaki bilgilerle doldurun:
lib/src/menu.dart
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
enum _MenuOptions {
navigationDelegate,
}
class Menu extends StatelessWidget {
const Menu({required this.controller, super.key});
final WebViewController controller;
@override
Widget build(BuildContext context) {
return PopupMenuButton<_MenuOptions>(
onSelected: (value) async {
switch (value) {
case _MenuOptions.navigationDelegate:
await controller.loadRequest(Uri.parse('https://youtube.com'));
}
},
itemBuilder: (context) => [
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.navigationDelegate,
child: Text('Navigate to YouTube'),
),
],
);
}
}
Kullanıcı YouTube'a git menü seçeneğini belirlediğinde WebViewController
'nin loadRequest
yöntemi yürütülür. Bu gezinme, önceki adımda oluşturduğunuz navigationDelegate
geri çağırması tarafından engellenecek.
Menüyü WebViewApp
ekranına eklemek için lib/main.dart
öğesini aşağıdaki gibi değiştirin:
lib/main.dart
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'src/menu.dart'; // ADD
import 'src/navigation_controls.dart';
import 'src/web_view_stack.dart';
void main() {
runApp(
MaterialApp(
theme: ThemeData(useMaterial3: true),
home: const WebViewApp(),
),
);
}
class WebViewApp extends StatefulWidget {
const WebViewApp({super.key});
@override
State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
late final WebViewController controller;
@override
void initState() {
super.initState();
controller = WebViewController()
..loadRequest(
Uri.parse('https://flutter.dev'),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter WebView'),
actions: [
NavigationControls(controller: controller),
Menu(controller: controller), // ADD
],
),
body: WebViewStack(controller: controller),
);
}
}
Uygulamanızı çalıştırın ve YouTube'a git menü öğesine dokunun. Gezinme denetleyicisinin YouTube'a gitmeyi engellediğini bildiren bir SnackBar ile karşılaşırsınız.
9. JavaScript'i değerlendirme
WebViewController
, JavaScript ifadelerini geçerli sayfanın bağlamında değerlendirebilir. JavaScript'i değerlendirmenin iki farklı yolu vardır: Değer döndürmeyen JavaScript kodu için runJavaScript
, değer döndüren JavaScript kodu için ise runJavaScriptReturningResult
kullanın.
JavaScript'i etkinleştirmek için WebViewController
özelliğini javaScriptMode
özelliği JavascriptMode.unrestricted
olarak ayarlanmış şekilde yapılandırmanız gerekir. Varsayılan olarak javascriptMode
, JavascriptMode.disabled
olarak ayarlanır.
_WebViewStackState
sınıfını, javascriptMode
ayarını aşağıdaki şekilde ekleyerek güncelleyin:
lib/src/web_view_stack.dart
class _WebViewStackState extends State<WebViewStack> {
var loadingPercentage = 0;
@override
void initState() {
super.initState();
widget.controller
..setNavigationDelegate( // Modify this line to use .. instead of .
NavigationDelegate(
onPageStarted: (url) {
setState(() {
loadingPercentage = 0;
});
},
onProgress: (progress) {
setState(() {
loadingPercentage = progress;
});
},
onPageFinished: (url) {
setState(() {
loadingPercentage = 100;
});
},
onNavigationRequest: (navigation) {
final host = Uri.parse(navigation.url).host;
if (host.contains('youtube.com')) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Blocking navigation to $host',
),
),
);
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
},
),
)
..setJavaScriptMode(JavaScriptMode.unrestricted); // Add this line
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
WebViewWidget(
controller: widget.controller,
),
if (loadingPercentage < 100)
LinearProgressIndicator(
value: loadingPercentage / 100.0,
),
],
);
}
}
WebViewWidget
artık JavaScript'i çalıştırabildiğinden menüye runJavaScriptReturningResult
yöntemini kullanma seçeneği ekleyebilirsiniz.
Düzenleyicinizi veya klavyenizi kullanarak Menu sınıfını StatefulWidget'a dönüştürün. lib/src/menu.dart
öğesini aşağıdakiyle eşleşecek şekilde değiştirin:
lib/src/menu.dart
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
enum _MenuOptions {
navigationDelegate,
userAgent, // Add this line
}
class Menu extends StatefulWidget { // Convert to StatefulWidget
const Menu({required this.controller, super.key});
final WebViewController controller;
@override // Add from here
State<Menu> createState() => _MenuState();
}
class _MenuState extends State<Menu> { // To here.
@override
Widget build(BuildContext context) {
return PopupMenuButton<_MenuOptions>(
onSelected: (value) async {
switch (value) {
case _MenuOptions.navigationDelegate: // Modify from here
await widget.controller
.loadRequest(Uri.parse('https://youtube.com'));
case _MenuOptions.userAgent:
final userAgent = await widget.controller
.runJavaScriptReturningResult('navigator.userAgent');
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('$userAgent'),
)); // To here.
}
},
itemBuilder: (context) => [
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.navigationDelegate,
child: Text('Navigate to YouTube'),
),
const PopupMenuItem<_MenuOptions>( // Add from here
value: _MenuOptions.userAgent,
child: Text('Show user-agent'),
), // To here.
],
);
}
}
"Kullanıcı aracısını göster" menü seçeneğine dokunduğunuzda, JavaScript ifadesini navigator.userAgent
yürütmenin sonucu Snackbar
içinde gösterilir. Uygulamayı çalıştırırken Flutter.dev sayfasının farklı göründüğünü fark edebilirsiniz. Bu, JavaScript etkinleştirilmiş olarak çalıştırmanın sonucudur.
10. JavaScript kanallarıyla çalışma
JavaScript kanalları, uygulamanızın WebViewWidget
JavaScript bağlamında geri çağırma işleyicileri kaydetmesini sağlar. Bu işleyiciler, değerleri uygulamanın Dart koduna geri iletmek için çağrılabilir. Bu adımda, XMLHttpRequest
sonucuyla çağrılacak bir SnackBar
kanalı kaydedeceksiniz.
WebViewStack
sınıfını aşağıdaki şekilde güncelleyin:
lib/src/web_view_stack.dart
class WebViewStack extends StatefulWidget {
const WebViewStack({required this.controller, super.key});
final WebViewController controller;
@override
State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
var loadingPercentage = 0;
@override
void initState() {
super.initState();
widget.controller
..setNavigationDelegate(
NavigationDelegate(
onPageStarted: (url) {
setState(() {
loadingPercentage = 0;
});
},
onProgress: (progress) {
setState(() {
loadingPercentage = progress;
});
},
onPageFinished: (url) {
setState(() {
loadingPercentage = 100;
});
},
onNavigationRequest: (navigation) {
final host = Uri.parse(navigation.url).host;
if (host.contains('youtube.com')) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Blocking navigation to $host',
),
),
);
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
},
),
)
// Modify from here...
..setJavaScriptMode(JavaScriptMode.unrestricted)
..addJavaScriptChannel(
'SnackBar',
onMessageReceived: (message) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(message.message)));
},
);
// ...to here.
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
WebViewWidget(
controller: widget.controller,
),
if (loadingPercentage < 100)
LinearProgressIndicator(
value: loadingPercentage / 100.0,
),
],
);
}
}
Set
içindeki her JavaScript kanalı için JavaScript bağlamında, JavaScript kanalıyla aynı ada sahip bir pencere özelliği olarak bir kanal nesnesi kullanılabilir name
. Bunu JavaScript bağlamından kullanmak, adlandırılmış JavascriptChannel
öğesinin onMessageReceived
geri çağırma işleyicisine iletilen bir mesajı göndermek için JavaScript Kanalı'nda postMessage
işlevini çağırmayı içerir.
Daha önce eklediğiniz JavaScript kanalını kullanmak için JavaScript bağlamında XMLHttpRequest
işlevini yürüten ve sonuçları SnackBar
JavaScript kanalı aracılığıyla geri ileten başka bir menü öğesi ekleyin.
WebViewWidget
artık JavaScript kanallarımız hakkında bilgi sahibi olduğuna göre,
uygulamayı daha da genişletmek için bir örnek ekleyeceksiniz. Bunu yapmak için Menu
sınıfına fazladan bir PopupMenuItem
ekleyin ve ek işlevselliği uygulayın.
_MenuOptions
numaralandırma değerini ekleyerek _MenuOptions
öğesini ek menü seçeneğiyle güncelleyin ve Menu
sınıfına aşağıdaki gibi bir uygulama ekleyin:javascriptChannel
lib/src/menu.dart
enum _MenuOptions {
navigationDelegate,
userAgent,
javascriptChannel, // Add this option
}
class Menu extends StatefulWidget {
const Menu({required this.controller, super.key});
final WebViewController controller;
@override
State<Menu> createState() => _MenuState();
}
class _MenuState extends State<Menu> {
@override
Widget build(BuildContext context) {
return PopupMenuButton<_MenuOptions>(
onSelected: (value) async {
switch (value) {
case _MenuOptions.navigationDelegate:
await widget.controller
.loadRequest(Uri.parse('https://youtube.com'));
case _MenuOptions.userAgent:
final userAgent = await widget.controller
.runJavaScriptReturningResult('navigator.userAgent');
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('$userAgent'),
));
case _MenuOptions.javascriptChannel: // Add from here
await widget.controller.runJavaScript('''
var req = new XMLHttpRequest();
req.open('GET', "https://api.ipify.org/?format=json");
req.onload = function() {
if (req.status == 200) {
let response = JSON.parse(req.responseText);
SnackBar.postMessage("IP Address: " + response.ip);
} else {
SnackBar.postMessage("Error: " + req.status);
}
}
req.send();'''); // To here.
}
},
itemBuilder: (context) => [
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.navigationDelegate,
child: Text('Navigate to YouTube'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.userAgent,
child: Text('Show user-agent'),
),
const PopupMenuItem<_MenuOptions>( // Add from here
value: _MenuOptions.javascriptChannel,
child: Text('Lookup IP Address'),
), // To here.
],
);
}
}
Bu JavaScript, kullanıcı JavaScript Kanalı Örneği menü seçeneğini belirlediğinde yürütülür.
var req = new XMLHttpRequest();
req.open('GET', "https://api.ipify.org/?format=json");
req.onload = function() {
if (req.status == 200) {
SnackBar.postMessage(req.responseText);
} else {
SnackBar.postMessage("Error: " + req.status);
}
}
req.send();
Bu kod, genel IP adresi API'sine GET
isteği göndererek cihazın IP adresini döndürür. Bu sonuç, SnackBar
JavascriptChannel
üzerinde postMessage
çağrılarak SnackBar
içinde gösterilir.
11. Çerezleri yönetme
Uygulamanız, CookieManager
sınıfını kullanarak WebView
içindeki çerezleri yönetebilir. Bu adımda, çerezlerin listesini gösterecek, çerez listesini temizleyecek, çerezleri silecek ve yeni çerezler ayarlayacaksınız. Çerez kullanım alanlarının her biri için _MenuOptions
bölümüne aşağıdaki gibi girişler ekleyin:
lib/src/menu.dart
enum _MenuOptions {
navigationDelegate,
userAgent,
javascriptChannel,
// Add from here ...
listCookies,
clearCookies,
addCookie,
setCookie,
removeCookie,
// ... to here.
}
Bu adımdaki diğer değişiklikler, Menu
sınıfının durumsuzdan durumluya dönüştürülmesi de dahil olmak üzere Menu
sınıfına odaklanmıştır. Menu
, CookieManager
'nin sahibi olmalıdır ve durumsuz widget'larda değiştirilebilir durum kötü bir kombinasyondur. Bu nedenle bu değişiklik önemlidir.
CookieManager'ı aşağıdaki şekilde sonuçtaki State sınıfına ekleyin:
lib/src/menu.dart
class Menu extends StatefulWidget {
const Menu({required this.controller, super.key});
final WebViewController controller;
@override
State<Menu> createState() => _MenuState();
}
class _MenuState extends State<Menu> {
final cookieManager = WebViewCookieManager(); // Add this line
@override
Widget build(BuildContext context) {
// ...
_MenuState
sınıfı, daha önce Menu
sınıfına eklenen kodun yanı sıra yeni eklenen CookieManager
sınıfını da içerir. Sonraki bölümlerde, _MenuState
öğesine yardımcı işlevler ekleyeceksiniz. Bu işlevler de henüz eklenmemiş menü öğeleri tarafından çağrılacak.
Tüm çerezlerin listesini alma
Tüm çerezlerin listesini almak için JavaScript kullanacaksınız. Bunu yapmak için _MenuState
sınıfının sonuna _onListCookies
adlı bir yardımcı yöntem ekleyin. runJavaScriptReturningResult
yöntemini kullandığınızda yardımcı yönteminiz JavaScript bağlamında document.cookie
kodunu çalıştırarak tüm çerezlerin listesini döndürür.
_MenuState
sınıfına aşağıdakileri ekleyin:
lib/src/menu.dart
Future<void> _onListCookies(WebViewController controller) async {
final String cookies = await controller
.runJavaScriptReturningResult('document.cookie') as String;
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(cookies.isNotEmpty ? cookies : 'There are no cookies.'),
),
);
}
Tüm çerezleri temizleme
WebView'daki tüm çerezleri temizlemek için CookieManager
sınıfının clearCookies
yöntemini kullanın. Yöntem, Future<bool>
döndürür. Bu değer, CookieManager
çerezleri temizlediyse true
, temizlenecek çerez yoksa false
olarak çözümlenir.
_MenuState
sınıfına aşağıdakileri ekleyin:
lib/src/menu.dart
Future<void> _onClearCookies() async {
final hadCookies = await cookieManager.clearCookies();
String message = 'There were cookies. Now, they are gone!';
if (!hadCookies) {
message = 'There were no cookies to clear.';
}
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message),
),
);
}
Çerez ekleme
Çerez eklemek için JavaScript çağrılabilir. Bir JavaScript belgesine çerez eklemek için kullanılan API, MDN'de ayrıntılı olarak belgelenmiştir.
_MenuState
sınıfına aşağıdakileri ekleyin:
lib/src/menu.dart
Future<void> _onAddCookie(WebViewController controller) async {
await controller.runJavaScript('''var date = new Date();
date.setTime(date.getTime()+(30*24*60*60*1000));
document.cookie = "FirstName=John; expires=" + date.toGMTString();''');
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Custom cookie added.'),
),
);
}
CookieManager ile çerez ayarlama
Çerezler, CookieManager kullanılarak da aşağıdaki gibi ayarlanabilir.
_MenuState
sınıfına aşağıdakileri ekleyin:
lib/src/menu.dart
Future<void> _onSetCookie(WebViewController controller) async {
await cookieManager.setCookie(
const WebViewCookie(name: 'foo', value: 'bar', domain: 'flutter.dev'),
);
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Custom cookie is set.'),
),
);
}
Çerez kaldırma
Bir çerezin kaldırılması, son kullanma tarihi geçmişte belirlenmiş bir çerezin eklenmesini içerir.
_MenuState
sınıfına aşağıdakileri ekleyin:
lib/src/menu.dart
Future<void> _onRemoveCookie(WebViewController controller) async {
await controller.runJavaScript(
'document.cookie="FirstName=John; expires=Thu, 01 Jan 1970 00:00:00 UTC" ');
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Custom cookie removed.'),
),
);
}
CookieManager menü öğelerini ekleme
Geriye yalnızca menü seçeneklerini eklemek ve bunları az önce eklediğiniz yardımcı yöntemlere bağlamak kalır. _MenuState
sınıfını aşağıdaki şekilde güncelleyin:
lib/src/menu.dart
class _MenuState extends State<Menu> {
final cookieManager = WebViewCookieManager();
@override
Widget build(BuildContext context) {
return PopupMenuButton<_MenuOptions>(
onSelected: (value) async {
switch (value) {
case _MenuOptions.navigationDelegate:
await widget.controller
.loadRequest(Uri.parse('https://youtube.com'));
case _MenuOptions.userAgent:
final userAgent = await widget.controller
.runJavaScriptReturningResult('navigator.userAgent');
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('$userAgent'),
));
case _MenuOptions.javascriptChannel:
await widget.controller.runJavaScript('''
var req = new XMLHttpRequest();
req.open('GET', "https://api.ipify.org/?format=json");
req.onload = function() {
if (req.status == 200) {
let response = JSON.parse(req.responseText);
SnackBar.postMessage("IP Address: " + response.ip);
} else {
SnackBar.postMessage("Error: " + req.status);
}
}
req.send();''');
case _MenuOptions.clearCookies: // Add from here
await _onClearCookies();
case _MenuOptions.listCookies:
await _onListCookies(widget.controller);
case _MenuOptions.addCookie:
await _onAddCookie(widget.controller);
case _MenuOptions.setCookie:
await _onSetCookie(widget.controller);
case _MenuOptions.removeCookie:
await _onRemoveCookie(widget.controller); // To here.
}
},
itemBuilder: (context) => [
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.navigationDelegate,
child: Text('Navigate to YouTube'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.userAgent,
child: Text('Show user-agent'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.javascriptChannel,
child: Text('Lookup IP Address'),
),
const PopupMenuItem<_MenuOptions>( // Add from here
value: _MenuOptions.clearCookies,
child: Text('Clear cookies'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.listCookies,
child: Text('List cookies'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.addCookie,
child: Text('Add cookie'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.setCookie,
child: Text('Set cookie'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.removeCookie,
child: Text('Remove cookie'),
), // To here.
],
);
}
CookieManager'ı kullanma
Uygulamaya yeni eklediğiniz tüm işlevleri kullanmak için aşağıdaki adımları deneyin:
- Liste çerezleri'ni seçin. Bu listede, flutter.dev tarafından ayarlanan Google Analytics çerezleri yer almalıdır.
- Çerezleri temizle'yi seçin. Çerezlerin gerçekten temizlendiği bildirilmelidir.
- Çerezleri temizle'yi tekrar seçin. Temizlenecek çerez bulunmadığı bildirilmelidir.
- Liste çerezleri'ni seçin. Çerez olmadığını bildirmelidir.
- Çerez ekle'yi seçin. Çerezin eklendiğini bildirmelidir.
- Çerez ayarla'yı seçin. Çerezin ayarlandığını bildirmelidir.
- Çerezleri listele'yi ve ardından son olarak Çerezi kaldır'ı seçin.
12. WebView'da Flutter öğelerini, dosyalarını ve HTML dizelerini yükleme
Uygulamanız, HTML dosyalarını farklı yöntemlerle yükleyip WebView'da gösterebilir. Bu adımda, pubspec.yaml
dosyasında belirtilen bir Flutter öğesini, belirtilen yolda bulunan bir dosyayı ve bir HTML dizesi kullanarak bir sayfayı yükleyeceksiniz.
Belirli bir yolda bulunan bir dosyayı yüklemek istiyorsanız path_provider
öğesini pubspec.yaml
öğesine eklemeniz gerekir. Bu, dosya sisteminde sık kullanılan konumları bulmak için kullanılan bir Flutter eklentisidir.
Komut satırında aşağıdaki komutu çalıştırın:
$ flutter pub add path_provider
Öğeyi yüklemek için pubspec.yaml
içinde öğenin yolunu belirtmemiz gerekir. pubspec.yaml
bölümüne aşağıdaki satırları ekleyin:
pubspec.yaml
# The following section is specific to Flutter packages.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# Add from here
assets:
- assets/www/index.html
- assets/www/styles/style.css
# ... to here.
Öğeleri projenize eklemek için aşağıdaki adımları uygulayın:
- Projenizin kök klasöründe
assets
adlı yeni bir Dizin oluşturun. assets
klasöründewww
adlı yeni bir dizin oluşturun.www
klasöründestyles
adlı yeni bir dizin oluşturun.www
klasöründeindex.html
adlı yeni bir Dosya oluşturun.styles
klasöründestyle.css
adlı yeni bir Dosya oluşturun.
Aşağıdaki kodu kopyalayıp index.html
dosyasına yapıştırın:
assets/www/index.html
<!DOCTYPE html>
<!-- Copyright 2013 The Flutter Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<html lang="en">
<head>
<title>Load file or HTML string example</title>
<link rel="stylesheet" href="styles/style.css" />
</head>
<body>
<h1>Local demo page</h1>
<p>
This is an example page used to demonstrate how to load a local file or HTML
string using the <a href="https://pub.dev/packages/webview_flutter">Flutter
webview</a> plugin.
</p>
</body>
</html>
style.css için HTML başlık stilini ayarlamak üzere aşağıdaki birkaç satırı kullanın:
assets/www/styles/style.css
h1 {
color: blue;
}
Öğeler ayarlanıp kullanıma hazır hale geldiğine göre artık Flutter öğelerini, dosyalarını veya HTML dizelerini yüklemek ve görüntülemek için gereken yöntemleri uygulayabilirsiniz.
Flutter öğesini yükleme
Yeni oluşturduğunuz öğeyi yüklemek için tek yapmanız gereken WebViewController
kullanarak loadFlutterAsset
yöntemini çağırmak ve parametre olarak öğenin yolunu vermektir. Kodunuzun sonuna aşağıdaki yöntemi ekleyin:
lib/src/menu.dart
Future<void> _onLoadFlutterAssetExample(
WebViewController controller, BuildContext context) async {
await controller.loadFlutterAsset('assets/www/index.html');
}
Yerel dosyayı yükleme
Cihazınıza dosya yüklemek için loadFile
yöntemini kullanacak bir yöntem ekleyebilirsiniz. Bunun için yine WebViewController
yöntemini kullanın. Bu yöntem, dosyanın yolunu içeren bir String
alır.
Öncelikle HTML kodunu içeren bir dosya oluşturmanız gerekir. Bunu, menu.dart
dosyasındaki kodunuzun en üstüne, içe aktarma işlemlerinin hemen altına HTML kodunu String olarak ekleyerek yapabilirsiniz.
lib/src/menu.dart
import 'dart:io'; // Add this line,
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart'; // And this one.
import 'package:webview_flutter/webview_flutter.dart';
// Add from here ...
const String kExamplePage = '''
<!DOCTYPE html>
<html lang="en">
<head>
<title>Load file or HTML string example</title>
</head>
<body>
<h1>Local demo page</h1>
<p>
This is an example page used to demonstrate how to load a local file or HTML
string using the <a href="https://pub.dev/packages/webview_flutter">Flutter
webview</a> plugin.
</p>
</body>
</html>
''';
// ... to here.
File
oluşturmak ve HTML dizesini dosyaya yazmak için iki yöntem ekleyeceksiniz. _onLoadLocalFileExample
, _prepareLocalFile()
yöntemi tarafından döndürülen yolu Dize olarak sağlayarak dosyayı yükler. Kodunuza aşağıdaki yöntemleri ekleyin:
lib/src/menu.dart
Future<void> _onLoadLocalFileExample(
WebViewController controller, BuildContext context) async {
final String pathToIndex = await _prepareLocalFile();
await controller.loadFile(pathToIndex);
}
static Future<String> _prepareLocalFile() async {
final String tmpDir = (await getTemporaryDirectory()).path;
final File indexFile = File('$tmpDir/www/index.html');
await Directory('$tmpDir/www').create(recursive: true);
await indexFile.writeAsString(kExamplePage);
return indexFile.path;
}
HTML dizesini yükleme
Bir HTML dizesi sağlayarak sayfayı görüntülemek oldukça basittir. WebViewController
, HTML dizesini bağımsız değişken olarak verebileceğiniz loadHtmlString
adlı bir yönteme sahiptir. Daha sonra WebView
, sağlanan HTML sayfasını gösterir. Kodunuza aşağıdaki yöntemi ekleyin:
lib/src/menu.dart
Future<void> _onLoadFlutterAssetExample(
WebViewController controller, BuildContext context) async {
await controller.loadFlutterAsset('assets/www/index.html');
}
Future<void> _onLoadLocalFileExample(
WebViewController controller, BuildContext context) async {
final String pathToIndex = await _prepareLocalFile();
await controller.loadFile(pathToIndex);
}
static Future<String> _prepareLocalFile() async {
final String tmpDir = (await getTemporaryDirectory()).path;
final File indexFile = File('$tmpDir/www/index.html');
await Directory('$tmpDir/www').create(recursive: true);
await indexFile.writeAsString(kExamplePage);
return indexFile.path;
}
// Add here ...
Future<void> _onLoadHtmlStringExample(
WebViewController controller, BuildContext context) async {
await controller.loadHtmlString(kExamplePage);
}
// ... to here.
Menü öğelerini ekleme
Öğeler ayarlanıp kullanıma hazır hale getirildikten ve tüm işlevlerin yer aldığı yöntemler oluşturulduktan sonra menü güncellenebilir. _MenuOptions
enum'una aşağıdaki girişleri ekleyin:
lib/src/menu.dart
enum _MenuOptions {
navigationDelegate,
userAgent,
javascriptChannel,
listCookies,
clearCookies,
addCookie,
setCookie,
removeCookie,
// Add from here ...
loadFlutterAsset,
loadLocalFile,
loadHtmlString,
// ... to here.
}
Numaralandırma güncellendiğine göre artık menü seçeneklerini ekleyebilir ve bunları az önce eklediğiniz yardımcı yöntemlere bağlayabilirsiniz. _MenuState
sınıfını aşağıdaki şekilde güncelleyin:
lib/src/menu.dart
class _MenuState extends State<Menu> {
final cookieManager = WebViewCookieManager();
@override
Widget build(BuildContext context) {
return PopupMenuButton<_MenuOptions>(
onSelected: (value) async {
switch (value) {
case _MenuOptions.navigationDelegate:
await widget.controller
.loadRequest(Uri.parse('https://youtube.com'));
case _MenuOptions.userAgent:
final userAgent = await widget.controller
.runJavaScriptReturningResult('navigator.userAgent');
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('$userAgent'),
));
case _MenuOptions.javascriptChannel:
await widget.controller.runJavaScript('''
var req = new XMLHttpRequest();
req.open('GET', "https://api.ipify.org/?format=json");
req.onload = function() {
if (req.status == 200) {
let response = JSON.parse(req.responseText);
SnackBar.postMessage("IP Address: " + response.ip);
} else {
SnackBar.postMessage("Error: " + req.status);
}
}
req.send();''');
case _MenuOptions.clearCookies:
await _onClearCookies();
case _MenuOptions.listCookies:
await _onListCookies(widget.controller);
case _MenuOptions.addCookie:
await _onAddCookie(widget.controller);
case _MenuOptions.setCookie:
await _onSetCookie(widget.controller);
case _MenuOptions.removeCookie:
await _onRemoveCookie(widget.controller);
case _MenuOptions.loadFlutterAsset: // Add from here
if (!mounted) return;
await _onLoadFlutterAssetExample(widget.controller, context);
case _MenuOptions.loadLocalFile:
if (!mounted) return;
await _onLoadLocalFileExample(widget.controller, context);
case _MenuOptions.loadHtmlString:
if (!mounted) return;
await _onLoadHtmlStringExample(widget.controller, context);
// To here.
}
},
itemBuilder: (context) => [
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.navigationDelegate,
child: Text('Navigate to YouTube'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.userAgent,
child: Text('Show user-agent'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.javascriptChannel,
child: Text('Lookup IP Address'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.clearCookies,
child: Text('Clear cookies'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.listCookies,
child: Text('List cookies'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.addCookie,
child: Text('Add cookie'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.setCookie,
child: Text('Set cookie'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.removeCookie,
child: Text('Remove cookie'),
),
const PopupMenuItem<_MenuOptions>( // Add from here
value: _MenuOptions.loadFlutterAsset,
child: Text('Load Flutter Asset'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.loadHtmlString,
child: Text('Load HTML string'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.loadLocalFile,
child: Text('Load local file'),
), // To here.
],
);
}
Öğeleri, dosyayı ve HTML dizesini test etme
Yeni uyguladığınız kodun çalışıp çalışmadığını test etmek için kodu cihazınızda çalıştırabilir ve yeni eklenen menü öğelerinden birini tıklayabilirsiniz. _onLoadFlutterAssetExample
etiketinin, HTML dosyasının başlığını mavi renge değiştirmek için eklediğimiz style.css
etiketini nasıl kullandığına dikkat edin.
13. İşlem tamamlandı
Tebrikler!!! Codelab'i tamamlamış olmanız gerekir. Bu codelab'in tamamlanmış kodunu codelab deposunda bulabilirsiniz.
Daha fazla bilgi edinmek için diğer Flutter codelab'lerini deneyin.