# Flutter Focus用法
## FocusNode
FocusNode是用於Widget獲取鍵盤焦點和處理鍵盤事件的對象。
常用方法:
* requestFocus: 請求焦點,注意這個請求焦點的執行放在了`scheduleMicrotask`中,因此結果可能會**延遲**最多一幀。
```dart
myFocusNode.requestFocus(),
```
* unfocus: 取消焦點
* disposition
* UnfocusDisposition.scope,表示向上尋找最近的FocusScopeNode。
* UnfocusDisposition.previouslyFocusedChild,尋找上一個焦點位置,如果沒有則給當前FocusScopeNode。
```dart
final currentFocus = FocusScope.of(context);
currentFocus.unfocus(disposition: UnfocusDisposition.previouslyFocusedChild);
```
* canRequestFocus: 是否能請求焦點
* hasFocus: 是否有焦點
## FocusScope
常用於希望輸入完成第一個欄位按Enter就可以跳下一個欄位直接輸入,而不用手動點擊下一個欄位再進行。
```dart
class Test extends StatefulWidget {
@override
_TestState createState() => _TestState();
}
class _TestState extends State<Test> {
FocusScopeNode node = FocusScopeNode();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: FocusScope( //創造FocusScope
node: node,
child: SingleChildScrollView(
//實作時記得改成實際輸入框樣式
child: Column(
children: <Widget>[
for (var i = 0; i < 10; i++) buildTextField(),
],
),
),
),
);
}
TextField buildTextField() {
return TextField(
onEditingComplete: () {
if (node.focusedChild == node.children.last) {
//若已是最後一個focusedChild則進行送出
print('submit');
} else {
//自動focus下一個欄位
node.nextFocus();
}
},
);
}
}
```
## 強制移除focus
```dart
body: GestureDetector(
//點擊任一位置皆可觸發(不一定要點在圖案或文字上)
behavior: HitTestBehavior.opaque,
onTap: () {
//點擊畫面任一非輸入匡位置則關閉鍵盤
FocusScope.of(context).requestFocus(FocusNode());
},
child: Container(),
),
```
## 簡單輸入框 DEMO
https://github.com/yenyen0318
| 點擊輸入匡會顯示鍵盤 | 點擊小眼睛會顯示輸入匡 |
| -------- | -------- |
|  | |
## 相關問題
### TextField 移除焦點時只移除了小鍵盤卻未移除TextField上的focus
```dart
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
currentFocus.focusedChild?.unfocus();
}
```
### 參考資料
https://stackoverflow.com/questions/53481261/how-to-unfocus-textfield-that-has-custom-focusnode
## 參考資料
1. https://cloud.tencent.com/developer/article/1858246
2. https://iter01.com/517982.html
###### tags: `flutter`