在片段级别应用以及ViewPager与它滑动手势的默认刷卡功能已禁用 [英] Swipe Gesture applied at Fragment level along with ViewPager with it's default swipe disabled

查看:159
本文介绍了在片段级别应用以及ViewPager与它滑动手势的默认刷卡功能已禁用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现以下问题: 安卓:FragmentActivity在FragmentActivity(滚动型的导航栏) 。但是我的这个问题是关于如何使用交易展示片段以及使轻扫手势检测在一个安全的方式。 注意:是在我已经发布(这也有使用交易,包括两种情况示出在容器的片段的有效方法)的答案的链接。请看到这一点。 我曾在问候了一些东西,但通过使用支持ViewPager片段,没有嵌套的:

详细信息: https://moqups.com/abhsax130778@gmail.com/ lc0ZOERO /号码:a5d7b55eb

  1. 使用的onTouchEvent和onInterceptTouchEvent使用自定义ViewPager禁用默认刷卡。
  2. 设置有片段,其中的每一个显示在每个选项卡的列表声明FragmentStatePagerAdapter。
  3. 在声明片段,其中有这样ViewPager的旁边main_activity的main_layout。 想法是显示activity_fragments上ViewPager_fragment一个按钮被点击,当用户presses返回时, 按钮,则默认ViewPager_fragment使用再次显示回栈交易上添加和弹出他们在返回pressed 的活性。因此,我也保持我的自定义backStack显示/隐藏activity_fragments后退堆栈时, 持久性有机污染物的事务。

现在我想要实现的是做第三点以上使用刷卡,比划右[左到右]只刷卡。

我已经使用GestureListener和SimpleOnGestureListener和活动的的onTouchEvent这一点。

问题,我面对的是:

此手势工作于活动屏幕,这是该片段和该活动的部分的下方的部分。 我想要的姿势工作

  1. 在分段区,在其布局的多个视图。
  2. 在只左右方向。
  3. 仅从activity_fragment到ViewPager的标签片段表现得像历史导航作为已经在onBak pressed /的onkeydown完成 实现用回堆栈弹出窗口和我的自定义回堆栈。

我想在这样的布局下面的类和改变我的活动片段。

我的手势和触摸监听器扩展框架布局:

 公共类OnSwipeTouchListener扩展的FrameLayout {

        私人最终GestureDetector gestureDetector;
        私有静态最后字符串变量=OnSwipeTouchListener;
    私人上下文的背景下;
        公共OnSwipeTouchListener(上下文的背景下,ATTRS的AttributeSet){
            超(背景下,ATTRS);
            this.context =背景;
            gestureDetector =新GestureDetector(上下文,新GestureListener());
            setClickable(真正的);

        }

        @覆盖
        公共布尔onInterceptTouchEvent(MotionEvent EV){
            返回super.onInterceptTouchEvent(EV);
        }

        @覆盖
        公共布尔的onTouchEvent(MotionEvent事件){
 gestureDetector.onTouchEvent(motionEvent);
            返回super.onTouchEvent(事件);
        }


        私人final类GestureListener扩展SimpleOnGestureListener {

            私有静态最终诠释SWIPE_THRESHOLD = 100;
            私有静态最终诠释SWIPE_VELOCITY_THRESHOLD = 100;

            @覆盖
            公共布尔onDown(MotionEvent E){

                返回true;
            }

            @覆盖
            公共布尔onFling(MotionEvent E1,E2 MotionEvent,浮velocityX,浮velocityY){

                布尔结果= FALSE;
                尝试 {
                    浮diffY = e2.getY() -  e1.getY();
                    浮diffX = e2.getX() -  e1.getX();
                    如果(Math.abs(diffX)> Math.abs(diffY)){
                        如果(Math.abs(diffX)> SWIPE_THRESHOLD和放大器;&安培; Math.abs(velocityX)> SWIPE_VELOCITY_THRESHOLD){
                            如果(diffX大于0){
                                onSwipeRight();
                            } 其他 {
                                onSwipeLeft();
                            }
                        }
                    } 其他 {
                        如果(Math.abs(diffY)> SWIPE_THRESHOLD和放大器;&安培; Math.abs(velocityY)> SWIPE_VELOCITY_THRESHOLD){
                            如果(diffY大于0){
                                onSwipeBottom();
                            } 其他 {
                                onSwipeTop();
                            }
                        }
                    }
                }赶上(例外的例外){
                    //看到,E1为空
                }
                返回结果;
            }
        }

        公共无效onSwipeRight(){
            ///这里管理我的背堆栈历史记录。
        }

        公共无效onSwipeLeft(){
        }

        公共无效onSwipeTop(){
        }

        公共无效onSwipeBottom(){
        }
    }
 

,然后更改框架布局,以此类引用:

 < path.to.my.package.OnSwipeTouchListener
            机器人:ID =@ + ID / activity_frag_frame_layout1
            机器人:layout_width =FILL_PARENT
            机器人:layout_height =FILL_PARENT
            机器人:能见度=隐形>

            <片段
                机器人:ID =@ + ID / activity_frag1
                机器人:layout_width =FILL_PARENT
                机器人:layout_height =FILL_PARENT
                类=path.to.my.package.fragments.Activity_Frag1
                机器人:标签=act_frag1/>
        < /path.to.my.package.OnSwipeTouchListener>
 

它帮助我一点,所以它应该帮助你找到解决方案。存在这样停止工作的片段中的一个一搜索查看,并且没有点击的工作原理。 如果你是我想要实现的,请在这方面有所帮助。

更新1: 在这两个的onTouchEvent和onInterceptTouchEvent返回真有预期的效果,但它阻止的点击次数在片段,其中搜索查看是存在的,没有点击,在点击的看法present工作。只有刷卡的工作。更新:在我最新的:我也放弃了使用事务背栈完全是因为我依靠我的自定义背叠在那里我维护导航历史记录的所有选项卡。这个我也用setCurrentTab和onTabSelected由ViewPager和FragmentStatePagerAdapter给出的方法。

更新2: 这一个是难以实现: 选中需要被拦截的事件,哪些是要传递给孩子的意见: HTTP:/ /developer.android.com/training/gestures/viewgroup.html

更新3:

  1. 在我的布局的活动,有一种观点寻呼机,并在它下面的每个帧的布局 有一个片段。

  2. 当你启动应用程序时,viewPager显示在第一个选项卡中的片段。

  3. 在单击该片段上的一个按钮,在片段中的一个 下面viewpager framelayouts显示并添加到我的自定义backstack。

  4. 在回车键pressed,这个片段被再次隐藏显示的标签片段 该viewPager。每一上述完成。只有我想的滑动手势进行 左到右的工作,而且我发现,我可以通过拦截触摸事件做到这一点。 但它不这​​样做,在所有。当我返回true, 只有滑动手势的作品,其他明智的这一行动被取消, 在这个片段工作的点击次数。

解决方案

我已经提到的。 HTML相对=nofollow> http://mobi-app-dev.blogspot.in/2014/01/android-transactions.html

选中需要被拦截的事件,哪些是要传递给孩子的意见: http://developer.android.com/training/gestures/viewgroup.html

而不是在用我的滑动手势听者框架布局 该片段所连接 现在我使用它的相对布局这是根欣赏 片段。

  @覆盖
    公共布尔onInterceptTouchEvent(MotionEvent事件){
        布尔截获= super.onInterceptTouchEvent(事件);

        //在一般情况下,我们不希望拦截触摸事件。它们应该是
        //通过子视图处理。

        gestureDetector.onTouchEvent(事件);
        返回false;
    }

    @覆盖
    公共布尔的onTouchEvent(MotionEvent事件){
        布尔感动= super.onTouchEvent(事件);
        gestureDetector.onTouchEvent(事件);
        返回感动;
    }
 

下面是我现在跟随,而使用的碎片在我的活动的一些提示:

交易的片段有效管理:

[注:如果您使用的是FragmentStatePagerAdapter,您可以在片段中,您使用的是作为该适配器的数据列表与另一个片段替换片段的特定索引处玩,在某种程度上,你是在相同的标签,但其内容不改变的标签被改变。然后使用notifyDataSetChanged()。在这里,你不使用事务,否则你做的。

  1. 使用Fragment.instantiate()来初始化片段代替 构造函数。
  2. 使用侦听器来更新/删除实例的引用 (从集合用来指代他们)片段onCreateView和的onDestroy的。
  3. 使用getView()来获取每一个地方和更新片段的根视图 功能。
  4. 请不要跟踪实例,事实上避免静电指针在以往可能。
  5. 使用getSupportFragment,而不是保持FragmentManager参考 鉴于寻呼机适配器或其他地方。
  6. 使用附加detatch的交易隐藏来看,要获得摆脱孩子的意见 片段的根视图,并重新初始化。 这是因为只有一个片段需要是可见的时间,其他的需要分离。 因此,需求重新连接。
  7. getActivity()或getApplicationContext()任何适用的,而不是保持 一个全局变量来引用的语境。
  8. onConfiguration改变(方向,键盘,调整大小):做活动,并把它传递 以积极的片段进行管理。 重要提示:如果你想使用的片段进行交易,不申报他们的布局。 提供集装箱(布局)的id添加片段的交易。
  9. 一个片段的交易应在事件调用来完成,而不是其他地方, 和这样的事件不应该是重复的。这prevents非法参数异常。
  10. 有一个ViewPager方法,你不必使用Fragments.Instead, 您可以使用视图,或ViewGroups。这取代片段的嵌套。
  11. 在检测片段的水平,这意味着如果你想有一个片段,B,以取代现有的片段'A',当你想回去,以显示片段A时,pressing回到'B' ,把该交易在后面的堆栈。

提示:在将刷卡的功能,因为还有其他的可点击的看法小心。 轻扫上RootView拦截触摸返回false,但分析的一面。


一件事:你应该观察到具有在一个时间在一个容器中一个片段解决的另一个问题:如果有两个片段,一个在另一个的顶部,从一个片段的点击进入另一个片段是下面。因此,隐藏或更换有只有一个片段的时间。回协议栈有助于维持导航的水平,并在配置改变或更新,尝试更新而不是做交易,因为这改变片段导航的顺序目标活性片段的同一个实例。

I found the question below: Android: FragmentActivity in FragmentActivity (Scrollview in Navigationbar) . However this question of mine is about how to use Transactions to show fragments as well as enabling swipe gesture detection in a safe way. Note: There is a link in the answer that I have posted (This also have the effective way of showing fragments in a container using transactions, including two scenarios). Please see that. I have tried a few things in regards, but by using a fragment supporting ViewPager, not nested:

Details: https://moqups.com/abhsax130778@gmail.com/lc0ZOERO/p:a5d7b55eb

  1. Disabled default swipe using onTouchEvent and onInterceptTouchEvent using custom ViewPager.
  2. Declared FragmentStatePagerAdapter provided with a list of fragments, each of which is displayed in each tab.
  3. Declare Fragments in the main_layout of the main_activity which has this ViewPager along side. Idea is to show the activity_fragments when a button on a ViewPager_fragment is clicked and when user presses return button, then the default ViewPager_fragment is shown again using back stack transactions on add and popping them on BackPressed of the activity. I am therefore also maintaining my custom backStack to show/hide the activity_fragments when the back stack pops a transaction.

Now what I want to achieve is to do the third point above using swipe-gestures for right [left to right] swipes only.

I have used GestureListener and SimpleOnGestureListener and activity's OnTouchEvent for this.

Problem that I face is that:

This gesture works on the portion of the activity screen which is below the fragment and the portion of the activity. I want the gesture work

  1. On Fragment area which has multiple views in its layout.
  2. In only left-right direction.
  3. Only from activity_fragment to ViewPager's tab fragment to behave like history navigation as already done in onBakPressed/onKeyDown implementation using back stack popups and my custom back stack.

I tried the following class and change in my activity fragment in layouts like this.

My Gesture and Touch listener extended with frame layout:

        public class OnSwipeTouchListener extends FrameLayout {

        private final GestureDetector gestureDetector;
        private static final String TAG = "OnSwipeTouchListener";
    private Context context;
        public OnSwipeTouchListener(Context context, AttributeSet attrs) {
            super(context, attrs);
            this.context=context;
            gestureDetector = new GestureDetector(context, new GestureListener());
            setClickable(true);

        }

        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            return super.onInterceptTouchEvent(ev);
        }

        @Override
        public boolean onTouchEvent(MotionEvent event) {
 gestureDetector.onTouchEvent(motionEvent);
            return super.onTouchEvent(event);
        }


        private final class GestureListener extends SimpleOnGestureListener {

            private static final int SWIPE_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) {

                boolean result = false;
                try {
                    float diffY = e2.getY() - e1.getY();
                    float diffX = e2.getX() - e1.getX();
                    if (Math.abs(diffX) > Math.abs(diffY)) {
                        if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                            if (diffX > 0) {
                                onSwipeRight();
                            } else {
                                onSwipeLeft();
                            }
                        }
                    } else {
                        if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) >           SWIPE_VELOCITY_THRESHOLD) {
                            if (diffY > 0) {
                                onSwipeBottom();
                            } else {
                                onSwipeTop();
                            }
                        }
                    }
                } catch (Exception exception) {
                    //see that e1 is null
                }
                return result;
            }
        }

        public void onSwipeRight() {
            ///manage my back stack history here.
        }

        public void onSwipeLeft() {
        }

        public void onSwipeTop() {
        }

        public void onSwipeBottom() {
        }
    }

and then change frame layouts to this class reference:

<path.to.my.package.OnSwipeTouchListener
            android:id="@+id/activity_frag_frame_layout1"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:visibility="invisible" >

            <fragment
                android:id="@+id/activity_frag1"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                class="path.to.my.package.fragments.Activity_Frag1"
                android:tag="act_frag1" />
        </path.to.my.package.OnSwipeTouchListener>

It helped me little, so should it help you in finding solution. There is a searchView in one of the fragments that stopped working, and no click works. If you get it what I want to achieve, please help in this regards.

Update 1: Returning true in both onTouchEvent and onInterceptTouchEvent has desired effect, but it blocks the clicks in fragments where SearchView is there, no clicks work in the clickable views present. Only the swipe is working. Update: In my latest: I have also discarded the use of transaction-back-stacks completely because I rely on my custom back-stack where I maintain the navigation history for all the tabs. This I do using setCurrentTab and onTabSelected methods given by ViewPager and FragmentStatePagerAdapter.

Update 2: This one is difficult to implement: Check which events needs to be intercepted and which are to be passed to the child views: http://developer.android.com/training/gestures/viewgroup.html

Update 3:

  1. In my layout for activity, there is a view pager, and in each frame layouts below it there is one fragment.

  2. When you start the app, the viewPager shows the fragment in the first tab.

  3. When a button on this fragment is clicked, one of the fragment in the framelayouts below viewpager is shown and added to my custom backstack.

  4. When return key is pressed, this fragment is hidden again to show the tab fragment in the viewPager. Every of the above is done. Only I want the swipe gesture for left to right to work, and I found that I can do it by intercepting touch events. But it does not do that at all When I return true, only the swipe gesture works, other wise this action is cancelled and the clicks on this fragment work.

解决方案

I have mentioned this answer in http://mobi-app-dev.blogspot.in/2014/01/android-transactions.html.

Check which events needs to be intercepted and which are to be passed to the child views: http://developer.android.com/training/gestures/viewgroup.html

Instead of using my swipe gesture listener in frame-layout on which fragments are attached, now I am using it on the relative-layouts which are the root-views of the fragments.

@Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        boolean intercepted = super.onInterceptTouchEvent(event);

        // In general, we don't want to intercept touch events. They should be
        // handled by the child view.

        gestureDetector.onTouchEvent(event);
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean touched = super.onTouchEvent(event);
        gestureDetector.onTouchEvent(event);
        return touched;
    }

Here are some tips that I follow now while using fragments in my activities:

Effective management of transactions for fragment:

[Note: In case you are using FragmentStatePagerAdapter, you can play with replacing a fragment with another fragment at a particular index in the list of fragment that you are using as a data for this adapter, in a way that you are in the same tab but its content is changed without changing the tab. Then use notifyDataSetChanged(). Here you do not use transactions, but otherwise you do].

  1. Use Fragment.instantiate() to initialize your fragments instead of constructor.
  2. Use listeners to update/delete the reference of instance (from the collection used to refer them) of fragment onCreateView and onDestroy.
  3. Use getView() to get the root view of fragment every where and on update functionality.
  4. Do not keep track of instances, infact avoid static pointers where ever possible.
  5. Use getSupportFragment instead of keeping reference of FragmentManager in view pager adapter or elsewhere.
  6. Use attach detatch on transaction hide view, to get rid of child views on Fragment's root view and re initialize. This is because only one fragment needs to be visible at a time, the others need to detach. Therefore re-attach on demand.
  7. getActivity() or getApplicationContext() whatever applicable, instead of keeping a global variable to keep references to context.
  8. onConfiguration change (orientation, keyboard, resize): do in activity and pass it to active fragment which manages it. Important: If you do want to use fragments for transactions, do not declare them in layouts. Provide container (layout) id in add fragment transaction.
  9. A Fragment transaction should be done in an event call, not anywhere else, and such an event should not be repetitive. This prevents Illegal Argument Exception.
  10. There is a ViewPager method where you do not have to use Fragments.Instead, you can use Views, or ViewGroups. This replaces the nesting of fragments.
  11. Detect the level of fragments, that means if you want a fragment 'B' to replace existing fragment 'A', and when you want to go back to show fragment 'A' when pressing back on 'B', put that transaction in back stack.


Tip : Carefull while adding swipe feature because there are other clickable views. Swipe with intercept touch on RootView returning false but analysing touches.


One more thing: you should observe that having one fragment in one container at a time resolves another issue: If there are two fragments , one on the top of the other, the clicks from one fragment goes to the other fragment that is beneath. So hide or replace to have just one fragment at a time. Back-Stack helps in maintaining the navigation levels, and on configuration change or update, try to update the same instance of the target active fragment, instead of doing transactions because that changes the order of fragments navigated.

这篇关于在片段级别应用以及ViewPager与它滑动手势的默认刷卡功能已禁用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆