安卓导航抽屉没有通过的onTouchEvent到活动抽屉、onTouchEvent

2023-09-05 06:56:52 作者:神明离开了我

我有一个活动它采用了Android NavigationDrawer 。 当仅使用片段 S(像往常一样),一切都运行完美。 但现在我想用这个抽屉在我的应用程序的其他活动,并为其中的一部分, 我不希望主视图是一个片段

I have an Activity which uses the Android NavigationDrawer. When using only fragments (as usual), everything works perfect. But now I want to use this drawer on other activities of my app, and for some of them, I don't want the main view to be a fragment.

问题 问题是,在的onTouchEvent()活动本身(和 onItemClickedListener() 孩子的ListView 为此事)不叫,因为抽屉消耗它。 当然,我希望它被称为:) 不用说,我希望答案是简单的(甚至是XML的),并希望不通过延长抽屉类(除非那是当然,需要通过)。

Question The problem is, the onTouchEvent() of the activity itself (and the onItemClickedListener() of a child ListView for that matter) isn't called, because the drawer consumes it. Of course, I want it to be called:) Needless to say, I would hope the answer will be simple (even a XML one), and hopefully not by extending the Drawer class (unless that's what it takes of course).

更多信息 该活动的主要布局非常简单,基本上是的ListView DrawerLayout 在它的上面(下文中的XML)。 该抽屉有一个片段,因为它是 childView (用于片段导航),当然,在的ListView 抽屉产品。

More Info The Activity's main layout is very simple, basically a ListView and the DrawerLayout on top of it (below in XML). The Drawer has one fragment as it's childView (for fragment navigation) and of course, the ListView for the Drawer Items.

我见过的关于(不完全)类似的问题很多问题,和常见的回答是使用 onInterceptTouch() requestDisallowInterceptTouchEvent() DrawerLayout ,并在父视图(活动的主要内容),并即使的onTouchEvent()(用假返回)上的的ListView 的抽屉中。 似乎没有这样的伎俩。

I've seen many questions regarding (not exactly) similar issues, and the frequent answer was to use onInterceptTouch(), requestDisallowInterceptTouchEvent() on the DrawerLayout, and on the Parent view (Activity's main content) and even onTouchEvent() (with False returned) on the ListView of the Drawer. Nothing seems to do the trick.

我看了这个链接 它似乎像使用拦截方法的地方可能是答案。但如何?

I read this link and it does seem like using Intercept methods somewhere could be the answer. But how?

请让我知道如果你需要任何code。但是,这是一个非常基本的code /布局此事。 谢谢!

Please let me know if you need any code. But it's a very basic code/layout for this matter. Thanks!

推荐答案

显然,答案是有点简单,但它确实让你延长DrawerLayout并做一些思考,也许会导致一些奇怪的结果(利用最后 举例来说,我还没有看到任何,还)。

Apparently the answer is somewhat easy, although it does make you extend the DrawerLayout and do some thinking, and maybe will result in some strange results (using the LAST example, I haven't seen any, yet).

总之,相关的问题而回头看,可以帮助理解这个问题(将解释关于第一个以后): 1。DrawerLayout prevents MainActivity.onTouchEvent()呼叫 2. How我可以在Android DrawerLayout requestDisallowTouchEvents 3. Set拖累利润率为Android导航抽屉

Anyway, related questions which looking backwards can help understanding the issue (will explain about the first one later on): 1. DrawerLayout prevents call of MainActivity.onTouchEvent() 2. How can I requestDisallowTouchEvents on Android DrawerLayout 3. Set drag margin for Android Navigation Drawer

答案 首先,请注意,我把很多的例子在这里。如果你只是想最好的一个(对我来说),跳到最后一个。 其次,如果有人有足够的声誉,请在第一个环节的问题发表评论,并把一个链接到这个答案(它可以帮助那个家伙)。

Answer First, please note that I put lots of examples here. If you just want the best one (for me), jump to the last one. Secondly, if someone has enough reputation, please comment on the first link's question and put a link to this answer (it can help that guy).

示例1 好了,基本上,只是延长Android的DrawerLayout和替换的onTouchEvent(),以这样的:

Example 1 Well, basically, just extend Android's DrawerLayout and replace onTouchEvent() to this:

@Override
public boolean onTouchEvent(MotionEvent arg0) {
    super.onTouchEvent(arg0);
    return false;
}

此解决方案将做任何事情,但它不会打开抽屉的滑轨,只有菜单点击等。此外,它转发点击所以当抽屉处于打开 例如,触摸它的外部环境不会关闭它,但点击无论是背后(如一个ListView)。 Le'ts更加努力......

This solution will do anything except that it won't open the Drawer on slides, only menu clicks and the like. Besides, it forwards clicks so when the Drawer is open for instance, touching outside of it will NOT close it, but click on whatever is behind (e.g. a ListView). Le'ts try harder...

例2 现在,让我们赶开或可见的情况下,返回true(和消费在抽屉的动作)。

Example 2 Now, let's catch the open OR visible cases, to return true (and consume the action at the Drawer).

@Override
public boolean onTouchEvent(MotionEvent arg0) {
    super.onTouchEvent(arg0);

    if(isDrawerOpen(findViewById(R.id.list_slidermenu)) || 
            isDrawerVisible(findViewById(R.id.list_slidermenu))){
        return true;
    }

    return false;
}

这个解决方案是最好的,因为它prevents点击的抽屉时,后面的抽屉是打开的,甚至可见(幻灯片开始...)。但是,触摸滑动它仍然无法正常工作。

This solution is better, as it prevents clicks on behind the Drawer when the drawer is open or even visible (slide starts...). But touch-sliding it still doesn't work.

示例3 好了,我们只是分裂的情况下。触摸(MotionEvent.ACTION_DOWN)的抽屉的内缘(区,谷歌desided时,在触及滑动抽屉) 会导致返回true,消费的作用,和其他人将事件转发(返回false)。

Example 3 Ok, so let's just split cases. Touches (MotionEvent.ACTION_DOWN) inside the Drawer's margin (area that Google desided to slide Drawer when touched at) will result in returning True to consume the action, and others will forward the event (return False).

@Override
public boolean onTouchEvent(MotionEvent arg0) {
    super.onTouchEvent(arg0);
    float edge = 30;//that's for a left drawer obviously. Use <parentWidth - 30> for the right one.
    View mDrawerListView = findViewById(R.id.drawer_listview);

    if(isDrawerOpen(mDrawerListView) || 
            isDrawerVisible(mDrawerListView)){
        return true;
    } else if(arg0.getAction() == MotionEvent.ACTION_DOWN && arg0.getX() > edge){
        return false;
    }

    return true;
}

请注意,我用30dp。这就是我发现的保证金(尽管在其中一个链接,就被说成是20 ....)。

Note that I used 30dp. That's what I found to be the margin (although in one of the links it is said to be 20....).

好了,下一个例子,当然要决定什么是,究竟是缘(见code以上)值,根据Android系统。我们不希望 使用一些可能会改变或什么的。

Well, the next example would of course be deciding what is, exactly, that edge (see in code above) value is, according to Android. We don't want to use a number that could change or whatever.

新问题 所以,现在,第一个链接应该得心应手。据黑客的抽屉code得到那个抽屉边/ megin数量。但是,它并没有为我工作,因为这些确切的字段名称不能被发现。 我跑mDrawerLayout.getClass()。getfield命令()返回所有字段,但没有任何运气找到我们想要的。有人吗?

New Question So now that first link should come handy. It "hacks" the Drawer code to get that Drawer edge/megin number. BUT, it didn't work for me, as those exact Field names could not be found. I run mDrawerLayout.getClass().getField() which returns all the fields, but without any luck finding what we want. Anyone?

最后一个例子 - 全code 好吧,看在例如3号,了解究竟是什么我做了之后,我们可以让它更快地通过扩展onFinishInflate()方法,并将其保存为一个全局变量 为此CustomDrawerLayout供以后使用。我们也可以把那首如果里面的第二个以节省一些更多的工作。确定这里有云:

Last Example - Full Code Ok, looking on example number 3, after understanding what exactly I did, we can make it faster by extending the onFinishInflate() method and save it as a global variable for this CustomDrawerLayout for later use. We can also put that first 'if' inside the second one to save some more work. OK here goes:

View mDrawerListView;
...

@Override
protected void onFinishInflate() {
    super.onFinishInflate();
    mDrawerListView = findViewById(R.id.drawer_listview);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    super.onTouchEvent(event);

    if(event.getX() > 30 && event.getAction() == MotionEvent.ACTION_DOWN){
        if(isDrawerOpen(mDrawerListView) || isDrawerVisible(mDrawerListView)){
            return true;
        } else{
            return false;
        }
    }

    return true;
}

这就是它了!希望它会帮助别人,将来自己身边,嘿嘿......

That's it for now! Hope it'll helps someone in the future beside myself, hehe....