Last Updated on February 4, 2023 by
Pengembangan aplikasi Flutter berkembang pesat karena spesifikasinya yang unik. Tentunya sebagai developer harus memahami sistem flutter focus dengan baik. Bergantung pada kebutuhan, ini termasuk bagian dari keyword focus system dalam pengembangan aplikasi.
Sistem Flutter Focus mudah dipahami dan dipelihara sebagai bagian dari aplikasi. Ini terutama difokuskan pada menekan keyword shortcut tertentu juga.
Pada Artikel kali ini kita akan belajar Flutter dan cara mengontrol ke mana input keyboard diarahkan. Jika Anda mengimplementasikan aplikasi yang menggunakan keyboard fisik, seperti sebagian besar aplikasi desktop dan web, halaman ini cocok untuk Anda.
Table of Contents
Flutter Focus System
Belajar Flutter hadir dengan sistem fokus yang mengarahkan input keyboard ke bagian tertentu dari aplikasi. Untuk melakukannya, pengguna “memfokuskan” input ke bagian aplikasi tersebut dengan mengetuk atau mengklik elemen UI yang diinginkan.
Setelah itu terjadi, teks yang dimasukkan dengan keyboard mengalir ke bagian aplikasi tersebut hingga fokus berpindah ke bagian lain dari aplikasi tersebut. Fokus juga dapat dipindahkan dengan menekan pintasan keyboard tertentu, yang biasanya terikat ke tombol Tab , sehingga terkadang disebut “penjelajahan tab”.
Elemen Flutter Focus System
Di bawah ini adalah istilah, seperti yang digunakan untuk elemen Flutter Focus. Berbagai kelas yang menerapkan beberapa konsep ini diperkenalkan di bawah ini.
- Focus tree – Pohon simpul fokus yang biasanya sedikit mencerminkan pohon widget, mewakili semua widget yang dapat menerima fokus.
- Focus node – Node tunggal dalam pohon fokus. Node ini dapat menerima fokus, dan dikatakan “memiliki fokus” jika menjadi bagian dari rantai fokus. Itu berpartisipasi dalam menangani peristiwa-key event hanya ketika memiliki fokus.
- Primary focus – Node fokus terjauh dari akar pohon fokus yang memiliki fokus. Ini adalah simpul fokus tempat key event mulai menyebar ke simpul fokus utama dan leluhurnya.
- Focus chain – Daftar urutan simpul fokus yang dimulai dari simpul fokus utama dan mengikuti cabang pohon fokus ke akar pohon fokus.
- Focus scope – Node fokus khusus yang tugasnya memuat sekelompok node fokus lainnya, dan hanya mengizinkan node tersebut untuk menerima fokus. Ini berisi informasi tentang node mana yang sebelumnya difokuskan pada subtree-nya.
- Focus traversal – Proses perpindahan dari satu node yang dapat difokuskan ke node lain dalam urutan yang dapat diprediksi. Ini biasanya terlihat di aplikasi saat pengguna menekan tombol Tab untuk berpindah ke kontrol atau bidang yang dapat difokuskan berikutnya.
FocusNode dan FocusScopeNode
Objek FocusNode menerapkan FocusScopeNode mekanisme flutter focus. Mereka adalah objek berumur panjang (lebih panjang dari widget, mirip dengan objek render) yang menyimpan status dan atribut fokus sehingga tetap ada di antara build pohon widget. Bersama-sama, mereka membentuk struktur data pohon fokus.
Mereka awalnya dimaksudkan untuk menjadi objek yang dihadapi developer yang digunakan untuk mengontrol beberapa aspek Fluter Focus system, tetapi seiring waktu mereka telah berevolusi untuk sebagian besar mengimplementasikan detail sistem fokus.
Untuk mencegah kerusakan aplikasi yang ada, mereka masih mengandung antarmuka publik untuk atributnya. Namun, secara umum, hal yang paling berguna adalah bertindak sebagai pegangan yang relatif buram, diteruskan ke widget turunan untuk memanggil requestFocus() widget ancestor, yang meminta agar widget turunan mendapatkan fokus. Pengaturan atribut lainnya paling baik dikelola oleh Focus atau FocusScopewidget, kecuali jika Anda tidak menggunakannya, atau menerapkan versi Anda sendiri.
Unfocus
Ada API untuk memberi tahu sebuah node untuk “give up focus”, bernama FocusNode.unfocus(). Meskipun menghilangkan fokus dari node, penting untuk disadari bahwa sebenarnya tidak ada yang namanya “unfocusing” di semua node. Jika sebuah node unfocus, maka harus melewati fokus di tempat lain, karena selalu ada fokus utama. Simpul yang menerima Flutter focus ketika sebuah simpul memanggil unfocus()adalah simpul terdekat FocusScopeNode, atau simpul yang sebelumnya terfokus dalam lingkup itu, bergantung pada disposition argumen yang diberikan kepada unfocus(). Jika Anda ingin lebih banyak kontrol ke mana fokus pergi ketika Anda menghapusnya dari sebuah node, fokuskan node lain secara eksplisit alih-alih memanggil unfocus(), atau gunakan mekanisme traversal fokus untuk menemukan node lain dengan metode focusInDirection, nextFocus, atau previousFocus pada FocusNode.
Saat memanggil unfocus(), disposition argumen memungkinkan dua mode untuk unfocus: UnfocusDisposition.scope dan UnfocusDisposition.previouslyFocusedChild.
Standarnya adalah scope, yang memberikan fokus ke cakupan fokus induk terdekat. Ini berarti bahwa jika fokus kemudian dipindahkan ke node berikutnya dengan FocusNode.nextFocus, maka dimulai dengan item yang dapat difokuskan “pertama” dalam cakupan.
Disposisi previouslyFocusedChild akan mencari ruang lingkup untuk menemukan anak yang sebelumnya difokuskan dan meminta fokus padanya. Jika tidak ada anak yang difokuskan sebelumnya, itu setara dengan scope.
Focus Widget
Dalam belajar flutter yang paling sederhana, membungkus Focus widget di sekitar subtree widget memungkinkan subtree widget untuk mendapatkan fokus sebagai bagian dari proses traversal fokus, atau kapanpun request Focus dipanggil saat FocusNode diteruskan ke sana. Saat digabungkan dengan pendeteksi isyarat yang memanggil requestFocus, ia dapat menerima fokus saat diketuk atau diklik.
Anda mungkin meneruskan FocusNode objek ke Focuswidget untuk dikelola, tetapi jika tidak, widget akan membuatnya sendiri. Alasan utama untuk membuatnya sendiri FocusNode adalah agar dapat memanggil requestFocus() node untuk mengontrol fokus dari widget induk. Sebagian besar fungsi lain dari a FocusNode paling baik diakses dengan mengubah atribut Focuswidget itu sendiri.
Widget digunakan di Focus sebagian besar kontrol Flutter sendiri untuk mengimplementasikan fungsi fokusnya.
Berikut adalah contoh yang menunjukkan cara menggunakan Focuswidget untuk membuat kontrol khusus dapat difokuskan. Itu membuat wadah dengan teks yang bereaksi untuk menerima fokus.
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); static const String _title = 'Focus Sample'; @override Widget build(BuildContext context) { return MaterialApp( title: _title, home: Scaffold( appBar: AppBar(title: const Text(_title)), body: Column( mainAxisAlignment: MainAxisAlignment.center, children: const <Widget>[MyCustomWidget(), MyCustomWidget()], ), ), ); } } class MyCustomWidget extends StatefulWidget { const MyCustomWidget({super.key}); @override State<MyCustomWidget> createState() => _MyCustomWidgetState(); } class _MyCustomWidgetState extends State<MyCustomWidget> { Color _color = Colors.white; String _label = 'Unfocused'; @override Widget build(BuildContext context) { return Focus( onFocusChange: (focused) { setState(() { _color = focused ? Colors.black26 : Colors.white; _label = focused ? 'Focused' : 'Unfocused'; }); }, child: Center( child: Container( width: 300, height: 50, alignment: Alignment.center, color: _color, child: Text(_label), ), ), ); } }
Key Event Flutter Focus
Key event dimulai pada simpul fokus dengan fokus utama. Jika simpul itu tidak kembali KeyEventResult.handled dari onKeyHandler, maka simpul fokus induknya diberikan peristiwa tersebut. Jika induknya tidak menanganinya, ia pergi ke induknya, dan seterusnya, hingga mencapai akar pohon fokus. Jika peristiwa mencapai akar pohon fokus tanpa ditangani, peristiwa tersebut dikembalikan ke platform untuk diberikan ke kontrol native berikutnya dalam aplikasi (jika Flutter UI adalah bagian dari UI aplikasi native yang lebih besar). Acara yang ditangani tidak disebarkan ke widget Flutter lain, dan juga tidak disebarkan ke widget asli.
Berikut adalah contoh Focuswidget yang menyerap setiap kunci yang tidak ditangani oleh subpohonnya, tanpa dapat menjadi fokus utama:
@override Widget build(BuildContext context) { return Focus( onKey: (node, event) => KeyEventResult.handled, canRequestFocus: false, child: child, ); }
Key Event Flutter focus diproses sebelum peristiwa entri teks, sehingga penanganan peristiwa kunci saat widget fokus mengelilingi bidang teks akan mencegah tombol tersebut dimasukkan ke dalam bidang teks.
Berikut adalah contoh widget yang tidak mengizinkan huruf “a” diketik ke dalam bidang teks:
@override Widget build(BuildContext context) { return Focus( onKey: (node, event) { return (event.logicalKey == LogicalKeyboardKey.keyA) ? KeyEventResult.handled : KeyEventResult.ignored; }, child: TextField(), ); }
Jika maksudnya adalah validasi input, fungsionalitas contoh ini mungkin akan lebih baik diimplementasikan menggunakan a TextInputFormatter, tetapi tekniknya masih bisa berguna: Shortcutswidget menggunakan metode ini untuk menangani pintasan sebelum menjadi input teks, misalnya.
Mendapatkan FocusNode
Untuk mengakses simpul fokus dari ancestor Focuswidget, buat dan teruskan FocusNode sebagai atribut Focuswidget. Karena perlu dibuang, node fokus yang Anda lewati harus dimiliki oleh widget stateful, jadi jangan hanya membuatnya setiap kali dibangun.
Jika Anda memerlukan akses ke node fokus dari turunan Focuswidget, Anda dapat memanggil Focus.of(context) untuk mendapatkan node fokus Focus widget terdekat dengan konteks yang diberikan. Jika Anda perlu mendapatkan FocusNodewidget Focus dalam fungsi build yang sama, gunakan Builder untuk memastikan Anda memiliki konteks yang benar. Ini ditunjukkan dalam contoh berikut:
@override Widget build(BuildContext context) { return Focus( child: Builder( builder: (context) { final bool hasPrimary = Focus.of(context).hasPrimaryFocus; print('Building with primary focus: $hasPrimary'); return const SizedBox(width: 100, height: 100); }, ), ); }
Widget FocusScope
Widget FocusScope adalah versi khusus dari Focuswidget yang mengatur FocusScopeNode bukan FocusNode. FocusScopeNode adalah simpul khusus di Focus Tree yang berfungsi sebagai mekanisme pengelompokan untuk simpul fokus di subtree. Traversal fokus tetap berada dalam lingkup fokus kecuali sebuah node di luar lingkup difokuskan secara eksplisit.
Lingkup fokus juga melacak fokus saat ini dan riwayat node yang difokuskan di dalam subtreenya. Dengan begitu, jika sebuah node melepaskan fokus atau dihilangkan saat memiliki fokus, fokus tersebut dapat dikembalikan ke node yang memiliki fokus sebelumnya.
Cakupan fokus juga berfungsi sebagai tempat untuk mengembalikan fokus jika tidak ada turunan yang memiliki fokus. Hal ini memungkinkan kode traversal fokus memiliki konteks awal untuk menemukan kontrol berikutnya (atau pertama) yang dapat difokuskan untuk dipindahkan.
Jika Anda memfokuskan node lingkup fokus, pertama-tama ia akan mencoba memfokuskan node saat ini, atau node yang baru saja difokuskan di sub pohonnya, atau node di subtreenya yang meminta fokus otomatis (jika ada). Jika tidak ada simpul seperti itu, ia menerima fokus itu sendiri.
Mengontrol traversal fokus
Setelah aplikasi memiliki kemampuan untuk fokus, hal berikutnya yang ingin dilakukan oleh banyak aplikasi adalah mengizinkan pengguna untuk mengontrol fokus menggunakan keyboard atau perangkat input lainnya. Contoh paling umum dari ini adalah “tab traversal” di mana pengguna menekan tombol Tab untuk pergi ke kontrol “berikutnya”.
Mengontrol “selanjutnya” adalah subjek dari bagian ini. Traversal semacam ini disediakan oleh Flutter secara default.
Dalam tata letak kisi sederhana, cukup mudah untuk memutuskan kontrol mana yang berikutnya. Jika Anda tidak berada di akhir baris, maka baris tersebut berada di kanan (atau kiri untuk lokal kanan-ke-kiri). Jika Anda berada di akhir baris, ini adalah kontrol pertama di baris berikutnya. Sayangnya, aplikasi jarang ditata dalam kisi-kisi, sehingga diperlukan lebih banyak panduan.
Algoritma default di Flutter focus (ReadingOrderTraversalPolicy) untuk traversal fokus cukup bagus: Ini memberikan jawaban yang tepat untuk sebagian besar aplikasi. Namun, selalu ada kasus patologis, atau kasus di mana konteks atau desain memerlukan urutan yang berbeda dari urutan algoritma pengurutan default. Untuk kasus tersebut, ada mekanisme lain untuk mencapai urutan yang diinginkan.
Widget FocusTraversalGroup
Widget harus ditempatkan di FocusTraversalGroup hierarki di sekitar subtree widget yang harus dilintasi sepenuhnya sebelum beralih ke widget atau grup widget lain. Hanya mengelompokkan widget ke dalam grup terkait seringkali cukup untuk menyelesaikan banyak masalah pemesanan traversal tab. Jika tidak, grup juga dapat diberikan FocusTraversalPolicy untuk menentukan urutan dalam grup.
Standarnya ReadingOrderTraversalPolicy biasanya cukup, tetapi dalam kasus di mana diperlukan lebih banyak kontrol atas pemesanan, OrderedTraversalPolicy dapat digunakan. Argumen widget order flutter focus yang ada di FocusTraversalOrder melilit komponen yang dapat difokuskan menentukan urutannya. Urutan dapat berupa subkelas apa pun dari FocusOrder, tetapi NumericFocusOrder dan LexicalFocusOrder disediakan.
Jika tidak ada kebijakan traversal fokus yang disediakan cukup untuk aplikasi Anda, Anda juga dapat menulis kebijakan Anda sendiri dan menggunakannya untuk menentukan pemesanan kustom yang Anda inginkan.
Berikut adalah contoh cara menggunakan FocusTraversalOrderwidget untuk melintasi deretan tombol dalam urutan SATU, DUA, TIGA menggunakan NumericFocusOrder.
class OrderedButtonRow extends StatelessWidget { const OrderedButtonRow({super.key}); @override Widget build(BuildContext context) { return FocusTraversalGroup( policy: OrderedTraversalPolicy(), child: Row( children: <Widget>[ const Spacer(), FocusTraversalOrder( order: NumericFocusOrder(2.0), child: TextButton( child: const Text('ONE'), onPressed: () {}, ), ), const Spacer(), FocusTraversalOrder( order: NumericFocusOrder(1.0), child: TextButton( child: const Text('TWO'), onPressed: () {}, ), ), const Spacer(), FocusTraversalOrder( order: NumericFocusOrder(3.0), child: TextButton( child: const Text('THREE'), onPressed: () {}, ), ), const Spacer(), ], ), ); } }
Temukan lebih banyak artikel seri belajar Dart maupun bahasa pemrograman lainnya hanya di CODEKEY. Klik https://codekey.id/ sekarang juga untuk langsung belajar gratis. Sampai bertemu lagi!
Jasa Pembuatan Aplikasi, Website dan Internet Marketing | PT APPKEY
PT APPKEY adalah perusahaan IT yang khusus membuat aplikasi Android, iOS dan mengembangkan sistem website. Kami juga memiliki pengetahuan dan wawasan dalam menjalankan pemasaran online sehingga diharapkan dapat membantu menyelesaikan permasalahan Anda.