Flutter 仿微信支付界面

左侧是微信支付的界面,右侧是开发完成后的效果,图标是从 iconfont 上下载的。首先介绍一下本篇涉及到的组件。

带装饰效果的 Container

实际过程中我们经常会遇到一个容器需要额外的样式,例如圆角,背景色等。在 Flutter 中,对于各种容器都有一个 decoration 的属性,可以用于装饰容器。典型的用法有设置背景色、圆角、边框和阴影等,其中背景色可以使用渐变色。decoration 是一个 Decoration 对象,最常用的是 BoxDecoration,BoxDecoration 的属性如下所示:

const BoxDecoration({
    this.color,
    this.image,
    this.border,
    this.borderRadius,
    this.boxShadow,
    this.gradient,
    this.backgroundBlendMode,
    this.shape = BoxShape.rectangle,
  })

其中color为使用颜色填充容器,image 为 使用图片作为背景,border 为边框,borderRadius 为边框圆角,boxShadow 为容器阴影,gradient 使用渐变色作为背景,backgroundBlendMode 是指与容器的混合模型,默认是覆盖,shape 是背景形状,默认是矩形。其中背景部分我们一般只会选择一种。这里以上面的绿色圆弧背景为例,还加上了一点点渐变(渐变色支持多个,可以根据需要调节),示例代码如下:

return Container(
      //......
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(4.0),
        gradient: LinearGradient(
            begin: Alignment.topCenter,
            end: Alignment.bottomCenter,
            colors: [
              Color(0xFF56AF6D),
              Color(0xFF56AA6D),
            ]),
      ),
  		//...
    );

这里设置了边角为圆弧,半径为4,使用渐变色填充,渐变方向为从顶部中央到底部中央,渐变色有两个。

Row 行布局和 Column列布局

这个在之前的第五篇列表篇介绍过,其中 Row 代表行布局(即子元素按一行排布),Column 代表列布局(即子元素按一列排布)。具体可以参考Flutter 入门与实战(五):来一个图文并茂的列表。

ListView列表组件

列表视图,和之前的一篇一样,只是本篇的用法不同,用于实现整个页面可以按列表的方式进行滚动,直接将各个部分组件放入到列表的 children属性中,而不是使用数组构建列表元素,有点类似滚动视图的用法。

GridView网格组件

GridView 用于将一个容器按行列划分,可以指定主轴的元素个数(根据滚动方向定),之后自动按总元素的个数分别填充到网格,例如按纵向滚动时,则可以指定行方向一行有多少个网格,每个网格一个元素。超出一行数量后会自动换另一行。最简单的用法是使用 GridView.count 方法构建 GridView,用法如下:

GridView.count(
   crossAxisSpacing: gridSpace,
   mainAxisSpacing: gridSpace,
   crossAxisCount: crossAxisCount,
   //设置以下两个参数,禁止GridView的滚动,防止与 ListView 冲突
   shrinkWrap: true,
   physics: NeverScrollableScrollPhysics(),
   children: buttons.map((item) {
      return _getMenus(item['icon'], item['name'], color: textColor);
    }).toList(),
);

这里 crossAxisSpacing 是与滚动方向垂直的元素的间距,如按纵向(默认值)滚动,则是横向行元素之间的间距。mainAxisSpacing 是与滚动方向相同的元素的间距。children 即网格中的元素。这里需要注意的是,由于 本例中GridView是嵌套在 ListView 里面的,两个组件都是纵向滚动,这样会引起冲突导致布局无法满足约束。因此,在这里设置了 shrinkWrap 为 true 和 physics 为NeverScrollableScrollPhysics,以禁止 GridView 的滚动,从而满足约束。

代码实现

首先来分析布局,所有菜单按钮其实都是一样的布局,可以使用统一的列布局完成菜单按钮,提高复用性。菜单按钮从上到下一次为图标、间距(图标与文字之间)和菜单名称。实现代码如下:

Column _getMenus(String icon, String name, {Color color = Colors.black}) {
  return Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: <Widget>[
      SizedBox(
        child: Image.asset(icon),
        width: 50,
        height: 50,
      ),
      SizedBox(
        height: 5,
      ),
      Text(name, style: TextStyle(fontSize: 14.0, color: color, height: 2)),
    ],
  );

通过传输一个图标名称,菜单名称和可选的字体颜色(顶部区域和其他的文字颜色不同)来实现单个菜单。

其次来看顶部区域,顶部区域只有两个按钮,使用带装饰的容器实现背景的装饰和圆角。再采用行布局将两个菜单按钮在横向均匀排布。同时,使用 Center 布局将两个菜单保持中部居中。这里指定了容器的高度,这是因为从美观上看太矮了不太协调,实际开发要根据 UI 设计稿定。

Widget _headerGridButtons() {
    double height = 144;
    List<Map<String, String>> buttons = GridMockData.headerGrids();
    return Container(
      height: height,
      margin: EdgeInsets.fromLTRB(MARGIN, MARGIN, MARGIN, MARGIN / 2),
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(4.0),
        gradient: LinearGradient(
            begin: Alignment.topCenter,
            end: Alignment.bottomCenter,
            colors: [
              Color(0xFF56AF6D),
              Color(0xFF56AA6D),
            ]),
      ),
      child: Center(
        child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: buttons
                .map((item) =>
                    _getMenus(item['icon'], item['name'], color: Colors.white))
                .toList()),
      ),
    );
  }

其他菜单布局都是一样,只是区域标题,菜单数量、菜单内容不同,因此可以统一封装一个通用的方法来构建任意形式的菜单,以及设置区域标题的字体样式、圆角背景等属性。菜单均使用 GridView 实现网格式布局,同时由于菜单布局相同,可以封装一个通用的方法来指定网格一行按钮的数量,按钮字体颜色等属性,实现代码的复用。

Widget _dynamicGridButtons(List<Map<String, String>> buttons, String title,
      {int crossAxisCount = 4}) {
    return Container(
      margin: EdgeInsets.fromLTRB(MARGIN, MARGIN, MARGIN, MARGIN / 2),
      padding: EdgeInsets.all(MARGIN),
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(4.0),
        color: Colors.white,
      ),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(
            title,
            style: TextStyle(color: Colors.grey[700]),
          ),
          SizedBox(height: 20),
          _gridButtons(buttons, crossAxisCount, textColor: Colors.black),
        ],
      ),
    );
  }

GridView _gridButtons(List<Map<String, String>> buttons, int crossAxisCount,
      {Color textColor = Colors.white}) {
    double gridSpace = 5.0;
    return GridView.count(
      crossAxisSpacing: gridSpace,
      mainAxisSpacing: gridSpace,
      crossAxisCount: crossAxisCount,
      //设置以下两个参数,禁止GridView的滚动,防止与 ListView 冲突
      shrinkWrap: true,
      physics: NeverScrollableScrollPhysics(),
      children: buttons.map((item) {
        return _getMenus(item['icon'], item['name'], color: textColor);
      }).toList(),
    );
  }
}

ListView 构建完整页面:实际的整个页面很简单,只需要将各个区域放入到 ListView 的 children 属性即可,从这里也可以看出,将子组件尽可能细化,不但能够提高代码复用性,还可以降低嵌套层级,提高代码的可读性和可维护性。

@override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView(
        children: [
          _headerGridButtons(),
          _dynamicGridButtons(GridMockData.financeGrids(), '金融理财'),
          _dynamicGridButtons(GridMockData.serviceGrids(), '生活服务'),
          _dynamicGridButtons(GridMockData.thirdpartyGrids(), '购物消费'),
        ],
      ),
    );
  }

Mock 数据准备
按钮数据均使用 Mock 数据,这里只是返回一个 List<Map<String, String>>数组对象,对象里是每个菜单的图标文件名称和菜单名称,下面是金融服务区域的菜单 Mock方法。

static List<Map<String, String>> financeGrids() {
    return [
      {'name': '信用卡还款', 'icon': 'images/grid-buttons/grid-1-1.png'},
      {'name': '借钱', 'icon': 'images/grid-buttons/grid-1-2.png'},
      {'name': '理财', 'icon': 'images/grid-buttons/grid-1-3.png'},
      {'name': '保险', 'icon': 'images/grid-buttons/grid-1-4.png'},
    ];
  }

其他待改进的地方:从代码中可以看出,访问按钮的时候是使用 Map 对象的键来访问的,需要使用['name']或['icon']来访问,这种方式非常不利于编码,而且很容易拼写错误。因此,实际使用中应当将 Json 对象(即 Map)转换为实体类,这样就可以通过访问实体类的属性来设置菜单的参数,实际维护起来更为方便。

结语:

Flutter 提供的基础 UI 组件库能够满足绝大部分复杂页面布局,通过各种布局组件的组合即可完成。因此,熟悉基础的布局组件的特性十分重要。同时,需要注意组件的拆分和抽离完成子组件的封装,提高复用性的同时也避免了嵌套层级过深的问题。

以上就是Flutter 仿微信支付界面的实现的详细内容,更多关于Flutter 微信支付界面的资料请关注我们其它相关文章!

(0)

相关推荐

  • flutter 实现点击下拉栏微信右上角弹出窗功能

    先看效果实现 需求分析 这个是使用 PopupRoute这个路由类进行实现 大概原理就是利用PopupRpute这个类进行改造,然后自定义一个页面,页面内镶嵌一个动画类,用来实现缩放动画 大概分为三部分,PopupRoute改造,弹出页面设置,动画类设置. 为什么选择PopupRoute? 可以镶嵌在flutter本身的路由管理之中 也就是逻辑操作都是正常的页面管理,可以手动管理,也可以用路由返回直接关掉,不会影响原有页面和布局 第一步,改造PopupRoute类 import 'package

  • flutter仿微信底部图标渐变功能的实现代码

    先给大家展示下效果图,感觉不错请参考实例代码. 实现思路 在flutter中,如果想实现上面的页面切换效果,必然会想到pageView.pageView的controller可以监听到pageView的滚动事件,也可以获取pageView滚动的位置,所以我们在滚动事件中根据位置去改变对应的图标颜色就可以实现了. 改变图标颜色 图标是从微信中提取出来的,都是webp格式的图片.要改变图片颜色可以使用ImageIcon这个组件. ImageIcon会把一张图片变成单色图片,所以只要图片没有多色的要求

  • Flutter实现仿微信底部菜单栏功能

    import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget{ @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: MyHomePage(), ), ); } } class MyHomePage extends Sta

  • Flutter 仿微信支付界面

    左侧是微信支付的界面,右侧是开发完成后的效果,图标是从 iconfont 上下载的.首先介绍一下本篇涉及到的组件. 带装饰效果的 Container 实际过程中我们经常会遇到一个容器需要额外的样式,例如圆角,背景色等.在 Flutter 中,对于各种容器都有一个 decoration 的属性,可以用于装饰容器.典型的用法有设置背景色.圆角.边框和阴影等,其中背景色可以使用渐变色.decoration 是一个 Decoration 对象,最常用的是 BoxDecoration,BoxDecorat

  • Android仿微信主界面的实现方法

    本文实例为大家分享了Android模仿微信主界面展示的具体代码,供大家参考,具体内容如下 先看一下效果图 实现的原理: ViewPager+FragmentPagerAdapter 主界面可分为三部分: top标题栏就是一个TextView 中间的ViewPager作为显示的容器,填充Fragment bottom是一个RadioGroup 这里为了布局的优化,将top和bottom抽取出来 ,然后用include将其导入主布局,如下 <LinearLayout xmlns:android=&quo

  • Android用ActionBar高仿微信主界面的实例代码

    经过前面两篇文章的学习,我想大家对ActionBar都已经有一个相对较为深刻的理解了.唯一欠缺的是,前面我们都只是学习了理论知识而已,虽然知识点已经掌握了,但是真正投入到项目实战当中时会不会掉链子还很难说.那么不用担心,本篇文章我就将带领大家一起进入ActionBar的应用实战,将理论和实践完美结合到一起. 如果你还没有看过我的前两篇文章,建议先去阅读一下 Android ActionBar完全解析使用官方推荐的最佳导航栏(上)和 Android ActionBar完全解析使用官方推荐的最佳导航

  • JS实现仿微信支付弹窗功能

    先奉上效果图 html代码 <!DOCTYPE html> <html> <head> <title>仿手机微信支付输入密码界面效果</title> <meta charset="utf-8" /> <meta name="viewport" content="initial-scale=1.0, width=device-width, user-scalable=no"

  • iOS高仿微信相册界面翻转过渡动画效果

    点开微信相册的时候,想要在相册图片界面跳转查看点赞和评论时,微信会采用界面翻转的过渡动画来跳转到评论界面,好像是在图片界面的背面一样,点击完成又会翻转回到图片界面,这不同于一般的导航界面滑动动画,觉得很有意思,于是自己学着做了一下,其实也很简单,下面是实现的类似的效果图: 在图片界面点击右下角的查看评论会翻转到评论界面,评论界面点击左上角的返回按钮会反方向翻转回图片界面,真正的实现方法,与传统的导航栏过渡其实只有一行代码的区别,让我们来看看整体的实现. 首先我们实现图片界面,这个界面上有黑色的背

  • Android高仿微信聊天界面代码分享

    微信聊天现在非常火,是因其界面漂亮吗,哈哈,也许吧.微信每条消息都带有一个气泡,非常迷人,看起来感觉实现起来非常难,其实并不难.下面小编给大家分享实现代码. 先给大家展示下实现效果图: OK,下面我们来看一下整个小项目的主体结构: 下面是Activity的代码: package com.way.demo; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import jav

  • Android 高仿微信支付数字键盘功能

    现在很多app的支付.输入密码功能,都已经开始使用自定义数字键盘,不仅更加方便.其效果着实精致. 下面带着大家学习下,如何高仿微信的数字键盘,可以拿来直接用在自身的项目中. 先看下效果图: 1. 自定义布局 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

  • Android仿微信支付密码弹出层功能

    预览 使用 这个弹出层是一个DialogFragment,逻辑都封装在其内部,使用起来很简单: Bundle bundle = new Bundle(); bundle.putString(PayFragment.EXTRA_CONTENT, "提现:¥ " + 100.00); PayFragment fragment = new PayFragment(); fragment.setArguments(bundle); fragment.setPaySuccessCallBack(

  • ViewPager+RadioGroup仿微信主界面

    话不多说,先上图,如图效果,可以点击底部按钮选择页面,也可以滑动页面进行选择. 那么我们下面就来实现一下吧. 首先创建工程WXTest,主界面布局使用ViewPager+RadioGroup来实现,界面代码如下. <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&quo

  • react+redux仿微信聊天界面

    一.项目概况 基于react+react-dom+react-router-dom+redux+react-redux+webpack2.0+react-photoswipe+swiper等技术混合开发的手机端仿微信界面聊天室--reactChatRoom,实现了聊天记录下拉刷新.发送消息.表情(动图),图片.视频预览,打赏.红包等功能. 二.技术栈MVVM框架: react / react-dom状态管理:redux / react-redux页面路由:react-router-dom弹窗插件

随机推荐