UWP忽略短时间内重复触发的事件
做移动端开发的可能都会遇到这种需求,当用户点击一个按钮之后,由于没有异步,或者设备性能很差等等原因,程序卡住了。但是用户不知道是咋回事啊,就开始狂点按钮,结果请求很多次资源,或者构造了很多重复视图。安卓上有很多介绍如何忽略重复点击的情况,uwp里我好像还没找到,那接下来就说一说我的方法吧。
首先是官方最常用的,从Windows诞生之初用到现在的,点击按钮之后把他Disable掉,等完成了在Enable。其实这算是最好的选择了,但是总归是麻烦了一些,尤其是在MVVM的时候,每个Button都要单独绑定一个IsEnabled,所以接下来就仿照安卓上的通用处理方法试一下。
首先创建一个类,我们就叫他EventWaiter吧,里面维护一个LastTime,一个IsEnabled,事件可以判断这个IsEnabled来知道,上一次点击和这一次点击的间隔是不是过短,从而决定是否要执行。
public class EventWaiter
{
private DateTime _lastTime;
public EventWaiter(double seconds)
{
Interval = TimeSpan.FromSeconds(seconds);
}
public EventWaiter(TimeSpan interval)
{
Interval = interval;
}
public EventWaiter()
{
Interval = TimeSpan.FromSeconds(0.1d);
}
//间隔
public TimeSpan Interval { get; set; }
public bool IsEnabled
{
get
{
if(DateTime.Now - _lastTime > Interval)
{
_lastTime = DateTime.Now;
return true;
}
return false;
}
}
public void Reset()
{
_lastTime = DateTime.Now;
}
}
大概用法是这样的:
var waiter = new EventWaiter();
var button = new Button();
button.Click += OnClick;
private void OnClick(object sender,RoutedEventArgs e)
{
if(waiter.IsEnabled)
{
//do something
}
}
接下来就是第三种需求了。对于安卓iOS来说,很少有SizeChanged,但是UWP不一样啊,UWP能窗口运行啊,所以在一些要响应SizeChanged,在窗口大小改变的时候做一些很重操作的时候,拖拽窗口就会变得非常卡,所以我现在想忽略拖动窗口的中间过程,只让他响应最后状态。而上面的EventWaiter,是一段时间内只响应第一次事件的触发,和我们的需求是完全反着的。
这时候就要请救星:DispatcherTimer出来了(感谢小竹)。
大致思路呢,按时间顺序叙述,是当原事件触发时,让Timer开始运行;第二次触发事件时判断Timer是否运行,如果正在运行呢,就停掉重新启动,相当于重置了计时器;等Timer第一次跑完,执行Tick的时候停掉Timer,并且激活内部的事件去做真正的操作。
我们再弄个新的类,起个名字叫EventDelayer(原谅我起名困难),里面需要维护一个DispatcherTimer,还要一个事件Arrived负责在最后被触发,和一个Delay()方法,负责进入触发判断。
public class EventDelayer
{
private DispatcherTimer _timer;
public EventDelayer(double seconds) : this(TimeSpan.FromSeconds(seconds))
{
}
public EventDelayer(TimeSpan interval)
{
_timer = new DispatcherTimer();
_timer.Tick += _timer_Tick;
Interval = interval;
}
public EventDelayer() : this(0.1)
{
}
public TimeSpan Interval
{
get => _timer.Interval;
set => _timer.Interval = value;
}
public bool ResetWhenDelayed { get; set; }
public void Delay()
{
if (!_timer.IsEnabled)
{
_timer.Start();
}
else
{
if (ResetWhenDelayed)
{
_timer.Stop();
_timer.Start();
}
}
}
private void _timer_Tick(object sender, object e)
{
if (_timer.IsEnabled)
{
_timer.Stop();
}
OnArrived();
}
public event EventHandler Arrived;
protected void OnArrived()
{
Arrived?.Invoke(this, EventArgs.Empty);
}
}
用法大概是这个样子:
var delayer = new EventDelayer();
delayer.Arrived += OnArrived;
this.SizeChanged += OnSizeChanged;
private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
delayer.Delay();
}
private void OnArrived(object sender,EventArgs args)
{
//do something
}
炒鸡完美。github:https://github.com/cnbluefire/ReaderView/tree/master/ReaderView/Common/Helpers
UWP忽略短时间内重复触发的事件的更多相关文章
- EasyUI中combotree允许多选的时候onSelect事件会重复触发onCheck事件
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgEAAADkCAIAAACOkmAuAAAgAElEQVR4nO2dW2wc15nnO0EQBJsdzA
- javascript避免dom事件重复触发
/** * 为指定控件添加限制性事件, 该事件在触发之后, 会被移除, 并在指定的时间间隔后, 重新绑定, 适用于避免控件事件被误操作重复触发的场景 * @param {String} domID 要 ...
- jQuery 防止相同的事件快速重复触发
重复触发就是防止用户重复点击提交数据了,我们一般都是点击之后没反应会再次点击了,这个不但要从用户体验上来做好,还在要js或php程序脚本上做好,让用户知道点击是己提交服务器正在处理,下面我就整理从脚本 ...
- echarts 图的点击事件(含:点击重复触发的问题及其解决方法)
今天用echarts的时候发现一个问题 鼠标指向不同地市触发一个事件展示该地区趋势图 但是但是后台中不管我第几次鼠标指向都会触发两次指向事件 现在贴出解决办法: 问题完美解决.但是为什么会调用两次, ...
- 实现textbox文本页面改变触发textchanged事件,代码里修改不触发
今天弄控件遇到一个问题,就是TextChanged,如果在代码里或在页面修改修改text值,就会触发事情,但如果在textchanged里修改text,它会不会触发呢,不会,我调试跟踪,并没发现它会重 ...
- Echarts如何添加鼠标点击事件?防止重复触发点击事件
Echarts如何添加鼠标点击事件? 1.通常我们只使用了以下代码,通过配置项和数据显示图表. var myChart = echarts.init(document.getElementById(' ...
- 关于Android避免按钮重复点击事件
最近测试人员测试我们的APP的时候,喜欢快速点击某个按钮,出现一个页面出现多次,测试人员能不能禁止这样.我自己点击了几下,确实存在这个问题,也感觉用户体验不太好.于是乎后来我搜了下加一个方法放在我们U ...
- C# Winform 拦截关闭按钮触发的事件
用户关闭软件时,软件一般会给“是否确认关闭”的提示. 通常,我们把它写在FormClosing 事件中,如果确定关闭,就关闭:否则把FormClosingEventArgs 的 Cancel 属性设置 ...
- GridView点击行触发SelectedIndexChanged事件
1.在<% @Page ...... %>指令中添加 EnableEventValidation="false" 2.在RowDataBound事件中添加 protec ...
随机推荐
- 调整iframe滚动条失效
1:<iframe scrolling="auto" frameborder="0" src="' + add + '" style= ...
- JSX
有一个 Babel 插件,用于在 Vue 中使用 JSX 语法,它可以让我们回到更接近于模板的语法上.JSX语法返回一个vnode对象 import AnchoredHeading from './A ...
- python 爬虫启航
1. 使用excel(简单使用) 数据- 自网站-导入 2.you-get python爬虫入门 1.环境配置 python,request,lxml 2.原理 爬虫的框架如下: 1.挑选种子URL: ...
- vuejs如何在服务器部署
title: vuejs如何在服务器部署 date: 2017-10-31 20:41:03 tags: [vue] --- 上传到网站服务器 Vue 是一个 javascript 的前端框架,它是运 ...
- docker mysql Exit 1
用laradock启动mysql时,state总是 Exit 1 ,docker-compose build后也没有效果 这时应该在-/.laradock/data(.env的DATA_PATH_HO ...
- Mesh属性[Unity]
Mesh属性[Unity] Mesh是Unity内的一个组件,称为网格组件.3D网格是Unity中最重要的图形元素.在Unity中存在多种组件用于渲染标准网格或者蒙皮网格.拖尾或者3D线条. 在Uni ...
- H5地理位置信息、微信摇一摇
geolocation window.navigator.geolocation 1.getCurrentPosition() // 获取当前的位置信息 2.watchPosition() // 监视 ...
- aio,nio ,io 心得
1.nio 流的过程有几个,连接,可读,读 ,返回 :连接了不一定可读,等待浪费时间,这些时间可以去读其他的连接,selector是管理,管理全部测一下可不可读,只对可读的连接进行读取.同时,nio有 ...
- C#//字节数组转16进制字符串
//字节数组转16进制字符串 private static string byteToHexStr(byte[] bytes,int length) { string returnStr = &quo ...
- ie7ajax 跨域 no transport 解决办法
客户端js <script src="jquery-1.8.0.min.js"></script> <script src="JavaScr ...