Flutter listview随机单词显示及自定义dialog

Posted 伟雪无痕

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter listview随机单词显示及自定义dialog相关的知识,希望对你有一定的参考价值。

一.listview 简介

1.listview源码查看,listview是最常见的组件之一,对于列表的展示一般首选listview,下面看下listview中的构造函数eg :

 /// It is usually more efficient to create children on demand using
  /// [ListView.builder] because it will create the widget children lazily as necessary.
  ///
  /// The `addAutomaticKeepAlives` argument corresponds to the
  /// [SliverChildListDelegate.addAutomaticKeepAlives] property. The
  /// `addRepaintBoundaries` argument corresponds to the
  /// [SliverChildListDelegate.addRepaintBoundaries] property. The
  /// `addSemanticIndexes` argument corresponds to the
  /// [SliverChildListDelegate.addSemanticIndexes] property. None
  /// may be null.
  ListView(
    Key? key,
    Axis scrollDirection = Axis.vertical,
    bool reverse = false,
    ScrollController? controller,
    bool? primary,
    ScrollPhysics? physics,
    bool shrinkWrap = false,
    EdgeInsetsGeometry? padding,
	//ListView各个构造函数的共同参数  
    this.itemExtent,
    this.prototypeItem,//列表项原型
    bool addAutomaticKeepAlives = true,
    bool addRepaintBoundaries = true,
    bool addSemanticIndexes = true,
    double? cacheExtent,// 预渲染区域长度
    List<Widget> children = const <Widget>[],//子widget列表
    int? semanticChildCount,
    DragStartBehavior dragStartBehavior = DragStartBehavior.start,
    ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
    String? restorationId,
    Clip clipBehavior = Clip.hardEdge,
  ) 

itemExtent  //该参数如果不为null,则会强制children的“长度”为itemExtent的值
prototypeItem //指定列表项的长度,所以和指定 itemExtent 一样,指定 prototypeItem 会有更好的性能,但itemExtent 和prototypeItem不能同时指定
shrinkWrap //设置ListView的长度,默认值为false,如果ListView要设置为一个无边界的容器时,shrinkWrap必须为true

2.ListTile源码查看及介绍,ListTile相当于android listview中的item,用于填充listview,ListTile中提供了一些常用的属性,包括icon,text,点击事件etc,eg:

const ListTile(
    Key? key,
    this.leading, //item左边的图标
    this.title, //标题
    this.subtitle, //子标题
    this.trailing, //item右边的图标
    this.isThreeLine = false, //是否显示三行
    this.dense, //是否使用缩小布局
    this.visualDensity, //紧凑程度,VisualDensity
    this.shape, //形状,这里边缘颜色无效,再点击时阴影可以看出来效果
    this.contentPadding, //content内边距
    this.enabled = true, //是否可用,仅改变颜色,默认为 true
    this.onTap, //点击事件
    this.onLongPress, //长按事件
    this.mouseCursor, //是否可用,仅改变颜色,默认为 true
    this.selected = false, //是否选中状态,是否可用,仅改变颜色,默认为 true
    this.focusColor, //聚焦颜色
    this.hoverColor, //悬停颜色
    this.focusNode, //焦点控制
    this.autofocus = false, //自动聚焦,默认为 false
    this.tileColor,
    this.selectedTileColor,
    this.enableFeedback,
    this.horizontalTitleGap,
    this.minVerticalPadding,
    this.minLeadingWidth,
  )

二.Dialog介绍

1.AlertDialog属性介绍

1).源码查看,eg:

  const AlertDialog(
    Key? key,
    this.title, //标题
    this.titlePadding, //标题外间距
    this.titleTextStyle, //标题样式 TextStyle
    this.content, //内容显示
    this.contentPadding = const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 24.0), //内容外间距
    this.contentTextStyle, //内容文本样式 TextStyle
    this.actions, //事件子控件组
    this.actionsPadding = EdgeInsets.zero, //事件子控件间距,默认为 EdgeInsets.zero,
    this.actionsAlignment,
    this.actionsOverflowDirection, //事件过多时,竖向展示顺序,只有正向和反向,默认为 VerticalDirection.down
    this.actionsOverflowButtonSpacing, //事件过多时,竖向展示时,子控件间距
    this.buttonPadding, //actions 中每个按钮边缘填充距离,默认为左右各 8.0
    this.backgroundColor, //背景色
    this.elevation, //阴影高度
    this.semanticLabel, //语义标签
    this.insetPadding = _defaultInsetPadding, //对话框距离屏幕边缘间距
    this.clipBehavior = Clip.none, //超出部分剪切方式,Clip.none
    this.shape, //形状 ShapeBorder
    this.scrollable = false, //是否可以滚动,默认为 false
  )

2).AlertDialog代码片段

Future alertDialog() async 
    var alertDialogs = await showDialog(
        context: context,
        builder: (context) 
          return AlertDialog(
            title: Text("提示"),
            content: Text("确定要修改吗"),
            actions: <Widget>[
              FlatButton(
                  child: Text("取消"),
                  onPressed: () => Navigator.pop(context, "cancel")),
              FlatButton(
                  child: Text("确定"),
                  onPressed: () => Navigator.pop(context, "yes")),
            ],
          );
        );
    return alertDialogs;
  

2.SimpleDialog属性介绍

1).源码查看,eg:

  const SimpleDialog(
    Key? key,
    this.title, //标题
    this.titlePadding = const EdgeInsets.fromLTRB(24.0, 24.0, 24.0, 0.0), //标题外间距
    this.titleTextStyle, //标题样式 TextStyle
    this.children, //子控件,可以随意自定义
    this.contentPadding = const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 16.0), //内容外间距
    this.backgroundColor, //背景色
    this.elevation, //阴影高度
    this.semanticLabel, //语义标签
    this.insetPadding = _defaultInsetPadding,
    this.clipBehavior = Clip.none,
    this.shape, //形状 ShapeBorder
  ) 

2)..SimpleDialog代码片段

 Future alertSimpleDialog() async 
    var alertDialogs = await showDialog(
        context: context,
        builder: (context) 
          return SimpleDialog(
            title: Text("提示"),
            children: <Widget>[
              FlatButton(
                child: Text("Option1"),
                onPressed: () => Navigator.pop(context, "Option1"),
              ),
              FlatButton(
                child: Text("Option2"),
                onPressed: () => Navigator.pop(context, "Option2"),
              ),
              FlatButton(
                child: Text("Option3"),
                onPressed: () => Navigator.pop(context, "Option3"),
              ),
            ],
          );
        );
    return alertDialogs;
  

3.toast介绍,可参考toast弹窗实现

4.自定义dialog

1).dialog 属性介绍

const Dialog(
    Key? key,
    this.backgroundColor, //背景色
    this.elevation, //阴影高度
    this.insetAnimationDuration = const Duration(milliseconds: 100), //动画时间
    this.insetAnimationCurve = Curves.decelerate, //动画效果,渐进渐出等等
    this.insetPadding = _defaultInsetPadding, //对话框距离屏幕边缘间距
    this.clipBehavior = Clip.none, //超出部分剪切方式
    this.shape, 形状 ShapeBorder
    this.child, //自定义弹框
  ) 

2).dialog自定义,需要继承Dialog,eg:

class ListviewDialog extends Dialog 
  List<String>data=[
    "游戏",
    "视频",
    "财经",
    "体育",];
  @override
  Widget build(BuildContext context) 
    // TODO: implement build
    return new Material(
      //透明层
      type: MaterialType.transparency, //透明类型
      child: new Center(
        //控件居中
        child: new SizedBox(
          width: 200.0,
          height: 180.0,
          child: new Container(
            color: Colors.white,
            child: ListView.builder(
                itemCount:data.length==0?0:data.length,
                itemBuilder: (BuildContext context, int  position)
                  return itemWidget(context,position);
                ),
          ),
        ),
      ),
    );;
  
  Widget itemWidget(BuildContext context,int index)
    return GestureDetector(
      child: Container(
          height: 45,
          width: double.infinity,
          child: Center(
            child:  Text(
                data[index],
                style: TextStyle(
                  color: Colors.black
                ),
            ),
          )
      ),
      onTap: ()
        Navigator.pop(context,data[index]);
      ,
    );
  

三.demo 展示,通过英文随机单词显示listview,且点击listview弹出点击单词的toast,长按弹出自定义的dialog

1.需要在pubspec.yaml中配置依赖库,eg:

dependencies:
  flutter:
    sdk: flutter


  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for ios style icons.
  english_words: ^4.0.0

2.实现RandomWordsTest.dart文件

import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
import 'package:fluttertoast/fluttertoast.dart';

class RandomWords extends StatefulWidget
  @override
  _RandomWordsState createState()=>_RandomWordsState();


class _RandomWordsState extends State<RandomWords>

  final _suggestions=<WordPair>[];
  final _biggerFont=const TextStyle(fontSize: 16.0);


  @override
  Widget build(BuildContext context) 
    /*final wordpair=WordPair.random();
    return Text(wordpair.asPascalCase);*/
    return Scaffold(
      appBar: AppBar(
        title: const Text('Random words list'),
      ),
      body: _buildSuggestions(),
    );
  

  Widget _buildSuggestions()
    return ListView.builder(
        padding: const EdgeInsets.all(16.0),
        itemBuilder: (context,i)
          if(i.isOdd) return const Divider();
          final index=i~/2;
          if(index>=_suggestions.length)
            _suggestions.addAll(generateWordPairs().take(10));
          
          return _buildRow(_suggestions[index]);
        );
  

  Widget _buildRow(WordPair pair)
    return ListTile(
      leading: Icon(Icons.tab_rounded),// 右侧组件图标
      trailing: Icon(Icons.table_view_sharp), // 右侧组件图标
      title: Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
      onLongPress: ()//长按事件
        setState(() 
          showCustomDialog(context).then((value) //显示dialog
            print("回调值是---  >  "+pair.asPascalCase);
          );
        );
      ,
      onTap: ()//点击事件回调
        Fluttertoast.showToast(//消息提醒
            msg: pair.asPascalCase,
            toastLength: Toast.LENGTH_SHORT,
            gravity: ToastGravity.CENTER,
            timeInSecForIosWeb: 1,
            backgroundColor: Colors.white,
            textColor: Colors.black,
            fontSize: 18.0
        );
      ,
    );
  

  Future  showCustomDialog(BuildContext context )async 
    var  result=await showDialog(
        context: context,
        builder: (BuildContext context) 
          return ListviewDialog();
        );
    return result;
  



class ListviewDialog extends Dialog 
  List<String>data=[
    "游戏",
    "视频",
    "财经",
    "体育",];
  @override
  Widget build(BuildContext context) 
    // TODO: implement build
    return new Material(
      //透明层
      type: MaterialType.transparency, //透明类型
      child: new Center(
        //控件居中
        child: new SizedBox(
          width: 200.0,
          height: 180.0,
          child: new Container(
            color: Colors.white,
            child: ListView.builder(
                itemCount:data.length==0?0:data.length,
                itemBuilder: (BuildContext context, int  position)
                  return itemWidget(context,position);
                ),
          ),
        ),
      ),
    );;
  
  Widget itemWidget(BuildContext context,int index)
    return GestureDetector(
      child: Container(
          height: 45,
          width: double.infinity,
          child: Center(
            child:  Text(
                data[index],
                style: TextStyle(
                  color: Colors.black
                ),
            ),
          )
      ),
      onTap: ()
        Navigator.pop(context,data[index]);
      ,
    );
  

以上是关于Flutter listview随机单词显示及自定义dialog的主要内容,如果未能解决你的问题,请参考以下文章

Flutter GridView显示随机单词

如果我输入任何随机单词,它不会显示“未找到书”

Flutter 之列表和头部 (ListView + Header)

Listview ArrayAdapter 自定义项 onClickListener 仅第一次工作

Flutter - 在一个屏幕上显示两个 ListView

Flutter—ListView嵌套ListView不显示的问题