I have parent view v extends linear layout. And child one is LinearLayout, child two is ScrollView.
I want to make MyParent View intercept vertical MotionEvent.ACTION_MOVE (only down direction, child scrollview.getScrollY()==0
) and processing it in parent, and other MotionEvent is processed by children
Here is MyView.xml
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android" >
<LinearLayout
android:id="@+id/child_linear>
android:height="50dp"
android:width="50dp">
...something...
</LinearLayout>
<ScrollView
android:id="@+id/child_scrollview>
<LinearLayout/>
</LinearLayout>
</ScrollView>
</merge>
And this is my code below
public class MyCustomView extends LinearLayout{
public MyCustomView(Context context) {
super(context);
init();
}
private void init(){
setOrientation(LinearLayout.VERTICAL);
LayoutInflater inflater =
(LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.MyView, this, true);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
final int action = event.getAction();
Log.d(log,"onInterceptTouchEvent : "+action);
if (action == MotionEvent.ACTION_CANCEL || action ==
MotionEvent.ACTION_UP) {
mIsBeingDragged = false;
return false;
}
if (action != MotionEvent.ACTION_DOWN && mIsBeingDragged) {
return true;
}
switch (action) {
case MotionEvent.ACTION_MOVE: {
if (isReadyForPull()) {
final float y = event.getY(), x =
event.getX();
final float diff, oppositeDiff, absDiff;
diff = y - mLastMotionY;
oppositeDiff = x - mLastMotionX;
absDiff = Math.abs(diff);
ViewConfiguration config =
ViewConfiguration.get(getContext());
if (absDiff > config.getScaledTouchSlop() &&
absDiff > Math.abs(oppositeDiff) && diff >= 1f) {
mLastMotionY = y;
mLastMotionX = x;
mIsBeingDragged = true;
Log.d(log,"Flag setting");
}
}
break;
}
case MotionEvent.ACTION_DOWN: {
if (isReadyForPull()) {
mLastMotionY = mInitialMotionY = event.getY();
mLastMotionX = event.getX();
mIsBeingDragged = false;
}
break;
}
}
return mIsBeingDragged;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
final int action=event.getAction();
Log.d(log,"onTouchEvent : "+action);
if (event.getAction() == MotionEvent.ACTION_DOWN && event.getEdgeFlags() != 0) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE: {
Log.d(log,"ACTION MOVE RECEIVE");
if (mIsBeingDragged) {
mLastMotionY = event.getY();
mLastMotionX = event.getX();
pullEvent();
return true;
}
break;
}
case MotionEvent.ACTION_DOWN: {
if (isReadyForPull()) {
mLastMotionY = mInitialMotionY = event.getY();
return true;
}
break;
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
if (mIsBeingDragged) {
mIsBeingDragged = false;
if (mState == State.RELEASE_TO_REFRESH ) {
setState(State.REFRESHING);
return true;
}
if (isRefreshing()) {
smoothScrollTo(-mHeaderHeight , null);
return true;
}
setState(State.RESET);
return true;
}
break;
}
}
return false;
}
isReadyForPull()
function check only this
private boolean isReadyForPull(){
return mScrollView.getScrollY()==0;
}
My code works well.
If I move down my child scrollview, onInterceptTouchEvent
first get MotionEvent.ACTION_DOWN and initialize values, and get sequentially MotionEvent.ACTION_MOVE so set mIsBeingDragged flag to true and return true. So I can process event in my ParentView's onTouchEvent
.
Otherwise, if I move up child scrollview, then onInterceptTouchEvent
return false and my child scrollview get that MotionEvent and scrolling down.
This is expected work. Good.
But, when I touch my child linearlayout, it doesn't not work!
If I touch and drag my child linearlayout, my CustomView's onInterceptTouchEvent
get MotionEvent.ACTION_DOWN, but couldn't get second MotionEvent.ACTION_MOVE.
Why this not work on only child linearlayout?
Note: I tested several times and know that (default)touchable view or viewgroup (like button, scrollview etc.) do work with my code, while (default)untouchable view or widget(like imageview, framelayout) don't work with my code.