『Android Tip』--ジェスチャー操作をシミュレート

9160 ワード

普段Android開発中に奇抜な機能やニーズに遭遇することが多いので、ここで記録して蓄積し、後で開発中に類似の問題が発生し、迅速に解決できるようにします.Android tips
前言
このバージョンはいよいよ終了し、1ヶ月をかけて開発・探検BUG和解BUGという作業を繰り返していて、人はもうしびれてしまいましたが、最後に自分の開発成果を見て嬉しいです.これがプログラマーの最も簡単な楽しみかもしれません.ここで全体の効果図を見てみると、細部が展示しにくいので、プレビューがあるのではないでしょうか.
シャドウやステータスバーの色、プルダウン・リフレッシュ、tab浮上、TCP更新、データ・キャッシュなど、細かい知識点がたくさん入っていたり、奇抜なBUG透明テーマのActivityDialogの展示、FragmentsetUserVisibleHint予定通りに実行されていないなど、とにかく今回のバージョン以降、自分で書くUIという能力が向上した気がします.
今日はバージョン全体の非常に小さな詳細な処理を紹介し、この機能を少し拡張しました.
概要
本題に入ると、インタフェース全体が共通のドロップダウンリフレッシュコントロール+designライブラリCoordinatorLayoutで実現されます.では、ここには小さなニーズがあります.効果を見てみましょう.
説明:青い領域をクリックして、資金ページを展開し、インタフェース全体を初期位置にスライドさせます.
機能は簡単ですが、実現の過程で、私の外層がスライドしているViewそうではないRecyclerViedwあるいはListViewあるいはScrollViewということがわかりましたので、対応するインタフェースはありませんsmoothScrollToPosition()、呼び出しに供します.自分で何とかしてこの効果を実現するしかない.
第一:研究CoordinatorLayoutソースコード、彼のスライドメカニズムを理解することは、私にとって少し難しいし、需要の見積り時間も許されない.
第二に、スライドが人為的にトリガされた以上、指のスライドイベントをシミュレートし、親Viewスライドイベントを発行させ、子Viewこのイベントを受信させ、処理させる.
インプリメンテーション
実現の構想が見つかった以上、実現に着手しましょう.その前に事件の配布メカニズムをある程度理解する必要があります.ほとんどのパートナーはよく知っていると思いますが、あまり接触していない人もいるかもしれません.では、大まかな紹介をして、後文に敷き詰めます.
イベント配信
事件の本質、操作の対象、伝達の過程を理解すれば、頭の中には基本的な概念がある.
イベントとは?
画面に触れるとイベントが発生しますAndroidシステムはそれをMotionEventにカプセル化します.
type
desc
MotionEvent.ACTION_DOWN
スクリーンを押す
MotionEvent.ACTION_UP
画面から移動
MotionEvent.ACTION_MOVE
画面をスライド
MotionEvent.ACTION_CANCEL
キャンセル
事件はどこで伝わりますか.
type
desc
Activity
イベントの開始点
ViewGroup
上層部のイベントの受信、処理、または送信を担当する
MotionEvent.ACTION_MOVE
上層部のイベントの受信と処理を担当する
イベントの伝達方向は何ですか?Acitivity->ViewGroup->View一次伝達から、最終的には処理または最上位に戻される.
イベントの転送をどのように制御しますか?
主に3つの方法で決定されます.
type
desc
dispatchTouchEvent()
イベントの配布を担当
onInterceptTouchEvent()
事件を阻止する責任を負う.
onTouchEvent()
事件の処理を受け持つ
イベント転送の流れは何ですか?
上図はイベント配布メカニズムの詳細に由来し、特に感謝します.
全体の流れはこのようにして、紙面の重点がここにないため、多く述べないで、私が書いたのは少し粗雑かもしれませんが、詳しい紹介を見たいなら、上の事件の配布メカニズムの詳しい文章をお勧めします.
やる
事件の配布について大まかに知っている以上、これからはやりやすいので、これを直接構築してMotionEventそれからView処理させたり、Activity下向きに配布させたりすることができます.
アナログクリック
まず簡単なことから、ジェスチャーのクリック操作をシミュレートします.クリック操作は、1つDownUpを組み合わせたものです.
MotionEvent downEvent = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, x, y, 0);
        MotionEvent upEvent = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, x, y, 0);
//       ,           。
if (object instanceof View) {
    ((View) object).onTouchEvent(downEvent);
    ((View) object).onTouchEvent(upEvent);
    } else if (object instanceof Activity) {
    ((Activity) object).dispatchTouchEvent(downEvent);
    ((Activity) object).dispatchTouchEvent(upEvent);
}
//        
downEvent.recycle();
upEvent.recycle();

こちらは静的メソッドにカプセル化されており、直接呼び出せばいいです.
public static void simulateClick(View view, float x, float y) {
        dealSimulateClick(view, x, y);
}
public static void simulateClick(Activity activity, float x, float y) {
    dealSimulateClick(activity, x, y);
}
Demoの運転効果を見てみましょう.
シミュレーションスライド
そのスライドが1つDown、1つUpと複数Moveイベントからなり、1つのスライドの遅延効果を追加するためにHandlerを用いて完成する.
Handler handler;
if (object instanceof View) {
    View view = (View) object;
    handler = new ViewHandler(view);
    view.onTouchEvent(MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN, startX, startY, 0));
    GestureBean bean = new GestureBean(startX, startY, endX, endY, duration, period);
    Message.obtain(handler, 1, bean).sendToTarget();
} else if (object instanceof Activity) {
    Activity activity = (Activity) object;
    handler = new ActivityHandler(activity);
    activity.dispatchTouchEvent(MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN, startX, startY, 0));
    GestureBean bean = new GestureBean(startX, startY, endX, endY, duration, period);
    Message.obtain(handler, 1, bean).sendToTarget();
}
Handlerで次々と送信Moveイベントを行い、指のスライドをシミュレートする効果を達成します.
static class ActivityHandler extends Handler {
    WeakReference mActivity;

    ActivityHandler(Activity activity) {
        super(Looper.getMainLooper());
        mActivity = new WeakReference<>(activity);
    }

    @Override
    public void handleMessage(Message msg) {
        Activity theActivity = mActivity.get();
        if (theActivity == null || theActivity.isFinishing()) {
            return;
        }
        long downTime = SystemClock.uptimeMillis();
        GestureBean bean = (GestureBean) msg.obj;
        long count = bean.count;
        if (count % 10 == 0) {
            Log.i(TAG, "handleMessage: " + count);
        }
        if (count >= bean.totalCount) {
            theActivity.dispatchTouchEvent(MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_UP, bean.endX, bean.endY, 0));
        } else {
            theActivity.dispatchTouchEvent(MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_MOVE, bean.startX + bean.ratioX * count, bean.startY + bean.ratioY * count, 0));
            bean.count++;
            Message message = new Message();
            message.obj = bean;
            sendMessageDelayed(message, bean.period);
        }
    }
}

静的メソッドもカプセル化して使用しました.
    /**
     *       
     *
     * @param activity     activity
     * @param startX        x
     * @param startY        y
     * @param endX          x
     * @param endY          y
     * @param duration         ms
     * @param period       
     *                 {@link #LOW}  
     *                 {@link #NORMAL}   
     *                 {@link #HIGH}  
     */
    public static void simulateScroll(Activity activity, float startX, float startY, float endX, float endY, long duration, int period) {
        dealSimulateScroll(activity, startX, startY, endX, endY, duration, period);
    }
Demoの運転効果を見てみましょう.
ジェスチャーをシミュレートして⭐10.、具体的なソースコードはGithubScrollDemoにアップロードしました.
まとめ
非常に小さなニーズの実現の細部から多くの知識点を広げることができ、このバージョンは多くのことを学んだと言わざるを得ません.今回の共有はあなたを助けることができるかもしれません.