Flutter手势密码的实现示例(附demo)

目录
  • 前言
  • 开始
    • 绘制圆点
    • 绘制手势路径
  • 组合9个圆点盘和手势路径
  • 手势密码组件的使用
  • 上传自定义组件到pub仓库
  • 后记

前言

本篇记录的是使用Flutter完成手势密码的功能,大致效果如下图所示:

该手势密码的功能比较简单,下面会详细记录实现的过程,另外还会简单说明如何将该手势密码作为插件发布到pub仓库。

开始

实现上面的手势密码并不难,大致可以拆分成如下几部分来完成:

  • 绘制9个圆点
  • 绘制手指滑动的线路
  • 合并以上两个部分

绘制圆点

我们使用面向对象的方式来处理9个圆点的绘制,每个圆点作为一个GesturePoint类,这个类要提供一个圆心坐标和半径才能画出圆形来,这里先放上这个类的源码:

// point.dart
import 'package:flutter/material.dart';
import 'dart:math';

// 手势密码盘上的圆点
class GesturePoint {
  // 中心实心圆点的画笔
  static final pointPainter = Paint()
    ..style = PaintingStyle.fill
    ..color = Colors.blue;

  // 外层圆环的画笔
  static final linePainter = Paint()
    ..style = PaintingStyle.stroke
    ..strokeWidth = 1.2
    ..color = Colors.blue;

  // 圆点索引,0-9
  final int index;
  // 圆心坐标
  final double centerX;
  final double centerY;
  // 中心实心圆点的半径
  final double radius = 4;
  // 外层空心的圆环半径
  final double padding = 26;

  GesturePoint(this.index, this.centerX, this.centerY);

  // 绘制小圆点
  void drawCircle(Canvas canvas) {
    // 绘制中心实心的圆点
    canvas.drawOval(
        Rect.fromCircle(center: Offset(centerX, centerY), radius: radius),
        pointPainter);

    // 绘制外层的圆环
    canvas.drawOval(
        Rect.fromCircle(center: Offset(centerX, centerY), radius: padding),
        linePainter);
  }

  // 判断坐标是否在小圆内(padding为半径)
  // 该方法用于在手指滑动时做判断,一旦坐标处于圆点内部,则认为选中该圆点
  bool checkInside(double x, double y) {
    var distance = sqrt(pow((x - centerX), 2) + pow((y - centerY), 2));
    return distance <= padding;
  }

  // 提供比较方法,用于判断List中是否存在某个点
  // 这个方法会在后面用到,当手势滑动到某个点时,如果之前滑动到过这个点,则这个点不能再被选中
  @override
  bool operator ==(Object other) {
    if (other is GesturePoint) {
      return this.index == other.index &&
          this.centerX == other.centerX &&
          this.centerY == other.centerY;
    }
    return false;
  }

  // 复写==方法时必须同时复写hashCode方法
  @override
  int get hashCode => super.hashCode;

}

上面需要注意的是,GesturePoint类提供了一个drawCircle方法用于绘制自身,将会在后面的代码中用到。

有了圆点这个对象,我们还需要将9个圆点依次画在屏幕上,由于这9个圆点后续是不再更新的,所以使用一个StatelessWidget即可。(如果你需要做成手指滑动到某个圆点,该圆点变色的效果,则需要用StatefulWidget组件去更新状态。)

下面使用一个自定义的无状态组件去画这9个圆点,代码如下:

// panel.dart
import 'package:flutter/material.dart';
import 'package:flutter_gesture_password/point.dart';

// 9个圆点视图
class GestureDotsPanel extends StatelessWidget {
  // 表示圆点盘的宽高
  final double width, height;
  // 装载9个圆点的集合,从外部传入
  final List<GesturePoint> points;

  // 构造方法
  GestureDotsPanel(this.width, this.height, this.points);

  @override
  Widget build(BuildContext context) {
    return Container(
      width: width,
      height: height,
      child: CustomPaint(
        painter: _PanelPainter(points),
      ),
    );
  }
}

// 自定义的Painter,用于从圆点集合中遍历所有圆点并依次画出
class _PanelPainter extends CustomPainter {
  final List<GesturePoint> points;

  _PanelPainter(this.points);

  @override
  void paint(Canvas canvas, Size size) {
    if (points.isNotEmpty) {
      for (var p in points) {
        // 画出所有的圆点
        p.drawCircle(canvas);
      }
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false; // 不让更新

}

以上代码比较简单,就不做详细说明了,如果对Flutter绘图基础还不了解的同学,可以看看这里的介绍:《Flutter实战——自绘组件 (CustomPaint与Canvas)

绘制手势路径

之所以手势路径要单独拿出来绘制,没有跟上面的9个小圆点盘放一起,是因为我们的圆点盘是不更新的,而手势路径需要在手指的每一次滑动中更新,所以单独将手势路径作为一个组件。显然这个组件是一个有状态的组件,需要继承StatefulWidget来实现。

在开始编码前,我们需要分析手势滑动的流程:

  • 必须监听手指按下,手指滑动,手指抬起三种不同的事件
  • 手指按下时,如果不在9个圆点中的任意一个上面,则手指滑动是无效的
  • 手指按下时若在某个点上,则后面手指移动时,需要绘制从那个点到手指当前的一条直线,若手指移动过程中进入其他圆点,则需要先绘制之前手指经过的所有圆点间的直线,再绘制最后一个圆点到手指当前滑动的坐标间的直线
  • 每个圆点只允许被记录一次,若之前手指滑动经过某个点,后面手指再经过该点时,该点不应该被记录
  • 手指抬起后,需要计算手指移动过程中经过了哪些点,以数组的形式返回所有点的索引。且手指抬起后,不需要绘制最后一个点到手指抬起时的坐标间的直线

梳理了上面的手势密码绘制流程后,我们还需要了解Flutter处理手势的一些API,本例子中主要使用的GestureDetector,这是Flutter官方对移动端手势封装的一个Widget,使用起来非常方便,如果有不太了解的同学,可以参考这里——《Flutter实战——手势识别

下面放上绘制手势密码路径的所有代码:

// path.dart
import 'package:flutter/material.dart';
import 'package:flutter_gesture_password/gesture_view.dart';
import 'package:flutter_gesture_password/point.dart';

// 手势密码路径视图
class GesturePathView extends StatefulWidget {
  // 手势密码路径视图的宽高,需要跟圆点视图保持一致,由构造方法传入
  final double width;
  final double height;
  // 手势密码中的9个点,由构造方法传入
  final List<GesturePoint> points;
  // 手势密码监听器,用于在手指抬起时触发,其定义为:typedef OnGestureCompleteListener = void Function(List<int>);
  final OnGestureCompleteListener listener;

  // 构造方法
  GesturePathView(this.width, this.height, this.points, this.listener);

  @override
  State<StatefulWidget> createState() => _GesturePathViewState();
}

class _GesturePathViewState extends State<GesturePathView> {
  // 记录手指按下或者滑动过程中,经过的最后一个点
  GesturePoint? lastPoint;
  // 记录手指滑动时的坐标
  Offset? movePos;
  // 记录手指滑动过程中所有经过的点
  List<GesturePoint> pathPoints = [];

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      child: CustomPaint(
        size: Size(widget.width, widget.height),    // 指定组件大小
        painter: _PathPainter(movePos, pathPoints), // 指定组件的绘制者,当movePos或者pathPoints更新时,整个组件也需要更新
      ),
      onPanDown: _onPanDown,     // 手指按下
      onPanUpdate: _onPanUpdate, // 手指滑动
      onPanEnd: _onPanEnd,       // 手指抬起
    );
  }

  // 手指按下
  _onPanDown(DragDownDetails e) {
    // 判断按下的坐标是否在某个点上
    // 注意:e.localPosition表示的坐标为相对整个组件的坐标
    // e.globalPosition表示的坐标为相对整个屏幕的坐标
    final x = e.localPosition.dx;
    final y = e.localPosition.dy;
    // 判断是否按在某个点上
    for (var p in widget.points) {
      if (p.checkInside(x, y)) {
        lastPoint = p;
      }
    }
    // 重置pathPoints
    pathPoints.clear();
  }

  // 手指滑动
  _onPanUpdate(DragUpdateDetails e) {
    // 如果手指按下时不在某个圆点上,则不处理滑动事件
    if (lastPoint == null) {
      return;
    }
    // 滑动时如果在某个圆点上,则将该圆点加入路径中
    final x = e.localPosition.dx;
    final y = e.localPosition.dy;
    // passPoint代表手指滑动时是否经过某个点,可为空
    GesturePoint? passPoint;
    for (var p in widget.points) {
      // 如果手指滑动经过某个点,且这个点之前没有经过,则记录下这个点
      if (p.checkInside(x, y) && !pathPoints.contains(p)) {
        passPoint = p;
        break;
      }
    }
    setState(() {
      // 如果经过点部为空,则需要刷新lastPoint和pathPoints,触发整个组件的更新
      if (passPoint != null) {
        lastPoint = passPoint;
        pathPoints.add(passPoint);
      }
      // 更新movePos的值
      movePos = Offset(x, y);
    });
  }

  // 手指抬起
  _onPanEnd(DragEndDetails e) {
    setState(() {
      // 将movePos设置为空,防止画出最后一个点到手指抬起时的坐标间的直线
      movePos = null;
    });
    // 调用Listener,返回手势经过的所有点
    List<int> arr = [];
    if (pathPoints.isNotEmpty) {
      for (var value in pathPoints) {
        arr.add(value.index);
      }
    }
    widget.listener(arr);
  }
}

// 绘制手势路径
class _PathPainter extends CustomPainter {
  // 手指当前的坐标
  final Offset? movePos;
  // 手指经过点集合
  final List<GesturePoint> pathPoints;

  // 路径画笔
  final pathPainter = Paint()
    ..style = PaintingStyle.stroke
    ..strokeWidth = 6
    ..strokeCap = StrokeCap.round
    ..color = Colors.blue;

  _PathPainter(this.movePos, this.pathPoints);

  @override
  void paint(Canvas canvas, Size size) {
    _drawPassPath(canvas);
    _drawRTPath(canvas);
  }

  // 绘制手指一动过程中,经过的所有点之间的直线
  _drawPassPath(Canvas canvas) {
    if (pathPoints.length <= 1) {
      return;
    }
    for (int i = 0; i < pathPoints.length - 1; i++) {
      var start = pathPoints[i];
      var end = pathPoints[i + 1];
      canvas.drawLine(Offset(start.centerX, start.centerY),
          Offset(end.centerX, end.centerY), pathPainter);
    }
  }

  // 绘制实时的,最后一个经过点和当前手指坐标间的直线
  _drawRTPath(Canvas canvas) {
    if (pathPoints.isNotEmpty && movePos != null) {
      var lastPoint = pathPoints.last;
      canvas.drawLine(Offset(lastPoint.centerX, lastPoint.centerY), movePos!, pathPainter);
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}

组合9个圆点盘和手势路径

组合这两个组件需要用到Stack组件,代码比较简单,直接上代码了:

import 'package:flutter/material.dart';
import 'package:flutter_gesture_password/path.dart';
import 'package:flutter_gesture_password/point.dart';
import 'package:flutter_gesture_password/panel.dart';

// 定义手势密码回调监听器
typedef OnGestureCompleteListener = void Function(List<int>);

class GestureView extends StatefulWidget {
  final double width, height;
  final OnGestureCompleteListener listener;

  GestureView({required this.width, required this.height, required this.listener});

  @override
  State<StatefulWidget> createState() => _GestureViewState();
}

class _GestureViewState extends State<GestureView> {
  List<GesturePoint> _points = [];

  @override
  void initState() {
    super.initState();
    // 计算9个圆点的位置坐标
    double deltaW = widget.width / 4;
    double deltaH = widget.height / 4;
    for (int row = 0; row < 3; row++) {
      for (int col = 0; col < 3; col++) {
        int index = row * 3 + col;
        var p = GesturePoint(index, (col + 1) * deltaW, (row + 1) * deltaH);
        _points.add(p);
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        GestureDotsPanel(widget.width, widget.height, _points),
        GesturePathView(widget.width, widget.height, _points, widget.listener)
      ],
    );
  }
}

手势密码组件的使用

到这里,手势密码就开发完成了,使用起来也非常简单,本文开篇的预览图使用的如下代码:

import 'package:flutter/material.dart';
import 'package:flutter_gesture_password/gesture_view.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Gesture password',
      home: _Home(),
    );
  }
}

class _Home extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _HomeState();
}

class _HomeState extends State<_Home> {
  List<int>? pathArr;

  @override
  Widget build(BuildContext context) {
    final screenWidth = MediaQuery.of(context).size.width;
    return Scaffold(
      appBar: AppBar(
        title: Text('Gesture password'),
      ),
      body: Column(
        children: [
          GestureView(
            width: screenWidth,
            height: screenWidth,
            listener: (arr) {
              setState(() {
                pathArr = arr;
              });
            },
          ),
          Text("${pathArr == null ? '' : pathArr}")
        ],
      ),
    );
  }
}

上传自定义组件到pub仓库

上传自定义组件到Pub仓库的流程不算很复杂,这里先放上官方文档:https://dart.cn/tools/pub/publishing
下面整理发布插件到pub仓库的主要步骤:

(这一步非必须但是建议)在github上新建一个项目,并将我们写的代码push到该仓库。(后面配置homepage时可以直接使用GitHub仓库地址)

在项目根目录下创建README.md文件,在其中编写对于项目的一些介绍,以及你编写的插件的用法
在项目根目录下创建CHANGELOG.md文件,记录每个不同版本更新了什么
在项目根目录下新建一个LICENSE文件,表明该插件使用什么开源协议
修改项目中的pubspec.yaml文件,主要修改点有:

homepage: 「填写项目主页地址,这里可以直接用github仓库地址」
publish_to: 'https://pub.dev' # 这个配置表示要把插件发布到哪里
version: 0.0.2 # 插件版本,每次更新记得修改这个version

在项目根目录下执行dart pub publish,首次执行会出现如下提示:

Package has 2 warnings.. Do you want to publish xxx 0.0.1 (y/N)? y
Pub needs your authorization to upload packages on your behalf.
In a web browser, go to https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force&response_type=code&client_id=8183068855108-8grd2eg9tjq9f38os6f1urbcvsq39u8n.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A55486&code_challenge=V1-sGcrLkXljXXpOyJdqf8BJfRzBcUQaH9G1m329_M&code_challenge_method=S2536&scope=openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email
Then click "Allow access".

Waiting for your authorization...

点击上面的链接会打开浏览器,授权即可。授权通过后,控制台会提示上传完成等信息。

后记

本篇记录的Flutter手势密码已经上传到pub仓库,地址为:https://pub.dev/packages/flutter_gesture_password
该项目的源码已托管至GitHub:https://github.com/yubo725/flutter-gesture-password

手势密码的最基本的实现方式就是上面的过程了,在本例中我并未做过多的封装,也没有提供更多的配置项比如手势密码圆点颜色,路径线条颜色、粗细等等,这些大家可以根据自己的项目,自行拷贝代码并做相应修改。另外,手势密码的保存与校验不在本篇记录范围内,大家可以根据最终的整型数组来做一些加密之类并保存到本地,在校验密码时,做字符串匹配即可。

到此这篇关于Flutter手势密码的实现示例(附demo)的文章就介绍到这了,更多相关Flutter手势密码内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Android自定义控件实现手势密码

    Android手势解锁密码效果图 首先呢想写这个手势密码的想法呢,完全是凭空而来的,然后笔者就花了一天时间弄出来了.本以为这个东西很简单,实际上手的时候发现,还有很多逻辑需要处理,稍不注意就容易乱套.写个UI效果图大约只花了3个小时,但是处理逻辑就处理了2个小时!废话不多说,下面开始讲解.      楼主呢,自己比较自定义控件,什么东西都掌握在自己的手里感觉那是相当不错(对于赶工期的小伙瓣儿们还是别手贱了,非常容易掉坑),一有了这个目标,我就开始构思实现方式.      1.整个自定义控件是继承

  • Android手势密码的实现

    一.大致界面介绍: 图1 图2 图3 图4 图1:手势密码绘制界面 [主要是绘制上方的9个提示图标和9个宫格密码图标] 图2:设置手势密码 [监听手势的输入,TouchEvent的事件处理,获取输入的手势密码,同时显示在上方的提示区域] 图3:再绘制一次,两次密码不一致提示界面 [这里在实现的时候,错误提示文字加了"左右晃动的动画",错误路径颜色标记为红色] 图4:校验手势密码,输入的密码错误,给予红色路径+错误文字提示 二.实现思路: 1. 正上方的提示区域,用一个类(LockInd

  • Android手势密码--设置和校验功能的实现代码

    效果图如下,大家感觉不错请参考实现代码 具体代码如下所示: private void setGesturePassword() { toggleMore.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecke

  • Android实现手势密码功能

    本文实例为大家分享了Android实现手势密码功能的具体代码,供大家参考,具体内容如下 首先声明一下,九宫格布局是从网上扒了一个大神写好的,大家在项目中实现的话可以直接把: Drawl,GuestureLockView,Point类直接复制到自己的项目中: 想了解功能的可以仔细看下源码中的这三个类,里面写的也非常详细: 使用GuestureLockView的三个步: 1.初始化布局容器: 2.初始化GuestureLockView; 3.将GuestureLockView添加到布局容器中: 创建

  • Android自定义UI手势密码终结版

    之前写过3篇手势密码的demo,不过没有集成到真实的企业项目中,这几天正好领到一个手势密码项目,昨天刚好弄完,今天抽空整理下,目前还没有完善,有一些地方需要更改,不过基本的流程都可以跑通了. 源码下载地址:http://xiazai.jb51.net/201610/yuanma/AndroidGestureLock(jb51.net).rar 先看主界面的入口把.里面有2个button(一个是设置手势密码.一个是校验手势密码) activity_main.xml <RelativeLayout

  • Android仿支付宝手势密码解锁功能

    Starting 创建手势密码可以查看 CreateGestureActivity.java 文件. 登陆验证手势密码可以看 GestureLoginActivity.java 文件. Features 使用了 JakeWharton/butterknife butterknife 使用了 ACache 来存储手势密码 /** * 保存手势密码 */ private void saveChosenPattern(List<LockPatternView.Cell> cells) { byte[

  • Android 简易手势密码开源库详解

    简介 本文介绍一个Android手势密码开源库的使用及实现的详细过程,该开源库主要实现以下几个功能: 支持手势密码的绘制,并支持密码保存功能,解锁时自动比对密码给出结果 封装了绘制密码的方法,比对两次密码是否一致,可以快捷地进行手势密码的设置 可以设置密码输入错误后的重试次数上限 可以自定义不同状态下手势密码图案的颜色 可以自定义手势密码的触摸点数量(n*n) 最近需要用到手势密码解锁功能,找了一些demo感觉用起来都有点麻烦,于是参考一些文章自己造了下轮子,封装了相关的一些方法,使用起来比较便

  • Android手势密码实现实例代码

    一.效果实现 二.实现思路: 1. 正上方的提示区域,用一个类(LockIndicator.java)来实现,自定义view来绘制9个提示图标: 2. 手势密码绘制区域,用一个类(GestureContentView.java)来实现,它继承自ViewGroup里面, 添加9个ImageView来表示图标, 在onLayout()方法中设置它们的位置: 3. 手势路径绘制, 用一个类(GestureDrawline.java)来实现,复写onTouchEvent()方法,在这个方法里面监听Tou

  • Android九宫格手势密码代码设计

    最近因为项目需要用到九宫格密码(也叫手势轨迹密码),特地去学习了一下九宫格密码的实现原来.可能有人认为九宫格密码事例网上到处都有,很多甚至直接拷贝过来就可以运行为什么还要学习呢.还特地写到网上有必要吗?其实写这个目的是为了增强和锻炼自己的语言组织能力.其实如果只是既然是学习就不光是要知道答案(完成效果)更重要的是知道他什么实现. 好了题外话就不多说了,要实现九宫格密码要解决的问题有: 1.给九宫格密码界面布局九个点,即确定每个节点的位置.每个点到上下左右的距离都是相同的.即九个点刚好围成一个正方

  • Flutter手势密码的实现示例(附demo)

    目录 前言 开始 绘制圆点 绘制手势路径 组合9个圆点盘和手势路径 手势密码组件的使用 上传自定义组件到pub仓库 后记 前言 本篇记录的是使用Flutter完成手势密码的功能,大致效果如下图所示: 该手势密码的功能比较简单,下面会详细记录实现的过程,另外还会简单说明如何将该手势密码作为插件发布到pub仓库. 开始 实现上面的手势密码并不难,大致可以拆分成如下几部分来完成: 绘制9个圆点 绘制手指滑动的线路 合并以上两个部分 绘制圆点 我们使用面向对象的方式来处理9个圆点的绘制,每个圆点作为一个

  • vue项目中扫码支付的实现示例(附demo)

    目录 需求背景 思路分析 UI展示 开始使用 一 编写支付组件模板 二 支付组件的JS相关代码和说明 附:组件JS完整的源码 需求背景 市场报告列表展示的报告有两种类型,一种是免费报告,另一种是付费报告.免费报告用户可以直接查看,付费报告需要用户购买之后才能查看. 思路分析 点击查看为付费报告,弹出支付二维码. 创建订单,二维码进行倒计时,其展示5秒后开始监听支付回调结果,频次为五秒一次. 倒计时第一次倒数到0秒,提醒二维码过期让用户点击刷新二维码. 继续倒计时并开始监听支付回调结果. 刷新之后

  • C++实现功能齐全的屏幕截图示例(附demo)

    目录 1.概述 2.屏幕截图的主要功能点 3.屏幕截图的主体实现思路 3.1.截图主窗口全屏置顶 3.2.桌面灰化 3.3.窗口自动套索 3.4.区域放大 3.5.截取区域的选择 3.5.截图工具条 3.6.矩形等图元的绘制 4.桌面灰化的实现细节 5.窗口自动套索实现 6.区域放大实现 7.截取区域的选择 8.矩形等图元的绘制 9.截图窗口的绘制机制 10.截图退出类型的详细设计 11.创建位图时将CreateCompatibleBitmap替换成CreateDIBSection 12.最后

  • Python实现病毒仿真器的方法示例(附demo)

    最近新冠在神州大陆横行,全国上下一心抗击疫情.作为一枚程序员,我也希望可以为抗击疫情做出自己的贡献,钟院士一直劝说大家不要出门,减少人口间的流动.对此,我特意做了一个病毒仿真器,探询冠状病毒传播. 1. 仿真效果 仿真开始,一开始只有5个发病者,传播率为0.8,潜伏期为14天 由于人口的流动,以及医院床位的隔离,一开始病毒扩撒不是很速度 随着医院床位满了,隔离失败,加上人口的流动,病患数开始几何式的增加 2. 什么是仿真器 仿真器(emulator)以某一系统复现另一系统的功能.与计算机模拟系统

  • Zend Framework入门之环境配置及第一个Hello World示例(附demo源码下载)

    本文实例讲述了Zend Framework入门之环境配置及第一个Hello World程序.分享给大家供大家参考,具体如下: 第一步:确认你的PHP环境: 1.请PHPer确认你的PHP版本是否在5.2.0以上..如果不是的话..请更新到5.2.0,否则.Zend Framework 好像用不了..我自己有试过. 遇到过这样的问题..所以请你们自己测试一下..PHP源码最新版下载地址为:http://www.php.net/downloads.php. 2.你的PHP环境配置好了之后,请打开ph

  • 基于Flutter实现手势密码加密与解锁功能

    目录 前言 1.绘制静态图形 2.存储手势密码数据 3.添加手势交互 4.绘制.刷新密码线 5.加入密码错误动画 总结 前言 密码的由来:在公元前405年,由古希腊和斯巴达的战争中,由于斯巴达盟友波斯帝国背叛,导致古希腊和斯巴达两败俱伤,这时斯巴达抓了一个波斯国的信使,这个信使 没有任何情报,只有一条有着杂乱无章的希腊字母的普通腰带,最终斯巴达统帅破解了这条腰带,成功击败了希腊.这就是世界上最早的密码.同时也是世界上最早的解密. 密码在我们生活中无处不在,作为个人隐私的最后一道防线显得无比的重要

  • 微信小程序实现点击按钮修改view标签背景颜色功能示例【附demo源码下载】

    本文实例讲述了微信小程序实现点击按钮修改view标签背景颜色功能.分享给大家供大家参考,具体如下: 1.效果展示 2.操作步骤: ① 数据绑定view样式背景属性值 ② 通过逻辑文件设置该背景属性初始值 ③ 通过点击按钮修改背景属性值 3.关键代码 index.wxml文件: <view style="background:{{viewBg}};color:white;height:100px;">我是view标签</view> <button type=

  • js实现密码强度检测【附示例】

    这篇文章主要介绍了js实现密码强度检测的相关实例,第一个例子给出了全部代码,可以直接运行,第二个例子只给出了js代码,感兴趣的码农可以自己完成第二个实例. 第一个实例 这段JavaScript代码比较实用,它完成用户注册时判断用户输入密码的强度,分强.弱.中三等级,它可以根据用户输入的密码显示对应的密码强弱等级,方便用户改进输入. 实现代码: <html> <head> <title>JS判断密码强度</title> <script language=

  • 微信小程序实现点击按钮移动view标签的位置功能示例【附demo源码下载】

    本文实例讲述了微信小程序实现点击按钮移动view标签的位置功能.分享给大家供大家参考,具体如下: 1.效果展示 2.关键代码 index.wxml文件 <view class="view" style="left:{{viewLeft}}px;">我是view标签</view> <button class="btn" type="default" bindtap="changeLocat

  • SpringBoot SSO轻松实现(附demo)

    前言 网上SSO的框架很多,此篇文章使用的是自写的SSO来实现简单的登录授权功能,目的在于扩展性,权限这方面,自写扩展性会好点. 提示:以下是本篇文章正文内容,下面案例可供参考 一.技术介绍 1.SSO是什么? 单点登录(SingleSignOn,SSO),就是通过用户的一次性鉴别登录.当用户在身份认证服务器上登录一次以后,即可获得访问单点登录系统中其他关联系统和应用软件的权限,同时这种实现是不需要管理员对用户的登录状态或其他信息进行修改的,这意味着在多个应用系统中,用户只需一次登录就可以访问所

随机推荐