Bu codelab hakkında
1. Giriş
Son Güncelleme: 19.10.2021
WebView Flutter eklentisi ile Android veya iOS Flutter uygulamanıza WebView widget'ı ekleyebilirsiniz. iOS'te WebView widget'ı WKWebView, Android'de ise WebView widget'ı WebView ile desteklenir. Bu eklenti, Flutter widget'larını web görünümünde oluşturabilir. Dolayısıyla, örneğin web görünümü üzerinde bir açılır menü oluşturulabilir.
Neler oluşturacaksınız?
Bu codelab'de, Flutter SDK'sını kullanarak bir WebView'u öne çıkaran, adım adım mobil uygulama geliştireceksiniz. Uygulamanız şunları yapabilecek:
- Web içeriğini
WebView
uygulamasında göster WebView
üzerine yığılmış Flutter widget'ları gösterme- Sayfa yükleme ilerleme durumuna yönelik etkinliklere tepki verme
WebView
öğesiniWebViewController
aracılığıyla kontrol edinNavigationDelegate
özelliğini kullanan web sitelerini engelleyin- JavaScript ifadelerini değerlendirme
- JavaScript'ten gelen geri çağırmaları
JavascriptChannels
ile ele alın - Çerezleri ayarlama, kaldırma, ekleme veya gösterme
- Öğelerden, dosyalardan veya HTML içeren dizelerden HTML yükleyin ve görüntüleyin
Neler öğreneceksiniz?
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 durumu etkinliklerini dinleme
- Sayfada gezinmeyi kontrol etme
WebView
'e geçmişinde geri ve ileri gitme komutu verme- Döndürülen sonuçların kullanımı da dahil olmak üzere JavaScript'i değerlendirme
- JavaScript'ten Dart kodu çağırmak için geri çağırmalar kaydetme
- Çerezler nasıl yönetilir?
- Öğelerden veya dosyalardan ya da HTML içeren dizeden HTML sayfaları yükleme ve görüntüleme
İhtiyacınız olanlar
- Android Studio 4.1 veya sonraki sürümler (Android geliştirme için)
- Xcode 12 veya üzeri (iOS geliştirme için)
- Flutter SDK'sı
- Android Studio, Visual Studio Code veya Emacs gibi bir kod düzenleyici.
2. Flutter geliştirme ortamınızı kurma
Bu laboratuvarı tamamlamak için Flutter SDK ve bir düzenleyici yazılımına ihtiyacınız vardır.
Codelab'i aşağıdaki cihazlardan birini kullanarak çalıştırabilirsiniz:
- Bilgisayarınıza bağlı ve Geliştirici moduna ayarlanmış fiziksel bir Android veya iOS cihaz.
- iOS simülasyon aracı (Xcode araçlarının yüklenmesi gerekir).
- Android Emülatörü (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 gerekli araçları sağlar. Proje oluşturmak için bağlantı verilen prosedürleri uygulayın veya kullanışlı bir komut satırı terminalinde aşağıdaki komutları ç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.
Bağımlılık olarak WebView Flutter eklentisi ekleme
Pub paketlerini kullanarak Flutter uygulamasına yeni özellikler eklemek kolaydı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'sını yapılandırma
webview_flutter
eklentisini Android'de kullanmak için minSDK
özelliğini 20
olarak ayarlamanız 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. Web Görünümleri, barındırılan yerel görünümlerdir ve uygulama geliştirici olarak bu yerel görünümleri uygulamanızda nasıl barındıracağınızı seçebilirsiniz. Android'de, Android'in varsayılan ayarı olan Sanal Ekran ile Karma ekran arasından seçim yapabilirsiniz. Ancak iOS her zaman Karma bileşim kullanır.
Sanal Ekranlar ve Karma beste arasındaki farklılıkların ayrıntılı bir açıklaması için lütfen Platform Görünümleri ile Flutter uygulamanızda yerel Android ve iOS görünümleri barındırma hakkındaki dokümanları okuyun.
Ekrana web görünümü yerleştirme
lib/main.dart
içeriğini şununla 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 uygulama iOS veya Android'de çalıştırıldığında, Web Görünümü, cihazınızda tam çerçeveli bir tarayıcı penceresi olarak gösterilir. Bu pencere, tarayıcının cihazınızda herhangi bir kenarlık veya kenar boşluğu olmadan tam ekranda gösterildiği anlamına gelir. Kaydırırken sayfanın biraz tuhaf görünebileceğini fark edeceksiniz. Bunun nedeni JavaScript'in şu anda devre dışı olması ve flutter.dev'in 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 Web Görünümü 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ırabilirsiniz. İlk WebView URL'sini kendi web sitenizle değiştirmekten çekinmeyin.
$ flutter run
Uygulamayı derleyip cihazınıza dağıttıktan sonra aşağıdakine benzer bir simülatör veya emülatörün çalıştığını ya da fiziksel bir cihazınızın olduğunu varsayarsak aşağıdakine benzer bir sonuç görürsünüz:
5. Sayfa yükleme etkinlikleri dinleniyor
WebView
widget'ı, uygulamanızın dinleyebileceği çeşitli sayfa yükleme ilerleme etkinlikleri sağlar. WebView
sayfa yükleme döngüsü sırasında tetiklenen üç farklı sayfa yükleme etkinliği vardır: onPageStarted
, onProgress
ve onPageFinished
. Bu adımda bir sayfa yükleme göstergesi uygulayacaksınız. Bu sayede, WebView
içerik alanı üzerinde Flutter içeriği oluşturabileceğiniz de gösterilir.
Uygulamanıza sayfa yükleme etkinlikleri ekleme
lib/src/web_view_stack.dart
adresinde yeni bir kaynak dosya oluşturun ve dosyayı 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ı bir Stack
içine sarmış ve sayfa yükleme yüzdesi %100'den az olduğunda WebView
öğesini koşullu olarak bir LinearProgressIndicator
ile yerleştirmiştir. Zaman içinde değişen program durumu da söz konusu olduğundan bu durumu StatefulWidget
ile ilişkili bir State
sınıfında depoladınız.
Bu yeni WebViewStack
widget'ından yararlanmak için lib/main.dart
öğenizi şu ş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 ziyaret ettiğ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 kumanda, WebView
widget'ının oluşturulmasından sonra, geri çağırma yoluyla kullanıma sunulur. Kullanılabilirliğinin eşzamansız olması, bu denetleyiciyi Dart'ın eşzamansız Completer<T>
sınıfı için başlıca aday haline getirir.
lib/src/web_view_stack.dart
'ü 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}); // 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 etrafındaki widget'ta oluşturulan bir kumandayı kullanıyor. Bu sayede, WebViewWidget
için denetleyicinin uygulamanın diğer bölümleriyle kolayca paylaşılması sağlanır.
Gezinme Denetimleri Oluşturma
Çalışan bir WebView
'e sahip olmak bir şeydir ancak sayfa geçmişinde geri ve ileri gidebilmek ve sayfayı yeniden yükleyebilmek yararlı bir ekleme olur. Neyse ki WebViewController
ile bu işlevi uygulamanıza ekleyebilirsiniz.
lib/src/navigation_controls.dart
adresinde yeni bir kaynak dosya oluşturun ve aşağıdakini girin:
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 WebView
öğesini bir dizi IconButton
aracılığıyla kontrol edebilmesi için, oluşturma sırasında kendisiyle paylaşılan WebViewController
kullanır.
AppBar'a gezinme denetimleri ekleme
Güncellenmiş WebViewStack
ve yeni geliştirilen NavigationControls
ile artık her şeyi güncellenmiş bir WebViewApp
dosyasında bir araya getirmenin zamanı geldi. Paylaşılan WebViewController
öğesini burada oluştururuz. Bu uygulamadaki widget ağacının üst kısmına yakın bir yerde bulunan WebViewApp
için bu düzeyde oluşturma işlemini gerçekleştirmek mantıklı olacaktı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
);
}
}
Uygulamayı çalıştırdığınızda kontrollerin bulunduğu bir web sayfası gösterilir:
7. Gezinme Temsilcisi ile navigasyonu takip etme
WebView
, uygulamanıza WebView
widget'ının sayfada gezinmesini izleme ve kontrol etme olanağı tanıyan bir NavigationDelegate,
sağlar. WebView,
tarafından bir gezinme işlemi başlatıldığında (ör. kullanıcı bir bağlantıyı tıkladığında) NavigationDelegate
çağrılır. NavigationDelegate
geri çağırması, WebView
öğesinin gezinmeye devam edip etmeyeceğini kontrol etmek için kullanılabilir.
Özel NavigationDelegate kaydetme
Bu adımda, YouTube.com adresine gitmeyi engellemek için bir NavigationDelegate
geri çağırma işlevi kaydedersiniz. 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
öğesini ş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});
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, WebViewController
sınıfını kullanarak NavigationDelegate
cihazınızı test etmenize olanak tanıyan bir menü öğesi ekleyeceksiniz. Okuyucu için geri çağırma mantığının kapsamını genişleterek, YouTube.com'da yalnızca tam sayfada gezinmeyi engellemek ve API dokümanlarında satır içi YouTube içeriğine izin vermeye devam etmek için bırakıldı.
8. AppBar'a menü düğmesi ekleme
Sonraki birkaç adımda, AppBar
widget'ında JavaScript'i değerlendirmek, JavaScript kanallarını çağırmak ve çerezleri yönetmek için kullanılacak bir menü düğmesi oluşturacaksınız. Tam anlamıyla yararlı bir menü.
lib/src/menu.dart
adresinde yeni bir kaynak dosya oluşturun ve aşağıdakini girin:
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
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ıp YouTube'a Git menü öğesine dokunun. Gezinme denetleyicisinin YouTube'a gitmeyi engellediğini bildiren bir SnackBar ile karşılaşacaksı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 kodları için runJavaScript
, değer döndüren JavaScript kodları için runJavaScriptReturningResult
kullanın.
JavaScript'i etkinleştirmek için WebViewController
öğesini, javaScriptMode
özelliği JavascriptMode.unrestricted
olacak şekilde yapılandırmanız gerekir. javascriptMode
, varsayılan olarak JavascriptMode.disabled
değerine ayarlıdır.
javascriptMode
ayarını aşağıdaki şekilde ekleyerek _WebViewStackState
sınıfını 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,
),
],
);
}
}
Artık WebViewWidget
JavaScript yürütebildiğine göre runJavaScriptReturningResult
yöntemini kullanmak için menüye bir seçenek ekleyebilirsiniz.
Düzenleyicinizi veya bazı klavye işlemlerini kullanarak Menü sınıfını StatefulWidget'a dönüştürün. lib/src/menu.dart
değerini 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"e dokunduğunuzda seçeneğinde, navigator.userAgent
JavaScript ifadesinin çalıştırılmasının sonucu bir Snackbar
içinde gösterilir. Uygulamayı çalıştırırken Flutter.dev sayfasının farklı göründüğünü fark edebilirsiniz. Bu, JavaScript'in etkin olduğu çalıştırmanın bir sonucudur.
10. JavaScript kanallarıyla çalışma
JavaScript Kanalları, uygulamanızın değerleri uygulamanın Dart koduna geri aktarmak için çağrılabilecek WebViewWidget
JavaScript bağlamında geri çağırma işleyicileri kaydetmesine olanak tanır. Bu adımda, XMLHttpRequest
sonucuyla çağrılacak bir SnackBar
kanalı kaydedeceksiniz.
WebViewStack
sınıfını aşağıdaki gibi 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 bir JavaScript Kanalı için kanal nesnesi, JavaScript bağlamında name
JavaScript Kanalı ile aynı ada sahip bir pencere özelliği olarak sunulur. Bunun JavaScript bağlamından kullanılması, JavascriptChannel
adlı kullanıcının onMessageReceived
geri çağırma işleyicisine iletilecek bir mesajı göndermek için JavaScript Kanalında postMessage
çağrısı yapmayı içerir.
Yukarıda eklenen JavaScript Kanalından yararlanmak için, JavaScript bağlamında bir XMLHttpRequest
yürüten ve sonuçları SnackBar
JavaScript Kanalını kullanarak geri veren başka bir menü öğesi ekleyin.
WebViewWidget
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 ekstra işlevi dahil edin.
javascriptChannel
numaralandırma değerini ekleyerek _MenuOptions
öğesini ekstra menü seçeneğiyle güncelleyin ve aşağıdaki şekilde Menu
sınıfına bir uygulama ekleyin:
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, cihazın IP adresini döndüren bir GET
isteği gönderir. Bu sonuç, SnackBar
JavascriptChannel
üzerinde postMessage
çağrılarak bir 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 bir çerez listesi gösterir, çerez listesini temizler, çerezleri siler ve yeni çerezler ayarlarsınız. Çerez kullanım alanlarının her biri için _MenuOptions
öğesine 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 değişikliklerin geri kalanı, Menu
sınıfının durum bilgisizden durum bilgiliye dönüştürülmesi de dahil olmak üzere Menu
sınıfına odaklanmıştır. Menu
öğesinin, CookieManager
öğesinin sahibi olması gerektiğinden bu değişiklik önemlidir ve durum bilgisiz widget'larda değişebilir durum kötü bir kombinasyondur.
CookieManager'ı elde edilen State sınıfına aşağıdaki gibi 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ı, yeni eklenen CookieManager
ile birlikte daha önce Menu
sınıfına eklenen kodu içerir. Sonraki bölüm dizilerinde, _MenuState
öğesine yardımcı işlevler ekleyeceksiniz. Bu işlevler de henüz eklenmemiş menü öğeleri tarafından çağrılacaktır.
Tüm çerezlerin listesini alma
Tüm çerezlerin listesini almak için JavaScript kullanacaksınız. Bunu sağlamak için _MenuState
sınıfının sonuna _onListCookies
adlı bir yardımcı yöntem ekleyin. Yardımcı yönteminiz, runJavaScriptReturningResult
yöntemini kullanarak JavaScript bağlamında document.cookie
öğesini yürüterek 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
Web Görünümü'ndeki tüm çerezleri temizlemek için CookieManager
sınıfının clearCookies
yöntemini kullanın. Yöntem, CookieManager
çerezleri temizlediyse true
, temizlenecek çerez yoksa false
olarak çözümlenen bir Future<bool>
döndürür.
_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, JavaScript'in çağrılmasıyla yapılabilir. JavaScript dokümanına Çerez eklemek için kullanılan API, MDN üzerinde ayrıntılı olarak belgelenmiştir.
_MenuState
sınıfına şunu 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 oluşturma
Çerezler, CookieManager kullanılarak da aşağıdaki gibi ayarlanabilir.
_MenuState
sınıfına şunu 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
Çerez kaldırma işlemi, son kullanma tarihi geçmiş bir tarihe ayarlanmış bir çerez eklemeyi kapsar.
_MenuState
sınıfına şunu 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 sadece menü seçeneklerini ekleyip, eklediğiniz yardımcı yöntemlere aktarmak yeterli olacaktı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'ı uygulama
Uygulamaya yeni eklediğiniz tüm işlevleri kullanmak için aşağıdaki adımları deneyin:
- Liste çerezleri'ni seçin. flutter.dev tarafından ayarlanan Google Analytics çerezleri listelenmelidir.
- Çerezleri temizle'yi seçin. Çerezlerin gerçekten temizlendiğini bildirmelidir.
- Tekrar Çerezleri temizle'yi seçin. Temizlenecek çerez olmadığı bildirilir.
- Çerezleri listele'yi seçin. Çerez olmadığını bildirmelidir.
- Çerez ekle'yi seçin. Çerezi eklenmiş olarak bildirmelidir.
- Çerez ayarla'yı seçin. Çerezi ayarlandığı şekilde bildirmelidir.
- Çerezleri listele'yi, ardından son olarak Çerez kaldır'ı seçin.
12. WebView'e Flutter öğelerini, dosyalarını ve HTML dizelerini yükleme
Uygulamanız, farklı yöntemler kullanarak HTML dosyalarını yükleyebilir ve bunları Web Görünümü'nde gösterebilir. Bu adımda pubspec.yaml
dosyasında belirtilen bir Flutter öğesini yükleyecek, belirtilen yolda bulunan bir dosyayı yükleyecek ve HTML Dizesi kullanarak bir sayfa yükleyeceksiniz.
Belirli bir yolda bulunan bir dosyayı yüklemek istiyorsanız pubspec.yaml
öğesine path_provider
eklemeniz gerekir. Bu, dosya sisteminde yaygın olarak 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 öğenin yolunu pubspec.yaml
içinde belirtmemiz gerekir. pubspec.yaml
içine 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
adıyla yeni bir Dizin oluşturun. assets
klasöründewww
adında yeni bir Dizin oluşturun.www
klasöründestyles
adında yeni bir Dizin oluşturun.www
klasöründeindex.html
adında yeni bir Dosya oluşturun.styles
klasöründestyle.css
adında yeni bir Dosya oluşturun.
Aşağıdaki kodu kopyalayıp index.html
dosyasına yapıştırın:
<!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:
h1 {
color: blue;
}
Öğeler ayarlandığına ve kullanıma hazır olduğuna göre artık Flutter öğelerini, dosyaları 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 tüm yapmanız gereken WebViewController
kullanarak loadFlutterAsset
yöntemini çağırmak ve öğenin yolunu parametre olarak 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. Bu yöntem için, dosyanın yolunu içeren bir String
alan WebViewController
yöntemini tekrar kullanırsınız.
Öncelikle HTML kodunu içeren bir dosya oluşturmanız gerekir. Bunu, içe aktarma işlemlerinin hemen altındaki menu.dart
dosyasında kodunuzun üst kısmına bir Dize olarak HTML kodunu ekleyerek yapabilirsiniz.
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 eklersiniz. _onLoadLocalFileExample
, yolu _prepareLocalFile()
yöntemi tarafından döndürülen bir Dize şeklinde sağlayarak dosyayı yükler. Aşağıdaki yöntemleri kodunuza ekleyin:
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 Dizesi yükleme
Bir sayfayı HTML dizesi sağlayarak görüntülemek oldukça basit bir işlemdir. WebViewController
, HTML Dizesini bağımsız değişken olarak verebileceğiniz loadHtmlString
adlı bir yönteme sahiptir. Bunun ardından WebView
, sağlanan HTML sayfasını gösterir. Aşağıdaki yöntemi kodunuza ekleyin:
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 getirildiğine ve tüm işlevleri içeren yöntemler yapıldığına göre artık menü güncellenebilir. _MenuOptions
sıralamasına şu 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.
}
Sıralama güncellendiğine göre menü seçeneklerini ekleyebilir ve 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
Kodun az önce uyguladığınız kodu çalışıp çalışmadığını test etmek için kodu cihazınızda çalıştırıp yeni eklenen menü öğelerinden birini tıklayabilirsiniz. _onLoadFlutterAssetExample
'ün, HTML dosyasının başlığını mavi renge değiştirmek için eklediğimiz style.css
'u nasıl kullandığına dikkat edin.
13. Hepsi bu kadar.
Tebrikler!!! Codelab'i tamamladınız. Bu codelab'in tamamlanmış kodunu codelab deposunda bulabilirsiniz.
Daha fazla bilgi edinmek için diğer Flutter codelab'lerini deneyin.