新しいビューのプッシュをトリガーするボタンがあるとします。何度もクリックすると、十分に速く、同じビューが 2 回プッシュされることに気付きました。
ライブサンプルがあるこのページの公式ドキュメントを使用して、この動作を模倣できます: http://docs.sencha.com/touch/2-0/#!/guide/navigation_view
明確な問題は、単にそれを防ぐ方法ですか?
新しいビューのプッシュをトリガーするボタンがあるとします。何度もクリックすると、十分に速く、同じビューが 2 回プッシュされることに気付きました。
ライブサンプルがあるこのページの公式ドキュメントを使用して、この動作を模倣できます: http://docs.sencha.com/touch/2-0/#!/guide/navigation_view
明確な問題は、単にそれを防ぐ方法ですか?
もう 1 つの方法は、アクティブなビューが何であるかを確認し、プッシュしようとしているビューと同じでない場合にのみプッシュすることです。私はこれをテストしましたが、動作します。
例えば
if (this.getNavigationView().getActiveItem().xtype != "someView") {
this.getNavigationView().push({ xtype: "someView" });
}
jayteejee の回答を拡張して、次のようにカスタム ナビゲーション ビューで push メソッドをオーバーライドしました。
Ext.define('BT.navigation.View', {
extend: 'Ext.navigation.View',
xtype: 'btnavigationview',
push: function (view) {
if(this.getActiveItem().xtype != view.xtype)
this.callParent(arguments);
else
console.warn("Prevented pushing a potentially duplicate view of xtype: " + view.xtype);
}
});
仮定が十分に安全かどうかは完全にはわかりませんxtype
が、現在のアプリで、あるビューが同じタイプの別のビューをナビゲーション スタックにプッシュする必要がある状況は考えられません。だから、解決策は私にとってはうまくいきます、そしてそれはかなりきれいです。push
警告は、後で頭痛がするのを防ぐためにあります。なぜうまくいかないのかを解決しようとして髪を引っ張る可能性があります。
マスキングにより、ダブルタップの問題を防ぐことができます。
私のコードでは、ナビゲーション コンテナーのマスク/マスク解除に 2 つの関数を使用しています。
/**
* Mask container with rolling wheel. Usually need if Ajax-request is sent to the server and app waiting for response
* Best practice is masking the current navigator container, to prevent blocking whole app. Method warns if no container
* is defined. In some cases warning could be suppress with parameter
*
* @param container
* @param {boolean} [suppressWarning]
*/
startLoading: function(container, suppressWarning) {
var loadingComponent = container;
if (!loadingComponent) {
// <debug>
if (!suppressWarning) {
console.warn('Please define navigator container for non-blocking operation, or define suppressWarning parameter');
}
// </debug>
loadingComponent = Ext.Viewport;
}
// var lastMaskedContainer = container;
this.lastMaskedContainer = container;
loadingComponent.setMasked({
xtype: 'loadmask',
message: 'Loading...'
});
/*
Ext.defer(function() {
lastMaskedContainer.setMasked(false);
}, Pipedrive.app.maskingTimeout * 1000)
*/
},
/**
*
* @param {Ext.Container} container
* @param {boolean} [suppressWarning]
*/
stopLoading: function(container, suppressWarning) {
var loadingComponent = container;
if (!loadingComponent) {
// <debug>
if (!suppressWarning) {
console.warn('Please define either navigator container for non-blocking operation, or define suppressWarning parameter');
}
// </debug>
loadingComponent = Ext.Viewport;
}
var alreadyMasked = loadingComponent.getMasked();
var lastMaskedContainer = this.lastMaskedContainer;
if (!alreadyMasked && !suppressWarning) {
// <debug>
if (lastMaskedContainer != container) {
console.warn('Found Start/Stop Loading inconsistency. Please revise code'
+ (container ? '. Container: ' + container.getId() : 'Ext.Viewport')
+ (lastMaskedContainer ? ', last masked container: ' + lastMaskedContainer.getId() : '')
);
}
// </debug>
loadingComponent = Ext.Viewport;
}
loadingComponent.setMasked(false);
}
タップハンドラーよりも:
onDealDetailsTap: function(ct) {
console.log('onDealDetailsTap', ct);
var form = ct.getReferenceForm(),
navigatorContainer = this.getNavigatorContainer(form),
model = form.getRecord();
UiHelper.startLoading(navigatorContainer);
Ext.Viewport.fireEvent('detailfields', {
title: model.get('title'),
id: model.get('id'),
store: 'DealFields',
navigatorContainer: navigatorContainer
})
},
ローディングマスクをクリーンアップするには:
control : {
activitiesContainer: {
push: 'onPushActivitiesContainer'
},
onPushActivitiesContainer: function(ct) {
//console.log('onPushActivitiesContainer', ct);
UiHelper.stopLoading(ct);
},
特に、長時間の ajax リクエストを待つのはクールです....
乾杯、オレグ
ボタンがタップされたときにイベントを一時停止し、ビューが押されたときにイベントを再開するだけです
button.suspendEvents();
...
button.resumeEvents();
他の方法はないと思います。開発者またはユーザーとして、ボタンを 2 回タップすると、イベント ハンドラーが 2 回呼び出されることが予想されます。
お役に立てれば
コンテナ全体をマスクしてからマスクを解除するだけです。コントローラーとタップセットにボタンが存在するコンテナーまたはパネルの参照を作成します。
ref.setMasked(true)
新しいビューがプッシュされた後、単純にマスクを解除します
ref.setMasked(false)
これを確認するためのメソッドを作成しました:
ENSURE_NO_DOUBLE_TAP : function(classNameToPush) {
if (Ext.getClassName(Ext.getCmp('MyViewport').getActiveItem()) == classNameToPush) {
return false;
}
return true;
}
次に、ダブルタップされる可能性のあるものが処理される前に、アプリから:
if (!ENSURE_NO_DOUBLE_TAP('MyApp.view.View')) {
return;
}
もう 1 つの方法は、次のように、リスト項目が 1 回タップされるとパラメーターを反転することです。
{
onListItemTap: function () {
if (!this.tapped) {
this.tapped = true;
...
}
}
}
もちろん、これは、ユーザーが別の画面に移動するとすぐにリスト ビューを破棄している場合にのみ機能します。
リスナーを使用してボタンのタップイベントをリッスンしている場合、私の解決策は次のとおりです。
listeners : {
release : function(){
if(this.getDisabled())return false;
this.setDisabled(true);
this.fireEvent('tap');
},
tap : function() {
//do what you want
}
}
「itemsingletap」イベントを使用するだけです。
ダブルタップもサポートしたい場合は、「itemdoubletap」の 2 つ目のリスナーを作成し、同じ関数を呼び出すと、両方のリスナーが連携して正常に動作します。