Struggling with onTouchListener

问题: I have a ViewFlipper, on wich I want to set a touchListener. It is inside a ScrollView, (below the ViewFlipper there are more UI elements) and I want that if the user makes...

问题:

I have a ViewFlipper, on wich I want to set a touchListener. It is inside a ScrollView, (below the ViewFlipper there are more UI elements) and I want that if the user makes a vertical movement, the scrollview acts, and when the user makes a horizontal movement, the ViewFlipper acts. (The components are added dynamically in the ViewFlipper).

For clarification, this is the layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/parentrl">



<ScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <ViewFlipper
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/vflipper"
            android:layout_marginStart="20dp"
            android:layout_marginEnd="20dp"
            android:layout_marginTop="20dp"
            android:background="@drawable/flightcomponentborder">


        </ViewFlipper>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/inforecogida"
            android:layout_marginStart="10dp"
            android:layout_marginTop="10dp"
            android:text="@string/inforecogida"
            android:textColor="@color/actionbardefaultcolor"
            android:layout_below="@+id/vflipper"/>

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="2dp"
            android:layout_below="@+id/inforecogida"
            android:id="@+id/separador"
            android:background="@color/gris"
            android:layout_marginTop="10dp"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/personaheader"
            android:layout_below="@+id/separador"
            android:layout_marginTop="10dp"
            android:layout_alignStart="@+id/inforecogida"
            android:text="@string/persona"
            android:textColor="@color/actionbardefaultcolor"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/persona"
            android:layout_below="@+id/personaheader"
            android:layout_alignStart="@+id/inforecogida"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/infotext"
            android:layout_alignStart="@+id/inforecogida"
            android:layout_below="@+id/persona"
            android:text="@string/infotext"
            android:textStyle="italic"/>

    </RelativeLayout>

</ScrollView>



</RelativeLayout>

This is the TouchListener I am adding to the ViewFlipper:

parentListener = new View.OnTouchListener(){
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            int action = event.getActionMasked();
            switch (action) {
                case MotionEvent.ACTION_DOWN:
                    startX = event.getX();
                    startY = event.getRawY();

                    break;


                case MotionEvent.ACTION_UP:

                    endX = event.getX();
                    endY = event.getRawY();
                    int movX;//0=swipe izq 1=swipe right
                    int movY;
                    if(startX-endX < 0){
                        movX=0;
                        Log.i("David", "Swipe left action up");
                        float totalPixelsX=Math.abs(startX-endX);
                        float totalPixelsY=event.getRawY() - startY;
                        Log.i("David", "totalPixelsx: "+totalPixelsX);
                        Log.i("David", "totalPixelsY: "+totalPixelsY);
                        if(totalPixelsY<0){
                            Log.i("David", "scroll down");
                            totalPixelsY=event.getRawY() - startY;
                            Log.i("David", "We moved "+totalPixelsY+" pixels");
                        }else{
                            Log.i("David", "scroll up");
                            Log.i("David", "We moved "+totalPixelsY+" pixels");
                        }
                    }else{
                        movX=1;
                        Log.i("David", "Swipe right action up");
                        float totalPixelsX=Math.abs(startX-endX);
                        float totalPixelsY=event.getRawY() - startY;
                        Log.i("David", "totalPixelsx: "+totalPixelsX);
                        Log.i("David", "totalPixelsY: "+totalPixelsY);
                        if(totalPixelsY<0){
                            Log.i("David", "scroll down");
                            totalPixelsY=event.getRawY() - startY;
                            Log.i("David", "We moved "+totalPixelsY+" pixels");
                        }else{
                            Log.i("David", "scroll up");
                            Log.i("David", "We moved "+totalPixelsY+" pixels");
                        }
                    }
                    Log.i("David", "haveFlipped false");
                    haveFlipped=false;
                    break;

                case MotionEvent.ACTION_CANCEL:
                    endX = event.getX();
                    endY = event.getRawY();
                    if(startX-endX < 0){
                        movX=0;
                        Log.i("David", "Swipe left action cancel");
                        float totalPixelsX=Math.abs(startX-endX);
                        float totalPixelsY=event.getRawY() - startY;
                        Log.i("David", "totalPixelsx: "+totalPixelsX);
                        Log.i("David", "totalPixelsY: "+totalPixelsY);
                        if(totalPixelsY<0){
                            Log.i("David", "scroll down");
                            totalPixelsY=event.getRawY() - startY;
                            Log.i("David", "We moved "+totalPixelsY+" pixels");
                        }else{
                            Log.i("David", "scroll up");
                            Log.i("David", "We moved "+totalPixelsY+" pixels");
                        }
                    }else{
                        movX=1;
                        Log.i("David", "Swipe right action cancel");
                        float totalPixelsX=Math.abs(startX-endX);
                        float totalPixelsY=event.getRawY() - startY;
                        Log.i("David", "totalPixelsx: "+totalPixelsX);
                        Log.i("David", "totalPixelsY: "+totalPixelsY);
                        if(totalPixelsY<0){
                            Log.i("David", "scroll down");
                            totalPixelsY=event.getRawY() - startY;
                            Log.i("David", "We moved "+totalPixelsY+" pixels");
                        }else{
                            Log.i("David", "scroll up");
                        }
                    }
                    Log.i("David", "haveFlipped false");
                    haveFlipped=false;
                    break;

            }
            return true;
        }
    };

My problem is, the action_cancel or action_up are called BEFORE my finger lifts from the phone screen, so the amount of movement in Y axis is always smaller than the actual movement of my finger.

What I plan to achieve is that, when the amount of X > amount of y, use the ViewFlipper, and when the amount of X < amount of y, leave the ScrollView do his job.

I don't know if my approach is correct. Could anyone tell my why action_up and action_cancel are called before I lift my finger? And how to achieve my goal?

Thank you.


回答1:

If the ViewFlipper returns TRUE at its onTouch() method then the only way is to create a new Class extending RelativeLayout and implements its onInterceptTouchEvent() method.

public class MyRelativeLayout extends RelativeLayout {
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return super.onInterceptTouchEvent(ev);
    }
}

An then use this MyRelativeLayout as root of your XML layout file.


回答2:

I managed to get it working by removing this lines from MotionEvent.ACTION_CANCEL and MotionEvent.ACTION_UP:

endX = event.getX();
endY = event.getRawY();

And then, adding this on the switch:

case MotionEvent.ACTION_MOVE:
endX = event.getX();
endY = event.getRawY();
break;

This way, both the ScrollView and the ViewFlipper are acting as they should.

  • 发表于 2019-03-09 15:02
  • 阅读 ( 200 )
  • 分类:sof

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除