Slidable Widget Swipe Action Issue on Text Fields in iOS - Flutter

187 Views Asked by At

I'm encountering an issue with the Slidable widget in my Flutter app, specifically related to swipe actions on Text Fields in iOS. The swipe action works fine on Android, but on iOS, it doesn't seem to work properly when I swipe on Text Fields.

When I try to swipe on a Text Field within a Slidable widget in iOS, the swipe action doesn't trigger. It seems that the Text Field is capturing the swipe gesture, and the Slidable action doesn't get invoked.

I've tried wrapping the Slidable widget around a Stack and using GestureDetector to capture swipe gestures, but the issue persists.

Here is the complete code

import 'package:flutter/material.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';

import 'package:get/get.dart';

import 'app/modules/home/controllers/home_controller.dart';
import 'app/routes/app_pages.dart';

void main() {
  runApp(
    GetMaterialApp(
      title: "Application",
      initialRoute: AppPages.INITIAL,
      getPages: AppPages.routes,
    ),
  );
}

class HomeView extends GetView<HomeController> {
  HomeView({Key? key}) : super(key: key);
  final textTheme = ThemeData().textTheme;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SingleChildScrollView(
          child: Column(
            children: [
              GetBuilder<HomeController>(
                builder: (controller) {
                  return ListView.builder(
                    shrinkWrap: true,
                    physics: const NeverScrollableScrollPhysics(),
                    itemCount: 1,
                    itemBuilder: (context, index) {
                      return _buildWorkoutLogEntryCard(
                        context,

                      );
                    },
                  );
                },
              ),
            ],
          )),
    );
  }

  Widget _buildWorkoutLogEntryCard(
      BuildContext context,) {
    bool isSlidableOpen = true; // To control whether the Slidable is open

    return Card(
      elevation: 2,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(10.0),
      ),
      margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0),
      color: Colors.white,
      surfaceTintColor: Colors.white,
      shadowColor: Colors.white,
      child: GestureDetector(
        // GestureDetector to capture swipe gestures
        onHorizontalDragUpdate: (details) {
          if (details.delta.dx > 0) {
            // Swiping right
            isSlidableOpen = true;
            print(true);
          } else if (details.delta.dx < 0) {
            // Swiping left
            isSlidableOpen = false;
            print(false);
          }
          controller.update();
        },
        child: Stack(
          children: [
            if (isSlidableOpen)
              Slidable(
                endActionPane: ActionPane(
                  motion: const StretchMotion(),
                  extentRatio: 0.6,
                  children: [
                    SlidableAction(
                      flex: 1,
                      backgroundColor: Colors.red,
                      onPressed: (context) {
                        // Handle action
                      },
                      icon: Icons.delete,
                    ),
                  ],
                ),
                child:
                Container(), // You can use an empty container as the child
              ),
            ListTile(
              contentPadding: const EdgeInsets.symmetric(horizontal: 10),
              title: Padding(
                padding: const EdgeInsets.symmetric(vertical: 16.0),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.start,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    const SizedBox(width: 5),
                    Expanded(
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.start,
                        children: [
                          Flexible(
                            child: Padding(
                              padding: const EdgeInsets.only(right: 8.0),
                              child: Text(
                                "hello",
                                overflow: TextOverflow.visible,
                                textAlign: TextAlign.left,
                                style: textTheme.headlineMedium!.copyWith(
                                  color: Colors.black,
                                  fontWeight: FontWeight.bold,
                                ),
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),
                    Icon(
                      FontAwesomeIcons.arrowLeft,
                      size: 15,
                    )
                  ],
                ),
              ),
              subtitle: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  _buildWarmUpList(context,true),
                  _buildWarmUpList(context,false),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
  Widget _buildWarmUpList(BuildContext context, bool isWarmUp) {
    return GetBuilder<HomeController>(
      builder: (controller) {
        List<TextEditingController> _weightcontrollers =
        <TextEditingController>[];
        List<TextEditingController> _repcontrollers = <TextEditingController>[];
        return ListView.builder(
          shrinkWrap: true,
          physics: const NeverScrollableScrollPhysics(),
          itemCount: 2,
          itemBuilder: (context, index) {
            _weightcontrollers.add(TextEditingController(
                text: '0'
            ));
            _repcontrollers
                .add(TextEditingController(text: '0'));

            return Slidable(
              startActionPane: null,
              endActionPane: ActionPane(
                motion: const StretchMotion(),
                extentRatio: 0.25,
                children: [
                  SlidableAction(
                    backgroundColor: Colors.red,
                    icon: Icons.delete,
                    onPressed: (context) {
                      // isWarmUp
                      //     ? controller.deleteWarmUpRow(entry, index)
                      //     : controller.deleteSetRow(entry, index);
                    },
                  ),
                ],
              ),
              child: Column(
                children: [
                  ListTile(
                    dense: true,
                    minVerticalPadding: 0,
                    contentPadding: EdgeInsets.zero,
                    leading: Container(
                        padding: const EdgeInsets.all(8.0),
                        width: 35,
                        height: 35,
                        decoration: const BoxDecoration(
                          color: Colors.white,
                          boxShadow: <BoxShadow>[
                            BoxShadow(
                                color: Colors.white,
                                offset: Offset(2, 2),
                                blurRadius: 10.0),
                          ],
                        ),
                        child: isWarmUp
                            ? ColorFiltered(
                            colorFilter: const ColorFilter.mode(
                                Colors.black, BlendMode.srcIn),
                            child: Image.asset(
                              'assets/stretch.png',
                              height: 15,
                              width: 15,
                            ))
                            : Align(
                            alignment: Alignment.center,
                            child: Text(
                              '${index + 1}',
                              style: textTheme.headlineMedium!.copyWith(
                                color: Colors.black,
                                fontWeight: FontWeight.bold,
                              ),
                            ))),
                    title: Container(
                      decoration: const BoxDecoration(
                        color: Colors.white,
                        boxShadow: <BoxShadow>[
                          BoxShadow(
                              color: Colors.white,
                              offset: Offset(2, 2),
                              blurRadius: 10.0),
                        ],
                      ),
                      child: Align(
                        alignment: Alignment.center,
                        child: Row(
                          children: [
                            const SizedBox(width: 30.0),
                            Expanded(
                              child: Row(
                                mainAxisAlignment: MainAxisAlignment.end,
                                crossAxisAlignment: CrossAxisAlignment.center,
                                children: [
                                  SizedBox(
                                    width: 60,
                                    child: TextFormField(
                                      decoration: const InputDecoration(
                                          isDense: true, suffixText: 'kg'),
                                      controller: _weightcontrollers[index],
                                      keyboardType: TextInputType.number,
                                      textAlign: TextAlign.end,
                                      onTap: () {
                                        _weightcontrollers[index].selection =
                                            TextSelection(
                                                baseOffset: 0,
                                                extentOffset:
                                                _weightcontrollers[index]
                                                    .value
                                                    .text
                                                    .length);
                                      },
                                      onChanged: (value) {
                                        // controller.updateWeight(
                                        //     row, double.tryParse(value) ?? 0);
                                      },
                                    ),
                                  ),
                                ],
                              ),
                            ),
                            const SizedBox(width: 30.0),
                            Expanded(
                              child: Row(
                                mainAxisAlignment: MainAxisAlignment.end,
                                crossAxisAlignment: CrossAxisAlignment.center,
                                children: [
                                  SizedBox(
                                    width: 50,
                                    child: TextFormField(
                                      decoration: InputDecoration(
                                        suffixText:
                                        'reps',
                                      ),
                                      controller: _repcontrollers[index],
                                      onTap: () {
                                        _repcontrollers[index].selection =
                                            TextSelection(
                                                baseOffset: 0,
                                                extentOffset:
                                                _repcontrollers[index]
                                                    .value
                                                    .text
                                                    .length);
                                      },
                                      keyboardType: TextInputType.number,
                                      textAlign: TextAlign.right,
                                      onChanged: (value) {
                                        // controller.updateReps(
                                        //     row, int.tryParse(value) ?? 0);
                                      },
                                    ),
                                  ),
                                ],
                              ),
                            ),
                            const SizedBox(width: 30.0),
                          ],
                        ),
                      ),
                    ),
                  ),
                  const Divider(
                    color: Colors.grey,
                    height: 1.0,
                    thickness: 0.25,
                  ),
                ],
              ),
            );
          },
        );
      },
    );
  }
}

How can I make sure that the swipe action works on the entire Slidable widget, even if the user swipes on a Text Field?

0

There are 0 best solutions below