AndroidのViewDragHelperを使ってYouTube, SoundCloudのようなアニメーションを実装する!

こんにちは!エンジニアの後藤です。


業務ではGo言語でウェブアプリケーションを作ることに専念しているので、Webエンジニアと化していますが、ネイティブアプリが大好きなので休日はネイティブエンジニアに変化します。


さて、本題に。今回は、Androidに焦点を当てて、リッチなドラッグを作成するポイントを紹介します。YouTubeやSoundCloudで使われているアニメーションと言えば想像がつくでしょうか。


YouTube, SoundCloudのようなドラッグを実装する

実は既にライブラリが複数存在しているので、それらを使用するのが一番です。


YouTubeのような動きは DraggablePanel

SoundCloudのような動きは AndroidSlidingUpPanel


をそれぞれ使えば良いです。


今回はこれらのライブラリが共通して使用している ViewDragHelper というクラスの理解を深めたいと思います。これを使えばどんなドラッグもお手の物です。かっこいいカスタムView作りまくりましょう!

ViewDragHeleperとは

カスタマイズされたViewGroupクラスのためのUtilityクラスです。
ViewGroupの子Viewのドラッグや位置状態をトラッキングするための便利なメソッドが複数用意されています。


以下のようなアニメーションを簡単に実装できます。

drager-sample2


さっそくですが、ViewDragHelperの使い方を解説していきます!


ViewDragHelperのインスタンスを作成する

まずは ViewGroup を継承したクラスを用意します。

public class HogeLayout extends ViewGroup {
  ...
}
```


次に ViewDragHelperのインスタンスを作成するために ViewDragHelper.create メソッドを呼び出します。


ViewDragHelper.createメソッドの引数について解説しておきます。


第1引数には ViewGroupを継承したクラスが入ります。
第2引数には ドラッグ検知の感度合を示すfloat型の値が入ります。(AndroidのDocumentではsensitivityと呼ばれています)
第3引数には ViewDragHelper.Callbackクラスが入ります。これについては後ほど紹介します。

private static final float SENSITIVITY = 1.0f;

private ViewDragHelper viewDragHelper;

private void setupViewDragHelper() {
    viewDragHelper = ViewDragHelper.create(HogeLayout.this, SENSITIVITY, new ViewDragHelper.Callback() {
        @Override
        public boolean tryCaptureView(View child, int pointerId) {
            return false;
        }
    });
}

ViewGroup継承クラスの onInterceptTouchEventonTouchEvent メソッドをオーバーライドする

TouchEventをViewDragHelperに譲渡してあげます。

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
	final int action = event.getActionMasked();
    switch (action) {
        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP:
            viewDragHelper.cancel();
            return false;
        default:
            break;
    }
    return viewDragHelper.shouldInterceptTouchEvent(event);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    viewDragHelper.processTouchEvent(event);
    return true;
}

以上でViewDragHelperを使う準備は完了です!続いて Callback について解説していきます!

ViewDragHelper.Callbackについて

Callbackクラスは tryCaptureView メソッドを必ずオーバーライドしなければなりません。
このメソッドでドラッグしたいViewとドラッグしたくないViewを切り分けることできます。

new ViewDragHelper.Callback() {

    @Override
    public boolean tryCaptureView(View child, int pointerId) {
       return draggableView == child; // or unDraggableView != child
    }

    @Override
    public void onViewCaptured(View capturedChild, int activePointerId) {
     // tryCaptureViewでtrueが返った場合はonViewCapturedメソッドが呼ばれます。  
    }
}

ドラッグする

clampViewPositionVertical, clampViewPositionHorizontal メソッドをオーバーライドします。
ここで返された値がドラッグしているViewのY位置になります。

@Override
public int clampViewPositionVertical(View child, int top, int dy) {
   return top;
}

ドラッグ可能な範囲を決める

getViewVerticalDragRange, getViewHorizontalDragRange メソッドをオーバーライドします。ここで返された値がドラッグ可能な範囲になります。0を返すとViewをドラッグ不可能になります。

@Override
public int getViewVerticalDragRange(View child) {
    return draggableRange;
}


drager-sample1

Viewの位置を受け取る

Viewの位置が変更された場合は onViewPositionChanged メソッドが呼ばれます。

引数の dx, dy とは前の位置から移動した距離です。

@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
}

さいごに

ViewDragHelperには沢山のAPIが存在しますが、今回解説したポイントを押さえておけば、YouTube, SoundCloudのようなドラッグを実現することが出来ます。

サポートライブラリで提供されている SlidingPaneLayout にも使用されているのでそちらも参考に!


今回使ったコードのサンプルはGithubに置いてあります。


drager-sample3


参考URL

http://developer.android.com/reference/android/support/v4/widget/ViewDragHelper.html

http://developer.android.com/reference/android/support/v4/widget/ViewDragHelper.Callback.html

https://android.googlesource.com/platform/frameworks/support/+/master/v4/java/android/support/v4/widget/ViewDragHelper.java

https://android.googlesource.com/platform/frameworks/support/+/master/v4/java/android/support/v4/widget/SlidingPaneLayout.java

  • このエントリーをはてなブックマークに追加

エウレカでは、一緒に働いていただける方を絶賛募集中です。募集中の職種はこちらからご確認ください!皆様のエントリーをお待ちしております!

Recommend

レイティングアルゴリズム入門

Go言語製WAF GinでWebアプリを作ってみる【準備編】