FocusNode does not trigger when first time add to the widget with if statement

110 views Asked by At

I have some logic to check if statement and show the TextField widget as below:

             Flexible(
             fit: FlexFit.loose,
               child: ListView.builder(
                  shrinkWrap: true,
                     itemCount: _controller.selectedAllocationCategories.length,
                                                      
                     itemBuilder: (context, index) {
                       return Obx(() => _selectedCategoryItem(  _controller.selectedAllocationCategories[index],index,context));
                                                                              
            }),
            );
        Widget _selectedCategoryItem(
              SavingAllocationCategory category, int index, context) {
            final bool isSelected = index == _controller.selectedCategoryIndex;
            return GestureDetector(
              onTap: () {
                FocusScope.of(context).unfocus();
                 _controller.onTapAllocationCateogry(index);
                if (isSelected) {
                  WidgetsBinding.instance.addPostFrameCallback((_) {
                    Future.delayed(const Duration(milliseconds: 200), () {
                      _controller.focusNode.requestFocus();
                    });
                  });
                }
              },
              child: Container(
                padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 12),
            margin: const EdgeInsets.only(bottom: 16),
            height: 60,
            decoration: BoxDecoration(
                color: AppColors.boxColor, borderRadius: BorderRadius.circular(8)),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Text(
                  category.name,
                  style: const TextStyle(fontSize: 18),
                ),
                isSelected
                    ? Container(
                        width: 130,
                        // height: 30,
                        decoration: BoxDecoration(
                            color: AppColors.inputColor,
                            borderRadius: BorderRadius.circular(8)),
                        child: TextField(
                          controller: _controller.savingTextController,
                          textDirection: TextDirection.rtl,
                          focusNode: _controller.focusNode,
                          keyboardType:
                              const TextInputType.numberWithOptions(decimal: true),
                          decoration: const InputDecoration(
                            contentPadding:
                                EdgeInsets.symmetric(horizontal: 8, vertical: 8),
                            hintTextDirection: TextDirection.rtl,
                            border: InputBorder.none,
                          ),
                        ),
                      )
                    : Container(
                        width: 130,
                        // height: 30,
                        padding: const EdgeInsets.symmetric(horizontal: 5),
                        alignment: Alignment.centerRight,
                        decoration: BoxDecoration(
                            color: AppColors.inputColor,
                            borderRadius: BorderRadius.circular(8)),
                        child: Text(
                          formatCurrency(category.allocatedAmount),
                          style: const TextStyle(fontSize: 18),
                        ),
                      ),
              ],
            ),
          ),
        );
      }

but when i click one the GestureDetector to trigger focusnode but it seems not work. I suspect that maybe at the time focusnode request calling, TextField is not added to widget tree then it does not trigger focus on the textfield. But I don't know how to fix it.

I have already using WidgetsBinding.instance.addPostFrameCallback to make sure of calling focusrequest only after widget is binding but it does not work.

WidgetsBinding.instance.addPostFrameCallback((\_) {
Future.delayed(const Duration(milliseconds: 200), () {
_controller.focusNode.requestFocus();
});

What i expect is that when i click on the GestureDetector it will automatically trigger Focus request and pull up the virtual keyboard.

1

There are 1 answers

2
Ashikul Islam Sawan On

Use the Focus widget provided by Flutter. Try these examples. It can be work

Focus(
  autofocus: isSelected,
  child: TextField(
    // TextField properties
  ),
)

If that will not work, try this one.

FocusTraversalOrder(
  order: NumericFocusOrder(1), // Set an appropriate order
  child: TextField(
    // TextField properties
  ),
)

Last one...

final textFieldKey = GlobalKey();

// ...

if (isSelected) {
  WidgetsBinding.instance.addPostFrameCallback((_) {
    Future.delayed(const Duration(milliseconds: 200), () {
      FocusScope.of(context).requestFocus(textFieldKey.currentContext!.findRenderObject() as RenderBox);
    });
  });
}

// ...

TextField(
  key: textFieldKey,
  // other properties
)