Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/189.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/apache/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 截取包含可滚动小部件(scrollview、listview等)的片段上的手势_Android_Android Fragments_Android Listview_Fragment_Gesture - Fatal编程技术网

Android 截取包含可滚动小部件(scrollview、listview等)的片段上的手势

Android 截取包含可滚动小部件(scrollview、listview等)的片段上的手势,android,android-fragments,android-listview,fragment,gesture,Android,Android Fragments,Android Listview,Fragment,Gesture,我遇到了一个关于手势识别的应用程序的一部分问题,这个应用程序已经让我发疯好几个小时了 我有一个包含两个框架布局的活动,它们占据了整个屏幕,一个包含应用程序的主要内容,另一个包含聊天日志。一次只有一个设置为可见。我的想法是,我可以在主内容片段上向右滑动,聊天片段将在facebook风格的界面中可见。同样,在聊天片段上向左滑动将使主要内容片段回到视图中 滑动侦听器的代码: private void attachFragmentSwipeListeners() { int scree

我遇到了一个关于手势识别的应用程序的一部分问题,这个应用程序已经让我发疯好几个小时了

我有一个包含两个框架布局的活动,它们占据了整个屏幕,一个包含应用程序的主要内容,另一个包含聊天日志。一次只有一个设置为可见。我的想法是,我可以在主内容片段上向右滑动,聊天片段将在facebook风格的界面中可见。同样,在聊天片段上向左滑动将使主要内容片段回到视图中

滑动侦听器的代码:

 private void attachFragmentSwipeListeners() {
        int screenOrientation = getResources().getConfiguration().orientation;
        if (screenOrientation == Configuration.ORIENTATION_PORTRAIT) {
            FrameLayout mainContent = (FrameLayout) findViewById(R.id.flMainContent);
            mainContent.setOnTouchListener(new OnSwipeTouchListener(ExICS_Main.this) {
                @Override
                public void onSwipeLeft() {
                    showChatLog();
                    super.onSwipeLeft();
                }
            });

        FrameLayout chatWindow = (FrameLayout) findViewById(R.id.flChatWindow);
        chatWindow.setOnTouchListener(new OnSwipeTouchListener(ExICS_Main.this) {
            @Override
            public void onSwipeRight() {
                hideChatLog();
                super.onSwipeRight();
            }
        });
    }
}
听众本身:

public class OnSwipeTouchListener implements View.OnTouchListener {
    private static final String TAG = OnSwipeTouchListener.class.getName();
    private final GestureDetector gestureDetector;

    public OnSwipeTouchListener(Context context) {
        gestureDetector = new GestureDetector(context, new GestureListener());
    }

    public void onSwipeLeft() {
    }

    public void onSwipeRight() {
    }

    public boolean onTouch(View v, MotionEvent event) {
        return gestureDetector.onTouchEvent(event);
    }

    private final class GestureListener extends GestureDetector.SimpleOnGestureListener {
        private static final int SWIPE_DISTANCE_THRESHOLD = 100;
        private static final int SWIPE_VELOCITY_THRESHOLD = 100;

        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            Log.i(TAG, "OnSwipeTouchListener Fling");
            float distanceX = e2.getX() - e1.getX();
            float distanceY = e2.getY() - e1.getY();
            if (Math.abs(distanceX) > Math.abs(distanceY) && Math.abs(distanceX) > SWIPE_DISTANCE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                if (distanceX > 0) onSwipeRight();
                else onSwipeLeft();
                return true;
            }
            return false;
        }
    }
}
这已经过测试,可以正常工作,这在使用两个只包含文本视图等的占位符片段时非常好。我遇到的问题是当片段包含交互式小部件时,例如滚动视图或列表视图

在这些情况下,小部件的使用应确保它们只能以垂直方式滚动,然而,它们正在使用fling交互,甚至是水平交互,因此在应用程序中侦听片段级别的手势检测器永远不会被触发

我想做的是,当在片段上进行滑动时,让片段上的gesturedetector决定水平滑动是否足以触发主要内容和聊天之间的切换,反之亦然,如果是,则在活动级别调用show/hideChatLog()。如果没有,则将TouchEvent传播回片段的子视图,不管它是什么,以便它可以按照自己的意愿执行

或者,覆盖小部件本身上的手势检测,如果片段手势侦听器正在侦听的水平滑动,则将其推回到视图层次结构上,而不是使用它,以便片段手势检测器可以看到并对其进行操作

我尝试过创建一个新的手势监听器,它实现了onFling方法,如下所示,并将其附加到ListView或ScrollView等

public class IgnoreHorizontalSwipeInterceptor implements View.OnTouchListener {
    private static final String TAG = IgnoreHorizontalSwipeInterceptor.class.getName();
    private final GestureDetector gestureDetector;

    public IgnoreHorizontalSwipeInterceptor(Context context) {
        gestureDetector = new GestureDetector(context, new GestureListener());
    }

    public void onSwipeLeft() {
    }

    public void onSwipeRight() {
    }

    public boolean onTouch(View v, MotionEvent event) {
        return gestureDetector.onTouchEvent(event);
    }

    private final class GestureListener extends GestureDetector.SimpleOnGestureListener {
        private static final int SWIPE_DISTANCE_THRESHOLD = 100;
        private static final int SWIPE_VELOCITY_THRESHOLD = 100;

        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            Log.i(TAG, "OnSwipeTouchListener Fling");
            float distanceX = e2.getX() - e1.getX();
            float distanceY = e2.getY() - e1.getY();
            if (Math.abs(distanceX) > Math.abs(distanceY) && Math.abs(distanceX) > SWIPE_DISTANCE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                return false;
            }
            return false;
        }
    }
}
然后像这样附加它:

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View fragmentView = inflater.inflate(R.layout.fragment_room_list, container, false);
    ListView roomListView = (ListView) fragmentView.findViewById(R.id.lvRoomList);
    ...
    RoomListFragmentListAdapter adapter = new RoomListFragmentListAdapter(getActivity(), R.layout.room_list_item_layout, rooms);
    roomListView.setAdapter(adapter);
    roomListView.setOnTouchListener(new IgnoreHorizontalSwipeInterceptor(getActivity().getBaseContext()));
    return fragmentView;
}
我曾希望,通过在连接到listView的IgnoreHorizontalSwipeInterceptor中始终在onFling()中返回false,它将导致事件带回父级,即片段本身,但这不会发生

当我在listview上滑动时,我可以在日志中看到来自IgnoreHorizontalSwipeInterceptor onFling()的OnSwipeTouchListener Fling。如果我对一个不包含可滚动小部件的片段执行相同的操作,我可以像我希望的那样看到OnSwipeTouchListener Fling

我已经找到了答案,但这对我来说真的没有多大意义。。。它提到了重写InterceptTouchEvent,但我不知道在何处这样做或如何做才有意义。如果这确实是正确的方法,我们将非常感谢在何处以及如何做到这一点

另一种(可能更容易)的方法是实现一个接口,这样当片段小部件检测到自身发生水平滑动时,它会使用对父活动的回调来触发我期望的操作show/hideChatLog()。然而,这似乎是一种相当肮脏的做法,如果可能的话,我们宁愿避免

展示我对布局的理解

使用内容视图中的此片段,向右滑动以显示聊天日志,效果与预期一致:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/holo_blue_bright"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="XXXX.Activities.ExICS_Main$PlaceholderFragment">

    <TextView
        android:id="@+id/section_label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This is a fragment" />

</RelativeLayout>

但这一个没有,因为listview正在使用触摸事件,并且它没有被传递给片段onTouchEvent GestureListener:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="XXX.Fragments.Room_List_Fragment">

    <ListView
        android:id="@+id/lvRoomList"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

</LinearLayout>