タブレット用プログラムの書き止め

android OS & iPadOS の記録。

[余談] View.OnClickListener の例外発生。

2022-10-14 13:02:06 | Android studio 日記

クリックリスナー設定で遅延実行を使っていてViewをダブルタップすると例外発生する。

        mButtonClick = v -> {

            touchAction( v );
            mHandler.postDelayed(() -> {
                test(v.getId());
            }, 500);
        };

遅延の待ち時間にまたクリックイベントで同じところに入って来るため。
対応はフラグを立て2度目をスルーさせる。

    boolean clickFlag = false;

省略
        mButtonClick = v -> {
            if (clickFlag) return; // フラグがセットされていたら戻る
            clickFlag = true; // フラグをセット

            touchAction( v );
            mHandler.postDelayed(() -> {
                clickFlag = false; // 遅延実行が始まったらフラグをリセット
                test(v.getId());
            }, 500);
        };


touchAction( v );はview.OnClickListenerを設定したviewをアニメーションさせるメソッド。(省略)
アニメーションが完了する前に本処理メソッドに移るとアニメーションがぶつ切りになってしまう。
なので遅延実行でアニメーション完了後に本処理に移行する。
(アニメーションはタップされた確認表示。ユーザーに受け付けた意思表示で必要。)


遅延実行とイベント処理は例外処理が必須。

 

 


それとView.Animation。touchAction( v )の書き換え。
今まで何となく形にしてたものを手順通りに組む。
以前の適当の方がプログラム短くてスッキリしてる。
爆弾も残る。ので、安全を担保。

10/15、修正しました。
複数の場所でフラグ操作するのではなく単一メソッド内でスルー判断させ分かり易くするため。

 

省略

    private boolean clickFlag = false; 消去

    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        省略

        mButtonClick = v -> {
            if (clickFlag) return;

            touchAction( v );
        };

        mButton = view.findViewById(R.id.button);
        mButton.setOnClickListener(mButtonClick);
    }

    private final Handler mHandler = new Handler();
    private View mView = null; // 追加

    private void touchAction( View view ) {
        clickFlag = true;

        // 追加。 複数の場所でフラグ操作でなく単一メソッド内でスルー判断させる

        if ( mView == null ) mView = view;
        else if ( mView.getAnimation().hasStarted() ) // アニメーションが始まったらスルーさせる
            return;

        ///////////////

        Animation ActionB = AnimationUtils.loadAnimation( requireContext(), R.anim.scale_down_animation_set); // 小さく
        ActionB.setAnimationListener(new Animation.AnimationListener() { // アニメーション終了通知取得

            @Override
            public void onAnimationStart(Animation animation) { }

            @Override
            public void onAnimationEnd(Animation animation) { // 小さくなり切ったら次の元に戻るアニメーションを動かす

                Animation ActionB = AnimationUtils.loadAnimation( requireContext(), R.anim.scale_up_animation_set); // 大きさを戻す
                ActionB.setAnimationListener(new Animation.AnimationListener() { // アニメーション終了通知取得

                    @Override
                    public void onAnimationStart(Animation animation) { }

                    @Override
                    public void onAnimationEnd(Animation animation) { // 元に戻ったら本体の処理を始める
                        mHandler.post(MyFragment.this::move); // メインスレッドのViewにアクセスするメソッドを呼ぶにはハンドラーを使う
                        clickFlag = false;
                        mView = null;
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) { }
                });
                view.startAnimation( ActionB );
            }

            @Override
            public void onAnimationRepeat(Animation animation) { }
        });
        view.startAnimation(ActionB);
    }

 

やはり、ゴチャゴチャして嫌いだ。

 


過去記事が見つからなかったので追加。
場所は res:anim:scale_down_animation_set.xml

【scale_down_animation_set.xml】

< set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="@android:anim/decelerate_interpolator">

        < scale
            android:fromXScale="1.0"
            android:toXScale="0.7"
            android:fromYScale="1.0"
            android:toYScale="0.7"
            android:pivotX="50%"
            android:pivotY="50%"
            android:fillAfter="true"
            android:duration="150" />

</set>


【scale_up_animation_set.xml】

< set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="@android:anim/decelerate_interpolator">

        < scale
            android:fromXScale="0.7"
            android:toXScale="1.0"
            android:fromYScale="0.7"
            android:toYScale="1.0"
            android:pivotX="50%"
            android:pivotY="50%"
            android:fillAfter="true"
            android:duration="150" />

</set>