一个不可见的布局在Fragment后面被点击了:

35

我已经创建了几个片段,我会以以下方式添加第一个片段:

mainFragment = (MainFragment) MainFragment.create();
    getSupportFragmentManager().beginTransaction()
    .setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right)
    .add(R.id.content, mainFragment, MAIN_FRAGMENT_TAG)
    .commit();

第二个片段是这样添加的:

     getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right)
    //.hide(mainFragment)
    .add(R.id.content,VenueFragment.create(vid), "Venue Fragment")
    .addToBackStack(null)
    .commit();
    setDrawerIndicatorEnabled(false);

现在您可以看到这个交易没有应用隐藏方法,并且打开了VenueFragment,在这种情况下的问题是,在VenueFragment打开时(它是一个全屏视图),点击该片段的空白部分会调用MainFragment可点击视图。 我该如何防止这种情况发生?

如果我使用隐藏选项,则不会发生这种情况,但由于某种原因,删除MainFragment的动画向上移动,这会产生奇怪的体验。


3
将第二个片段视图的 clickable 属性设置为 true。<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:clickable="true" /> - faiziii
@faiziii,如果你仔细看的话,你会注意到这正是被接受的答案中所指定的。 - Emil Adz
5个回答

46
你需要将 VenueFragment 的根 ViewGroup 设置为可点击,以便它处理点击事件并防止它们向下传递(按照 z-顺序)。

你的意思是在第二个Fragment中我添加了VenueFragment吗? - Emil Adz
1
好的,但即使这样能够起作用,它看起来仍然像是一个变通方法,而不是 Google 所期望的处理方式。是否有其他处理这个问题的方法? - Emil Adz
我不知道。我曾面临同样的问题,那是我找到的唯一解决方案。一定还有其他方法。 - Emmanuel
现在我们知道为什么会发生这种情况了,现在这其实有些道理。而且你的答案是最容易完成的。所以谢谢。 - Emil Adz
我必须承认,当我看到你的解决方案时,我的第一反应是“笑哭了,这什么鬼”……但它确实起作用了!谢谢。 - narancs
我理解这个逻辑,如果它仍然有效,我想知道如果在可点击的布局(ViewGroup)中有可点击文本,我们该如何处理? - bvsss

22

将第二个片段视图的可点击属性设置为true。

例如:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:clickable="true" />

7
在VenueFragment上设置一个onClickListener是可行的,但我会添加更多的解释。当你的venue fragment是透明的时候,主fragment接收到触摸事件是预期的行为。在这种情况下,可以合理地期望触摸事件穿过透明视图传递到下面的视图。因此,安卓会传递触摸事件直到它们被处理。设置一个onClickListner将处理该事件,防止它被传递给下一个视图。如果你想要"正确地"防止点击下面的fragment,有几个选项:
  1. 在OnPause中从主fragment中删除onClickListner,并在OnResume中设置它。这样,在任何时候主fragment不是活动fragment时,它都不能被点击。
  2. 在你的VenueFragment中子类化顶层布局并覆盖OnTouchEvent以返回true。这实际上与设置一个onClickListner做的事情相同,但你可能会发现它使你阻止所有触摸事件的意图更加清晰。

1
感谢您的解释和+1,但说实话,我在第一个答案中收到的选项有效,并且基本上与您的第二个选项相同,用于修复此问题。只是没有继承的混乱,然后在布局中使用此自定义类。 - Emil Adz

3

快速的答案是在片段布局的属性中,使用android:clickable="true"

然而,更好的做法是创建一个包含FrameLayout和它的id且没有其他元素的activity。每当您想要一个fragment显示在屏幕上时,调用该activity并使用。

getSupportFragmentManager().beginTransaction()
    .setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right)
    .replace(R.id.frameLayoutId, mainFragment, MAIN_FRAGMENT_TAG)
    .commit();

使用replace替代add,这样可以使得fragment的布局通过frameLayoutId指定替换activity的frameLayout


1
我有一个更好的解决方案,至少我认为是这样的 :P。
在片段事务中,使用hide和show方法。

这并不是更好的解决方案,因为有时您想要保留后面的片段(例如:当顶部片段不是全屏片段时)。在这种情况下,您需要同时保留两个片段。那么你会怎么做呢? - Emil Adz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接