패키지, 저장소 및 앱 카테고리 검색

flutter_swipe_action_cell 표지
패키지 상세v3.1.9

flutter_swipe_action_cell

iOS 스타일의 셀 스와이프 액션 효과를 포함한 멋진 UI 패키지입니다. 이 패키지를 사용하여 iOS 스타일의 tableView 셀 스와이프 액션을 구현할 수 있습니다

AndroidiOSWebmacOSWindowsLinux
30일 다운로드
3.1만
좋아요
464
Pub 점수
150

패키지 설치

flutter pub add flutter_swipe_action_cell

패키지 개요

공개 정보를 바탕으로 생성한 선택 가이드입니다.

flutter_swipe_action_cell은 리스트 항목에서 iOS 스타일의 스와이프 액션을 가능하게 하는 Flutter 패키지로, 네이티브 iOS 테이블 뷰에서 발견되는 상호작용 행동을 모방합니다. 사용자는 리스트 셀을 수평으로 스와이프함으로써 액션 버튼을 표시할 수 있으며, 직관적인 제스처를 통해 사용자 인터랙션을 향상시킵니다. 이 패키지는 Android, iOS, 웹, macOS, Windows, Linux 등 여러 플랫폼을 지원하여 일관되고 완성도 높은 UI 경험을 원하는 크로스플랫폼 앱에 이상적입니다. 개발자는 앱의 디자인 언어에 맞게 스와이프 액션의 외관과 동작을 커스터마이징할 수 있습니다.

사용 사례

  • 리스트에서 iOS 스타일의 스와이프 삭제 또는 스와이프 액션 구현하기
  • 컨텍스트 작업이 있는 상호작용식 목록 항목 만들기
  • 작업 관리 또는 메시징 앱에서 사용자 경험 향상
  • 반응형이고 제스처 기반의 인터페이스 구축
  • 채팅 또는 알림 목록에 스와이프 효과 추가
  • 현대적이고 네이티브 스타일의 모바일 UI 설계

주요 기능

  • iOS 스타일의 수평 스와이프 작업
  • 사용자 정의 가능한 액션 버튼 및 색상
  • 다양한 스와이프 방향 지원
  • 크로스 플랫폼 호환성
  • ListView 및 기타 리스트 위젯과의 간편한 통합
  • 사용자 정의 가능한 애니메이션 및 타이밍

적합한 대상

  • iOS 스타일의 Flutter 앱을 개발하는 개발자
  • 네이티브 사용자 경험 패턴을 우선시하는 팀
  • 인터랙티브한 목록 항목 동작을 요구하는 앱
  • 사용자 인터페이스 중심의 프로젝트, 제스처 기반 상호작용 포함
  • 여러 운영 체제를 대상으로 하는 크로스 플랫폼 개발자

고려 사항

  • 비-iOS 플랫폼에 대한 추가 스타일링이 필요할 수 있습니다
  • 대규모 목록의 성능 영향
  • 제한된 내장 접근성 기능
  • 복잡한 작업 워크플로우를 위한 사용자 정의 로직 필요
  • 수직 스와이프 제스처에 최적화되지 않음
  • 중첩 스크롤 컨텍스트에서 터치 이벤트를 신중하게 처리해야 합니다

원본 README

연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.

Language:

English | 中文简体

flutter_swipe_action_cell

A package that can give you a cell that can be swiped, effect is like iOS native

If you like this package, you can give me a star😀. The more stars this project has, the more time I will speant in the project😀
Donate:
Alipay Wechat

Get started

3.0.0 and later version is for flutter 3
pub home page click here: pub
install:
flutter_swipe_action_cell: ^3.1.9

1.Preview:

Simple delete Perform first action when full swipe
Delete with animation More than one action
Effect like WeChat(confirm delete) Automatically adjust the button width
Effect like WeChat collection Page: Customize your button shape
With leading Action and trailing action
Edit mode

Full example:

Preview (YouTobe video)

And you can find full example code in example page

Examples

  • Example 1: Simple delete the item in ListView

  • Tip: put the code in the itemBuilder of your ListView
 SwipeActionCell(
      key: ObjectKey(list[index]), /// this key is necessary
      trailingActions: <SwipeAction>[
        SwipeAction(
            title: "delete",
            onTap: (CompletionHandler handler) async {
              list.removeAt(index);
              setState(() {});
            },
            color: Colors.red),
      ],
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Text("this is index of ${list[index]}",
            style: TextStyle(fontSize: 40)),
      ),
    );
  • Example 2: Perform first action when full swipe

SwipeActionCell(
      /// this key is necessary
      key: ObjectKey(list[index]),
      trailingActions: <SwipeAction>[
        SwipeAction(
            /// this is the same as iOS native
            performsFirstActionWithFullSwipe: true,
            title: "delete",
            onTap: (CompletionHandler handler) async {
              list.removeAt(index);
              setState(() {});
            },
            color: Colors.red),
      ],
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Text("this is index of ${list[index]}",
            style: TextStyle(fontSize: 40)),
      ),
    );
  • Example 3: Delete with animation

SwipeActionCell(
     key: ObjectKey(list[index]),
     trailingActions: <SwipeAction>[
       SwipeAction(
           title: "delete",
           onTap: (CompletionHandler handler) async {
             
             /// await handler(true) : will delete this row
             /// And after delete animation,setState will called to 
             /// sync your data source with your UI

             await handler(true);
             list.removeAt(index);
             setState(() {});
           },
           color: Colors.red),
     ],
     child: Padding(
       padding: const EdgeInsets.all(8.0),
       child: Text("this is index of ${list[index]}",
           style: TextStyle(fontSize: 40)),
     ),
   );
  • Example 4: More than one action:

SwipeActionCell(
     key: ObjectKey(list[index]),
     trailingActions: <SwipeAction>[
       SwipeAction(
           title: "delete",
           onTap: (CompletionHandler handler) async {
             await handler(true);
             list.removeAt(index);
             setState(() {});
           },
           color: Colors.red),

       SwipeAction(
           widthSpace: 120,
           title: "popAlert",
           onTap: (CompletionHandler handler) async {
             /// false means that you just do nothing,it will close
             /// action buttons by default
             handler(false);
             showCupertinoDialog(
                 context: context,
                 builder: (c) {
                   return CupertinoAlertDialog(
                     title: Text('ok'),
                     actions: <Widget>[
                       CupertinoDialogAction(
                         child: Text('confirm'),
                         isDestructiveAction: true,
                         onPressed: () {
                           Navigator.pop(context);
                         },
                       ),
                     ],
                   );
                 });
           },
           color: Colors.orange),
     ],
     child: Padding(
       padding: const EdgeInsets.all(8.0),
       child: Text(
           "this is index of ${list[index]}",
           style: TextStyle(fontSize: 40)),
     ),
   );
  • Example 5:Delete like WeChat message page(need to confirm it:

return SwipeActionCell(
      key: ValueKey(list[index]),
      trailingActions: <SwipeAction>[
        SwipeAction(
          ///
          /// This attr should be passed to first action
          ///
          nestedAction: SwipeNestedAction(title: "确认删除"),
          title: "删除",
          onTap: (CompletionHandler handler) async {
            await handler(true);
            list.removeAt(index);
            setState(() {});
          },
          color: Colors.red,
        ),
        SwipeAction(
            title: "置顶",
            onTap: (CompletionHandler handler) async {
              /// false means that you just do nothing,it will close
              /// action buttons by default
              handler(false);
            },
            color: Colors.grey),
      ],
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Text("this is index of ${list[index]}",
            style: TextStyle(fontSize: 40)),
      ),
    );
  • Example 6:Edit mode(just like iOS native effect)

/// To controller edit mode
SwipeActionEditController controller;

/// 在initState
@override
  void initState() {
    super.initState();
    controller = SwipeActionController();
  }
/// To get the selected rows index
List<int> selectedIndexes = controller.getSelectedIndexes();


/// open cell
controller.openCellAt(index: 2, trailing: true, animated: true);

/// close cell
controller.closeAllOpenCell();

/// whether any cell is currently open (e.g. to let a back gesture close it first)
bool hasOpen = controller.hasAnyOpenCell;

/// toggleEditingMode
controller.toggleEditingMode()

/// startEditMode
controller.startEditingMode()

/// stopEditMode
controller.stopEditingMode()

/// select cell
controller.selectCellAt(indexPaths:[1,2,3])

controller.deselectCellAt(indexPaths:[1,2,3])

/// pass your data length to selectedAll
controller.selectAll(30
)

/// deselect all cell
controller deselectAll()

ListView.builder(
        itemBuilder: (c, index) {
          return _item(index);
        },
        itemCount: list.length,
      );


 Widget _item(int index) {
     return SwipeActionCell(
       /// controller
       controller: controller,
       /// index is required if you want to enter edit mode
       index: index,
       key: ValueKey(list[index]),
       trailingActions: [
         SwipeAction(
             /// this is the same as iOS native
             performsFirstActionWithFullSwipe: true,
             onTap: (handler) async {
               await handler(true);
               list.removeAt(index);
               setState(() {});
             },
             title: "delete"),
       ],
       child: Padding(
         padding: const EdgeInsets.all(15.0),
         child: Text("This is index of ${list[index]}",
             style: TextStyle(fontSize: 35)),
       ),
     );
   }

  • Example 7:customize shape


Widget _item(int index) {
    return SwipeActionCell(
      key: ValueKey(list[index]),
      trailingActions: [
        SwipeAction(
            nestedAction: SwipeNestedAction(
              /// customize your nested action content
              content: Container(
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(30),
                  color: Colors.red,
                ),
                width: 130,
                height: 60,
                child: OverflowBox(
                  maxWidth: double.infinity,
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Icon(
                        Icons.delete,
                        color: Colors.white,
                      ),
                      Text('确认删除',
                          style: TextStyle(color: Colors.white, fontSize: 20)),
                    ],
                  ),
                ),
              ),
            ),

            /// you should set the default  bg color to transparent
            color: Colors.transparent,

            /// set content instead of title of icon
            content: _getIconButton(Colors.red, Icons.delete),
            onTap: (handler) async {
              list.removeAt(index);
              setState(() {});
            }),
        SwipeAction(
            content: _getIconButton(Colors.grey, Icons.vertical_align_top),
            color: Colors.transparent,
            onTap: (handler) {}),
      ],
      child: Padding(
        padding: const EdgeInsets.all(15.0),
        child: Text(
            "This is index of ${list[index]},Awesome Swipe Action Cell!! I like it very much!",
            style: TextStyle(fontSize: 25)),
      ),
    );
  }

  Widget _getIconButton(color, icon) {
    return Container(
      width: 50,
      height: 50,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(25),

        /// set you real bg color in your content
        color: color,
      ),
      child: Icon(
        icon,
        color: Colors.white,
      ),
    );
  }

  • Example 8:Close opening cell when navigator change its routes.

Add a SwipeActionNavigatorObserver in MaterialApp's navigatorObservers

return MaterialApp(
  navigatorObservers: [SwipeActionNavigatorObserver()],
  ....
);

About CompletionHandler in onTap function of SwipeAction

it means how you want control this cell after you tap it. If you don't want any animation, just don't call it and update your data and UI with setState()

If you want some animation:

  • handler(true) : Means this row will be deleted(You should call setState after it)

  • await handler(true) : Means that you will await the animation to complete(you should call setState after it so that you will get an animation)

  • handler(false) : means it will not delete this row.By default, it just close this cell's action buttons.

  • await handler(false) : means it will wait the close animation to complete.

About all parameter:

I wrote them in my code with dart doc comments. You can read them in source code.

카테고리

소스 저장소

이 패키지를 사용하는 프로젝트