ということで、一番の解決策はスクロールが必要な場合はモーションを無視し、必要無い時にはモーションを有効にすることだろうが、それを実現するためには、やはりサブクラスを書く必要があるだろう。
長くなったので続きは明日にでも。
[Android][SDK][CalendarView]上下のフリックモーションに対応する(ScrollView上のY軸モーションが無効になる)
という訳で、スクロールが不要な時はY軸のモーションを受付けるScrollViewを書いてみた。
- MotionableScrollView.java
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ScrollView;
public class MotionableScrollView extends ScrollView {
public MotionableScrollView(Context context) {
super(context);
}
public MotionableScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MotionableScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_MOVE: {
if ( this.canScroll() ) {
//スクロール可能な場合は既定の処理を実施
return super.onInterceptTouchEvent(ev);
} else {
return false;
}
}
case MotionEvent.ACTION_DOWN: {
return super.onInterceptTouchEvent(ev);
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
return super.onInterceptTouchEvent(ev);
case MotionEvent.ACTION_POINTER_UP:
return super.onInterceptTouchEvent(ev);
}
return super.onInterceptTouchEvent(ev);
}
protected boolean canScroll() {
View child = this.getChildAt(0);
if (child != null) {
int childHeight = child.getHeight();
return this.getHeight() < childHeight + this.getPaddingTop() + this.getPaddingBottom();
}
return false;
}
}switchで分岐しているsuper.onInterceptTouchEvent(ev)の呼び出しは全て集約できると思うが、実際には他にも処理を入れているので便宜上分けている。
canScrollメソッドは本クラスの要だが、元々ScrollViewに実装されている。相変わらずprivateスコープの為書き直したのだ。
こういうのはせめてprotectedスコープにしておくべきだと思うんだ。