ons-carouselのインデックス初期化バグ対策

  • 3
    Like
  • 2
    Comment

この記事は、Onsen UI Advent Calendar 2016 の14日目の記事として作成しました。

※このバグはOnsen UI 2.0.5以降で修正されています
※Angular2バインディングではまだ起こるようです(https://github.com/OnsenUI/OnsenUI/issues/1815)

はじめに

#1565は2.0.1で修正すると言ったな」
「そ、そうだ、アシアルさんっ...早く直しt...」
「あれは嘘だ」
「ウウウアァアアアア!」

以前取り上げたons-carouselのバグの改修は進んでいないようです。

しかし、アプリは作らねばならない。

動作環境

  • OnsenUI 2.0.4
  • AngularJS 1.5.9
  • Android 5.1.1
  • iOS 10.1

問題

ons-carouselを使用する際、

  • ons-carouselをスワイプしてカルーセルの現在位置を変える
  • pushPage()で別のページに遷移
  • 遷移後のページでAndroidならキーボード表示、iOSなら画面を横に傾ける
  • popPage()で遷移前のページに戻る

と操作すると、カルーセルの位置が初期値(index=0)に戻ってしまいます。

解決方法

まず、postchangeイベントが発生したらカルーセルの表示位置を保存します。
インデックス初期化バグはページ遷移後に発生するので、それ用のフラグpagePushedを準備します。

main.controller.js
vm.carousel.on('postchange', function(event) {
    if (pagePushed) {
        needFix = true; // バグ発生を検知
    } else {
        lastIndex = event.activeIndex;
    }
});

ページ遷移後、カルーセルが表示されていないにも関わらずpostchangeイベントが発火した場合は「バグが発生した」とみなします。

次にページ遷移の実行部分の処理です。

main.controller.js
var options = {
    prePop: checkCarouselBug,
};
navi.pushPage('detail.html').then(function() {
    pagePushed = true;
});;

バグ発生時にカルーセルの位置を戻す動作をpushPage()の引数として渡すと、遷移先のページで呼び出すことが可能です。

main.controller.js
function checkCarouselBug() {
    pagePushed = false;
    if (needFix) {
        needFix = false;
        $timeout(function() {
            vm.carousel.setActiveIndex(lastIndex); // 復元
        });
    }
}

最後に、遷移後のページでpopPage()の直前にバグチェックを実行します。

detail.controller.js
function back() {
    var options = {};
    args.prePop(); // バグチェック&インデックス復元
    navi.popPage(options);
}

これでOK!

おわりに

ページ毎にインデックス復元を実行しないといけなくなるので、あまり良い方法とは言えませんが、とりあえず現状はこれで対応可能です。

今回の修正の内容は以下で確認可能です。
http://codepen.io/puku0x/pen/WogwRg

※ 遷移後ページの戻るボタンの表示が崩れていますがv2.0.4の不具合のようです