美文网首页
Flutter_ListView左滑出现删除按钮

Flutter_ListView左滑出现删除按钮

作者: JxSr程知农 | 来源:发表于2022-05-25 13:29 被阅读0次

    Flutter的ListView左滑出现删除按钮。

    如同iOS原生ListView的删除风格,列表项左滑,右侧出现删除按钮。这里用了2个dart文件,实现这个功能。

    (1) left_slide_actions.dart文件。

    import 'package:flutter/material.dart';
    
    typedef _BaseFunction<T> = void Function(T o);
    
    /// 来源: https://blog.csdn.net/zhuowalun8427/article/details/121285947 。
    class LeftSlideActions extends StatefulWidget {
      final double actionsWidth;
      final List<Widget> actions;
      final Widget child;
      final Decoration? decoration;
      final VoidCallback? actionsWillShow;
      final _BaseFunction<VoidCallback>? exportHideActions;
    
      const LeftSlideActions({
        Key? key,
        required this.actionsWidth,
        required this.actions,
        required this.child,
        this.decoration,
        this.actionsWillShow,
        this.exportHideActions,
      }) : super(key: key);
    
      @override
      _LeftSlideActionsState createState() => _LeftSlideActionsState();
    }
    
    class _LeftSlideActionsState extends State<LeftSlideActions>
        with TickerProviderStateMixin {
      double _translateX = 0;
      late AnimationController _controller;
    
      @override
      void dispose() {
        _controller.dispose();
        super.dispose();
      }
    
      @override
      void initState() {
        super.initState();
        _controller = AnimationController(
          lowerBound: -widget.actionsWidth,
          upperBound: 0,
          vsync: this,
          duration: const Duration(milliseconds: 300),
        )..addListener(() {
          _translateX = _controller.value;
            setState(() {});
          });
        if (widget.exportHideActions != null) {
          widget.exportHideActions!(_hide);
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return Container(
          decoration: widget.decoration,
          clipBehavior: Clip.hardEdge,
          child: Stack(
            children: [
              Positioned.fill(
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.end,
                  children: widget.actions,
                ),
              ),
              GestureDetector(
                onHorizontalDragUpdate: (v) {
                  _onHorizontalDragUpdate(v);
                },
                onHorizontalDragEnd: (v) {
                  _onHorizontalDragEnd(v);
                },
                child: Transform.translate(
                  offset: Offset(_translateX, 0),
                  child: Row(
                    children: [
                      Expanded(flex: 1, child: widget.child),
                    ],
                  ),
                ),
              ),
            ],
          ),
        );
      }
    
      void _onHorizontalDragUpdate(DragUpdateDetails details) {
        _translateX =
            (_translateX + details.delta.dx).clamp(-widget.actionsWidth, 0.0);
        setState(() {});
      }
    
      void _onHorizontalDragEnd(DragEndDetails details) {
        _controller.value = _translateX;
        if (details.velocity.pixelsPerSecond.dx > 200) {
          _hide();
        } else if (details.velocity.pixelsPerSecond.dx < -200) {
          _show();
        } else {
          if (_translateX.abs() > widget.actionsWidth / 2) {
            _show();
          } else {
            _hide();
          }
        }
      }
    
      void _show() {
        if (widget.actionsWillShow != null) {
          widget.actionsWillShow!();
        }
        if (_translateX != -widget.actionsWidth) {
          _controller.animateTo(-widget.actionsWidth);
        }
      }
    
      void _hide() {
        if (_translateX != 0) {
          _controller.animateTo(0);
        }
      }
    }
    

    (2)main.dart文件。

    import 'package:flutter/material.dart';
    import 'left_slide_actions.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return const MaterialApp(
          home: HomePage(),
        );
      }
    }
    
    class HomePage extends StatefulWidget {
      const HomePage({Key? key}) : super(key: key);
    
      @override
      _HomePageState createState() => _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> {
      static const int _itemNum = 20;
      final List<String> _itemTextList = [];
      final Map<String, VoidCallback> _mapForHideActions = {};
    
      @override
      void initState() {
        super.initState();
        for (int i = 1; i <= _itemNum; i++) {
          _itemTextList.add(i.toString());
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('ListView左滑出现删除按钮'),
            //backgroundColor: Colors.pink,
          ),
          body: SafeArea(
            child: ListView.separated(
              scrollDirection: Axis.vertical,
              padding: const EdgeInsets.fromLTRB(12, 20, 12, 30),
              itemCount: _itemTextList.length,
              itemBuilder: (BuildContext context, int index) {
                if (index < _itemTextList.length) {
                  final String tempStr = _itemTextList[index];
                  return LeftSlideActions(
                    key: Key(tempStr),
                    actionsWidth: 60,
                    actions: [
                      _buildDeleteBtn(index),
                    ],
                    child: _buildListItem(index),
                    decoration: const BoxDecoration(
                      borderRadius: BorderRadius.all(Radius.circular(5)),
                    ),
                    actionsWillShow: () {
                      // 隐藏其他列表项的行为。
                      for (int i = 0; i < _itemTextList.length; i++) {
                        if (index == i) {
                          continue;
                        }
                        String tempKey = _itemTextList[i];
                        VoidCallback? hideActions = _mapForHideActions[tempKey];
                        if (hideActions != null) {
                          hideActions();
                        }
                      }
                    },
                    exportHideActions: (hideActions) {
                      _mapForHideActions[tempStr] = hideActions;
                    },
                  );
                }
                return const SizedBox.shrink();
              },
              separatorBuilder: (BuildContext context, int index) {
                return const SizedBox(height: 10);
              },
              // 添加下面这句 内容未充满的时候也可以滚动。
              physics: const AlwaysScrollableScrollPhysics(),
              // 添加下面这句 是为了GridView的高度自适应, 否则GridView需要包裹在固定宽高的容器中。
              //shrinkWrap: true,
            ),
          ),
        );
      }
    
      Widget _buildListItem(final int index) {
        return Container(
          height: 50,
          padding: const EdgeInsets.symmetric(horizontal: 10),
          alignment: Alignment.centerLeft,
          decoration: const BoxDecoration(
            color: Color(0xFFEEEEEE),
            boxShadow: [
              BoxShadow(
                // 阴影颜色。
                color: Color(0x66EBEBEB),
                // 阴影xy轴偏移量。
                offset: Offset(0.0, 0.0),
                // 阴影模糊程度。
                blurRadius: 6.0,
                // 阴影扩散程度。
                spreadRadius: 4.0,
              ),
            ],
          ),
          child: Text(
            ('行内容---' + _itemTextList[index]),
            style: const TextStyle(
              fontSize: 15,
              fontWeight: FontWeight.w500,
              color: Color(0xFF333333),
              height: 1,
            ),
          ),
        );
      }
    
      Widget _buildDeleteBtn(final int index) {
        return GestureDetector(
          onTap: () {
            // 省略: 弹出是否删除的确认对话框。
            setState(() {
              _itemTextList.removeAt(index);
            });
          },
          child: Container(
            width: 60,
            color: const Color(0xFFF20101),
            alignment: Alignment.center,
            child: const Text(
              '删除',
              style: TextStyle(
                fontSize: 16,
                fontWeight: FontWeight.w500,
                color: Colors.white,
                height: 1,
              ),
            ),
          ),
        );
      }
    }
    

    相关文章

      网友评论

          本文标题:Flutter_ListView左滑出现删除按钮

          本文链接:https://www.haomeiwen.com/subject/txmeprtx.html