AndroidのViewDragHelperを使ってYouTube, SoundCloudのようなアニメーションを実装する!
こんにちは!エンジニアの後藤です。
業務ではGo言語でウェブアプリケーションを作ることに専念しているので、Webエンジニアと化していますが、ネイティブアプリが大好きなので休日はネイティブエンジニアに変化します。
さて、本題に。今回は、Androidに焦点を当てて、リッチなドラッグを作成するポイントを紹介します。YouTubeやSoundCloudで使われているアニメーションと言えば想像がつくでしょうか。
YouTube, SoundCloudのようなドラッグを実装する
実は既にライブラリが複数存在しているので、それらを使用するのが一番です。
YouTubeのような動きは DraggablePanel
SoundCloudのような動きは AndroidSlidingUpPanel
をそれぞれ使えば良いです。
今回はこれらのライブラリが共通して使用している ViewDragHelper
というクラスの理解を深めたいと思います。これを使えばどんなドラッグもお手の物です。かっこいいカスタムView作りまくりましょう!
ViewDragHeleperとは
カスタマイズされたViewGroupクラスのためのUtilityクラスです。
ViewGroupの子Viewのドラッグや位置状態をトラッキングするための便利なメソッドが複数用意されています。
以下のようなアニメーションを簡単に実装できます。
さっそくですが、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継承クラスの onInterceptTouchEvent
と onTouchEvent
メソッドをオーバーライドする
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;
}
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に置いてあります。
参考URL
http://developer.android.com/reference/android/support/v4/widget/ViewDragHelper.html
http://developer.android.com/reference/android/support/v4/widget/ViewDragHelper.Callback.html
エウレカでは、一緒に働いていただける方を絶賛募集中です。募集中の職種はこちらからご確認ください!皆様のエントリーをお待ちしております!
こんにちは!エンジニアの後藤です。
業務ではGo言語でウェブアプリケーションを作ることに専念しているので、Webエンジニアと化していますが、ネイティブアプリが大好きなので休日はネイティブエンジニアに変化します。
さて、本題に。今回は、Androidに焦点を当てて、リッチなドラッグを作成するポイントを紹介します。YouTubeやSoundCloudで使われているアニメーションと言えば想像がつくでしょうか。
YouTube, SoundCloudのようなドラッグを実装する
実は既にライブラリが複数存在しているので、それらを使用するのが一番です。
YouTubeのような動きは DraggablePanel
SoundCloudのような動きは AndroidSlidingUpPanel
をそれぞれ使えば良いです。
今回はこれらのライブラリが共通して使用している ViewDragHelper
というクラスの理解を深めたいと思います。これを使えばどんなドラッグもお手の物です。かっこいいカスタムView作りまくりましょう!
ViewDragHeleperとは
カスタマイズされたViewGroupクラスのためのUtilityクラスです。
ViewGroupの子Viewのドラッグや位置状態をトラッキングするための便利なメソッドが複数用意されています。
以下のようなアニメーションを簡単に実装できます。
さっそくですが、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継承クラスの onInterceptTouchEvent
と onTouchEvent
メソッドをオーバーライドする
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; }
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に置いてあります。
参考URL
http://developer.android.com/reference/android/support/v4/widget/ViewDragHelper.html
http://developer.android.com/reference/android/support/v4/widget/ViewDragHelper.Callback.html
エウレカでは、一緒に働いていただける方を絶賛募集中です。募集中の職種はこちらからご確認ください!皆様のエントリーをお待ちしております!