最近我们有一个应用程序项目,其中长按是完美的UX交互。
事实证明,在ionic4中实现并不像在原生环境中那样简单。但其他的都是,所以我们继续往下看。
这里的事件与angular提供的标准(单击)事件绑定是一样的,但是对于长时间的按压,会有两个动作(press)和(pressup)。可以尝试直接添加这些事件,但是会出现到以下问题:“press”事件无法绑定,因为没有加载Hammer.JS,也没有指定自定义加载器。
设置
在处理事件之前,我们需要做一些配置。
安装HammerJs
通过npm: npm install HammerJS - save
将HammerJS添加到整个项目中。
接下来,直接在src/main.ts
中导入代码库,将其添加到代码库中:
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
import "hammerjs"; // HAMMER TIME
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.log(err));
设置Hammer手势配置
现在应该能够在我们的应用程序中访问Hammer指令,但是当Ionic 4处于测试阶段时
,我们遇到了一些问题并发现解决方案是通过扩展它来创建我们自己的HammerGestureConfig,所以为了方便,我们在下面添加了以下内容:
import { Injectable } from "@angular/core";
import { HammerGestureConfig } from "@angular/platform-browser";
/**
* @hidden
* This class overrides the default Angular gesture config.
*/
@Injectable()
export class IonicGestureConfig extends HammerGestureConfig {
buildHammer(element: HTMLElement) {
const mc = new (window).Hammer(element);
for (const eventName in this.overrides) {
if (eventName) {
mc.get(eventName).set(this.overrides[eventName]);
}
}
return mc;
}
}
添加到App Providers
添加了HammerJS并定义了自定义的HammerGestureConfig,我们希望将它添加到我们的Angular提供程序中 app.module.ts
@NgModule({
declarations: [AppComponent],
entryComponents: [],
imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule],
providers: [
StatusBar,
SplashScreen,
{provide: RouteReuseStrategy, useClass: IonicRouteStrategy},
{
provide: HAMMER_GESTURE_CONFIG,
useClass: IonicGestureConfig
},
],
bootstrap: [AppComponent]
})
现在设置已经完成,我们现在可以玩这些事件了。
为了这个演示,我将使用一个ion-button
,但你可以使用你想要的任何HTML元素。
添加事件绑定
因此,继续在元素上添加 press
和 pressup
事件绑定,并将它们指向控制器上的相应功能:
<--Template Segment-->
Press Me
// Controller Functions
onPress($event) {
console.log("onPress", $event);
}
onPressUp($event) {
console.log("onPressUp", $event);
}
如果已正确设置它,将在控制台中看到事件触发。onPress将在长按约1秒后触发,并且在释放onPressUp事件后将触发。
接下来要做什么
好吧,鉴于这种用户体验互动可以用于大量不同的事情,我不会告诉你为什么需要它,但是,这个演示的一个很好的用例(我认为)将创建一个进度计数器,同时按钮被按下。
演示:长按以增加计数器
首先,我已经在Github上添加了这个演示的源代码,所以请随意使用它作为参考。
不要忘记:事件绑定只需要一次!
它可能感觉违反直觉,但是尽管按住了按钮,实际的按下事件只被触发一次,因此如果我们希望计数器不断增加直到按钮被释放,我们必须找到一种方法来调用增量函数。在本演示中,我将使用一个简单的setTimeout函数来执行此操作。
管理超时间隔
import {Component} from '@angular/core';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
public progress: number = 0;
// Interval function
protected interval: any;
onPress($event) {
console.log("onPress", $event);
this.startInterval();
}
onPressUp($event) {
console.log("onPressUp", $event);
this.stopInterval();
}
startInterval() {
const self = this;
this.interval = setInterval(function () {
self.progress = self.progress + 1;
}, 50);
}
stopInterval() {
clearInterval(this.interval);
}
}
所以我会尝试分解这里发生的事情。在标记中观察到(press)事件绑定时,将运行onPress($ event)方法。此方法调用startInterval函数,该函数创建一个间隔函数,该函数设置为每50毫秒重新运行一次,并将函数绑定到局部变量,以便以后可以清除(停止)它。注意重新声明this
为另一个局部变量self
。不要忘记 javascript中[this](https://quirksmode.org/js/this.html)
关键字的重要性以及它的上下文如何变化!
因此,现在间隔已启动并运行,您将看到进度变量每50毫秒递增1。现在当用户将手指从按钮上抬起时,会触发(press)事件绑定,在我们的示例中清除了初始按下事件创建的间隔,因此计数器停止递增...魔法!
重用和可扩展性
你可能会注意到的一件事是,如果你想在页面上有多个按钮,那么就会有大量的代码重复。在这种情况下,聪明的做法是将所有的逻辑逻辑移动到自己的组件中,并使其自包含且可重用。但那是另外的事!
源代码
不要忘记,这个演示的源代码可以在https://github.com/pjhartin/ionic4-long-press-demo上找到