flutter widget组件之-----------交互模型组件

flutter widget组件之-----------交互模型组件

widget分为两类:widgets library中的标准widget和Material Components library中的专用widget;任何应用程序都可以使用widgets library中的widget,但只有Material应用程序可以使用Material Components库。其中Card,ListTitle就是Material Components库中的组件。

LongPressDraggable

可以使其子widget在长按时可拖动

  • 构造函数
LongPressDraggable({
    Key key,
    @required Widget child,// 被长按的对象组件
    @required Widget feedback,// 鼠标拖动时,显示的组件
    T data,
    Axis axis,
    Widget childWhenDragging,//拖动时的子项对象
    Offset feedbackOffset = Offset.zero,
    DragAnchor dragAnchor = DragAnchor.child,
    int maxSimultaneousDrags,
    VoidCallback onDragStarted,// 拖动开始回调
    DraggableCanceledCallback onDraggableCanceled,// 拖动取消回调
    DragEndCallback onDragEnd,// 拖动结束回调
    VoidCallback onDragCompleted,// 拖动完成时的回调
    this.hapticFeedbackOnStart = true,
    bool ignoringFeedbackSemantics = true,
  })

  • 应用示例
class MyStatePageState extends State<MyStatePage>{

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("longpressdragable"),),
      body: Center(
        child: LongPressDraggable(
          child: RaisedButton(child: Text("press"),),
          // 鼠标拖动时,所移动的组件对象
          feedback: Container(child: Text("feedback"),),
          onDragStarted: (){
            print("ondragstarted.....................");

          },
          onDraggableCanceled: (a,d){
            print("$a,,,,,,,,,,,,,,,,,,,,,,,,,,,,$d,,,,,,ondraggablecanceled");
          },
          onDragCompleted: (){
            print("ondragcompleted.............");
          },
          onDragEnd: (e){
            print("$e................ondragend");
          },
          data: Text("data..."),//没看到啥变化
          // 拖动时  替换原child组件
          childWhenDragging: Text("childwhenDragging"),
        ),
      ),
    );
  }

}

GestureDetector

一个检测手势的widget

  • 构造函数
GestureDetector({
    Key key,
    this.child,//子组件
    this.onTapDown,// 单击接触
    this.onTapUp,// 单击离开
    this.onTap,// 单击触发
    this.onTapCancel,//触发的onTapDown指针不会再触发单击事件
    this.onDoubleTap,//双击触发
    this.onLongPress,// 长按
    this.onLongPressUp,// 长按离开
    this.onVerticalDragDown,// 接触并可能开始垂直移动
    this.onVerticalDragStart,// 接触并开始垂直移动
    this.onVerticalDragUpdate,//接触并垂直移动
    this.onVerticalDragEnd,//接触并垂直移动结束
    this.onVerticalDragCancel,//先前触发onVerticalDragDown的指针未完成触发了取消。
    this.onHorizontalDragDown,
    this.onHorizontalDragStart,
    this.onHorizontalDragUpdate,
    this.onHorizontalDragEnd,
    this.onHorizontalDragCancel,
    this.onPanDown,//指针已通过主按钮与屏幕接触,并可能开始移动
    this.onPanStart,//触摸点与屏幕接触,并已开始移动
    this.onPanUpdate,// 屏幕上的触摸点位置每次改变时,都会触发该回调
    this.onPanEnd,//先前通过主按钮与屏幕接触并且移动的指针不再与屏幕接触,并且当它停止接触屏幕时以特定速度移动
    this.onPanCancel,//先前触发onPanDown的指针未完成
    this.onScaleStart,//与屏幕接触的指针已建立焦点,初始比例为1.0
    this.onScaleUpdate,// 与屏幕接触的指针表示新的焦点和/或比例
    this.onScaleEnd,// 指针不再与屏幕接触
    this.behavior,
    this.excludeFromSemantics = false
  }) 


  • 应用示例
class MyStatePageState extends State<MyStatePage> {

  var _scaffoldKey = new GlobalKey<ScaffoldState>();

  String _operation = "No Gesture detected!"; 


    //更新文本
  void updateText(String text) {
    setState(() {
      _operation = text;
    });
    //提示
    showSnackBar(text);
  }

  // 底部弹层显示信息
  void showSnackBar(String message) {
    var snackBar = SnackBar(
        content: Text(message),
        backgroundColor: Colors.lightGreen,
        duration: Duration(milliseconds: 400));
    _scaffoldKey.currentState.showSnackBar(snackBar);
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      appBar: AppBar(
        title: Text("GestureDetectorTest"),
      ),
      body: Center(
        child: GestureDetector(
          child: Container(
            alignment: Alignment.center,
            color: Colors.blue,
            width: 200.0,
            height: 200.0,
            child: Text(
              _operation,
              style: TextStyle(
                  color: Colors.white,
                  fontSize: 14,
                  decoration: TextDecoration.none),
            ),
          ),
          onTap: () => updateText("onTap"), //单击
          onDoubleTap: () => updateText("onDoubleTap"), //双击
          onLongPress: () => updateText("onLongPress"), //长按
          // onTapDown: (e){
          //   print("tapdown....................");
          // },
          // onVerticalDragDown: (e){
          //   print("VerticalDragDown....................");
          // },
          // onPanDown: (e){
          //    print("pandown....................");
          // },
        ),
      ),
    );
  }

}


DragTarget

一个拖动的目标widget,在完成拖动时它可以接收数据

  • 构造函数
Draggable({
    Key key,
    @required this.child,// 子项widget
    @required this.feedback,//正在拖动时,显示的widget
    this.data,//要传递的数据
    this.axis,//控制widget在拖动时,只能横向
    this.childWhenDragging,//拖动的时候,在原始位置展示的widget
    this.feedbackOffset = Offset.zero,
    this.dragAnchor = DragAnchor.child,
    this.affinity,
    this.maxSimultaneousDrags,
    this.onDragStarted,///开始拖拽
    this.onDraggableCanceled,//没有拖拽到DragTarget或拖拽没有完成的回调
    this.onDragEnd,///结束拖拽
    this.onDragCompleted, ///拖拽到DragTarget且接受的时候回调
    this.ignoringFeedbackSemantics = true,
})
DragTarget({
    Key key,
    @required this.builder,// target的创建者
    this.onWillAccept,//预判是否会接受这个Draggable
    this.onAccept,//接受Draggable的回调
    this.onLeave,//Draggable拖拽到上但是没有松开,直接离开的回调
})


  • 应用示例
class _DraggableWidgetPageState extends State<DraggableWidgetPage> {

  GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: scaffoldKey,
      appBar: AppBar(),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: <Widget>[
            Draggable(
              data: 4,
              ///控制widget在拖动时,
              //axis: Axis.horizontal,
              ///停止的时候,显示的widget
              child: Container(
                width: 50,
                height: 50,
                color: Colors.green,
                child: Center(
                  child: Text(
                    "4",
                    style: TextStyle(fontSize: 20),
                  ),
                ),
              ),

              ///正在拖动时,显示的widget
              feedback: Container(
                width: 50,
                height: 50,
                color: Colors.green,
                child: Center(
                  child: Text(
                    "4",
                    style: TextStyle(fontSize: 20),
                  ),
                ),
              ),
              ///拖动的时候,在原始位置展示的widget
              childWhenDragging: Container(
                width: 50,
                height: 50,
                child: Text("childWhenDragging"),
                color: Colors.grey,
              ),
              ///开始拖拽
              onDragStarted: () {
                print("----onDragStarted,开始拖拽");
              },
              ///拖拽到DragTarget且接受的时候回调
              onDragCompleted: () {
                print("----onDragCompleted,拖拽完成");
              },
              ///没有拖拽到DragTarget或拖拽没有完成的回调
              onDraggableCanceled: (v, offset) {
                print("----onDraggableCanceled,拖拽取消");
              },
            ),
            Container(
              width: 100,
              height: 100,
              color: Colors.orange,
              child: DragTarget(
                builder: (context, List<int> candidateData,List<dynamic> rejectedData) {
                  ///candidateData,当Draggable被拖到DragTarget上的时候的data,已经准备好接受
                  print("----candidateData" + candidateData.toString());

                  ///rejectData,当Draggable被拖到DragTarget上的时候,不被接受
                  print("----rejectedData" + rejectedData.toString());

                  ///这两个数据都是正拖到上面的时候,还没放到上面,还没松手
                  return Center(
                    child: Text(candidateData.toString() +
                        "----" +
                        rejectedData.toString()),
                  );
                },
                ///接收Draggable的data数据,判断是否接收
                onWillAccept: (data) {
                  print("----onWillAccept,拖拽" + data.toString() + "到target");
                  if (data == 4) {
                    return true;
                  } else {
                    return false;
                  }
                },
                ///当拖到DragTarget的时候,松手后
                onAccept: (data) {
                  print("----onAccept,接收" + data.toString());
                  scaffoldKey.currentState
                      .showSnackBar(SnackBar(content: Text(data.toString())));
                },
                ///拖到上面,没有松手,又离开
                onLeave: (data) {
                  print("----onLeave,离开" + data.toString());
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}


Dismissible

可以在拖动时隐藏的widget

  • 构造函数
Dismissible({
    @required Key key,
    @required this.child,// 子项
    this.background,//向右滑动背景色
    this.secondaryBackground,///向左滑动背景色
    this.onResize,//widget大小改变时的回调
    this.onDismissed,//大小改变完成后,widget隐藏时的回调
    this.direction = DismissDirection.horizontal,//隐藏widget的方向
    this.resizeDuration = const Duration(milliseconds: 300),
    this.dismissThresholds = const <DismissDirection, double>{},
    this.movementDuration = const Duration(milliseconds: 200),
    this.crossAxisEndOffset = 0.0,
  })

  • 应用示例
class _DraggableWidgetPageState extends State<DraggableWidgetPage> {

  GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: scaffoldKey,
      appBar: AppBar(),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: <Widget>[
            Dismissible(
              key:ValueKey("myString"),
              child:ListTile(
                title:Text("dismissble"),
              ),
              // 向右滑动背景色
              background:Container(
                color:Colors.green,
              ),
              // 向左滑动背景色
              secondaryBackground: Container(
                color:Colors.red,
              ),
              onResize: (){
                print("onresize.............");
              },
              onDismissed: (e){
                 print("onDismissed.............$e");
              },
              

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


Navigator

导航器,可以在多个页面(路由)栈之间跳转

  • 构造函数
Navigator({
    Key key,
    this.initialRoute,//初始路由
    @required this.onGenerateRoute,//路由生成器,
    this.onUnknownRoute,//OnGenerateRoute 无法生成路由时调用。
    this.observers = const <NavigatorObserver>[] // 此导航器的观察着列表
})

  • 应用示例
import 'package:flutter/material.dart';
// import 'package:test_flutter/customPaintView/chess_vectors_flutter.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.green,
        primaryColor: Colors.pink
      ),
      initialRoute: '/',
       home: MyHomePage(),
      routes: {
        '/lgx': (BuildContext context) => HomePage(),
        '/signup': (BuildContext context) => SignUpPage(),
      },
    );
  }
}
// 主页面
class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child:Column(
        children: <Widget>[
          RaisedButton(
            color: Colors.red,
            onPressed: (){
                Navigator.pushNamed(context, "/lgx");
            },
            child: Text("lgx"),
          ),
           RaisedButton(
            color: Colors.green,
            onPressed: (){
                Navigator.pushNamed(context, "/signup");
            },
            child: Text("signup"),
          ),

        ],
      ),
    );
  }
}

// 路由lgx指向的页面
class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("lgx"),
        leading:IconButton(
           icon: const Icon(Icons.arrow_back),
           onPressed: () {Navigator.pop(context);},
         ),
      ),
      body:  DefaultTextStyle(
        style: Theme.of(context).textTheme.display1,
        child: Container(
          color: Colors.white,
          alignment: Alignment.center,
          child: Text('lgx'),
        ),
      ),
    );
  }
}

class CollectPersonalInfoPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DefaultTextStyle(
      style: Theme.of(context).textTheme.display1,
      child: GestureDetector(
        onTap: () {
          // This moves from the personal info page to the credentials page,
          // replacing this page with that one.
          Navigator.of(context)
              .pushReplacementNamed('signup/choose_credentials');
        },
        child: Container(
          color: Colors.lightBlue,
          alignment: Alignment.center,
          child: Text('Collect Personal Info Page'),
        ),
      ),
    );
  }
}

class ChooseCredentialsPage extends StatelessWidget {
  const ChooseCredentialsPage({
    this.onSignupComplete,
  });

  final VoidCallback onSignupComplete;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onSignupComplete,
      child: DefaultTextStyle(
        style: Theme.of(context).textTheme.display1,
        child: Container(
          color: Colors.pinkAccent,
          alignment: Alignment.center,
          child: Text('Choose Credentials Page'),
        ),
      ),
    );
  }
}

// 路由signup指向的页面
class SignUpPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // SignUpPage builds its own Navigator which ends up being a nested
    // Navigator in our app.
    return Scaffold(
      appBar: AppBar(
        title: Text("sinup"),
        leading:IconButton(
           icon: const Icon(Icons.arrow_back),
           onPressed: () {Navigator.pop(context);},
         ),
      ),
      body: Navigator(
        initialRoute: 'signup/personal_info',
        onGenerateRoute: (RouteSettings settings) {
          WidgetBuilder builder;
          switch (settings.name) {
            case 'signup/personal_info':
              // Assume CollectPersonalInfoPage collects personal info and then
              // navigates to 'signup/choose_credentials'.
              builder = (BuildContext _) => CollectPersonalInfoPage();
              break;
            case 'signup/choose_credentials':
              // Assume ChooseCredentialsPage collects new credentials and then
              // invokes 'onSignupComplete()'.
              builder = (BuildContext _) => ChooseCredentialsPage(
                    onSignupComplete: () {
                      // Referencing Navigator.of(context) from here refers to the
                      // top level Navigator because SignUpPage is above the
                      // nested Navigator that it created. Therefore, this pop()
                      // will pop the entire "sign up" journey and return to the
                      // "/" route, AKA HomePage.
                      Navigator.of(context).pop();
                    },
                  );
              break;
            default:
              throw Exception('Invalid route: ${settings.name}');
          }
          return MaterialPageRoute(builder: builder, settings: settings);
        },
      ),
    );
  }
}


IgnorePointer

可以使其子widget在长按时可拖动

  • 构造函数


  • 应用示例


AbsorbPointer

可以使其子widget在长按时可拖动

  • 构造函数


  • 应用示例


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值