2019-03-27 potatotips #60 @cattaka_net
僕は上スワイプでBottomSheetを
出したかっただけなんだ
Takao Sumitomo
@cattaka_net
2019-03-27 potatotips #60 @cattaka_net
自己紹介
●
住友 孝郎(Takao Sumitomo)
●
Wantedly, Inc. 所属
●
Androidアプリを主に担当
●
@cattaka_net
Goは書かないけどゴーファーが好き
(アイコンは気分で変わる)
2019-03-27 potatotips #60 @cattaka_net
2019-03-27 potatotips #60 @cattaka_net
本題
2019-03-27 potatotips #60 @cattaka_net
BottomSheetはご存知ですよね
下から出てくるやつ
●
BottomSheetDialogが有名
●
例)Material Design
●
by Eajy
●
https://goo.gl/YrChM4
これを上スワイプで出るようにしたかった
こんなのが作りたかった→
処理の本体はBottomSheetBehavior
←親のCoordinatorLayout
←子要素のView
1:Nested Scrollが親に伝わる
2:イベントをリレー
BottomSheetBehavior
3:子要素のViewの座標を動かす
アプローチ
アプローチ
←ここのスクロールイベントを奪う
BottomSheetBehavior
奪ったイベント
どちらかにリレー
スクロール量の奪い方
親のViewにOnTouchListenerを仕込んで頑張る?
●
独自実装したくない...
●
別件でロングタップも使いたい
●
スクロール開始の閾値とかやりたくない
←この部分に仕込む
強引にNestedScrollする?
見た目上はBottomSheetの後ろにあるけど、
ViewTree上はNested ScrollできるViewを置く?
Viewの構造的に無理だよね、、
GestureDetectorを使う
●
タッチイベントからユーザー操作の識別してくれる
●
i.e. ロングタップやスクロール
←この部分に仕込む
OnGestureListener
●
GestureDetectorとセットで使う
●
便利なリスナー達
●
onDown
●
onShowPress
●
onFling
●
onSingleTapUp
●
onLongPress
●
onScroll
スクロール量の喰わせ方
BottomSheetBehaviorに強引に喰わせる?
●
そもそもスクロール量のsetterがない、、
BottomSheetBehavior
奪ったイベント
NestedScrollイベントを捏造して喰わせる
奪ったイベント
子ViewがNested Scrollしたかのように
して、親Viewにイベントを送る
NestedScrollイベントの捏造方法
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
if (!isScrolling) {
isScrolling = true;
mCoordinatorLayout.onStartNestedScroll(
mBottomSheetView,
mBottomSheetView,
ViewCompat.SCROLL_AXIS_VERTICAL,
ViewCompat.TYPE_TOUCH
);
}
mCoordinatorLayout.onNestedPreScroll(
mBottomSheetView,
(int) distanceX,
(int) distanceY,
new int[2],
ViewCompat.TYPE_TOUCH
);
return true;
}
←初回はNestedScrollの開始を伝える
←スクロールイベントを送る
NestedScrollイベントの捏造方法
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getActionMasked() == MotionEvent.ACTION_UP) {
if (isScrolling) {
isScrolling = false;
mCoordinatorLayout.onStopNestedScroll(
mBottomSheetView,
ViewCompat.TYPE_TOUCH
);
}
}
return gestureDetector.onTouchEvent(event);
}
←NestedScrollの終わりを伝える
なんとか動いた!
学んだこと
NestedScrollは危険が危ない
イベントハンドラがいっぱいある
● boolean onStartNestedScroll
● void onNestedScrollAccepted
● void onStopNestedScroll
● void onNestedScroll
● void onNestedPreScroll
● boolean onNestedFling
● boolean onNestedPreFling
メソッドの実装が2系統ある
●
新しいもの
●
NestedScrollingChild2
●
NestedScrollingParent2
●
古いもの
●
NestedScrollingChild
●
NestedScrollingParent
ライブラリによっては1部分しか実装してない
●
Viewの構造を入れ替えたとき、
途中にPreとか新旧とか、
片方しか実装してないのが混ざると、
動かない
●
デバッガでステップ実行してると、
「ぉ、、、ぉぅ、、、」ってなる
●
BottomSheetBehaviorはPreのみ実装
みなさんも気をつけてください
この発表のサンプルコード&アプリ
●
cattaka/AndroidSnippets
●
http://github.com/cattaka/AndroidSnippets/
●
BottomSheetBehaviorOpenBySwipeUpActivity.java
●
Google Play
●
https://goo.gl/HuAtZG
●
Open by up
ご清聴ありがとうございました
Takao Sumitomo
@cattaka_net

僕は上スワイプでBottomSheetを出したかっただけなんだ