片段超过另一个片段问题


271

当我#77000000在另一个片段(我们称其为主要片段)上显示一个片段(背景为全屏)时,我的主要片段仍会对点击做出反应(即使没有看到也可以单击按钮)。

问题:如何防止点击第一个(主要)片段?

编辑

不幸的是,我不能只隐藏主片段,因为我在第二个片段上使用了透明背景(因此,用户可以看到后面的内容)。


根据你给我们的工作着,你应该尝试设置Visibility您的main FragmentGONE,当你不使用它。
adneal 2012年

1
在不了解如何实现onClicked方法的情况下,我猜测单击时返回的是“ false”。
DeeV 2012年

@DeeV,onClick方法不返回任何内容。但是,您有个好主意,谢谢(我会尽快答复)。
德米特里·扎伊采夫2012年

1
天啊 你是对的。onTouch返回它。我只是希望我能理解为什么触摸事件会破裂。如果您不发布触摸事件,则不应这样做。
DeeV 2012年

@DeeV,如果您的视图(例如,在其他视图之上)没有捕获onTouch事件,则系统会继续搜索具有相同坐标的其他视图。
德米特里·扎伊采夫2012年

Answers:


578

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" />

4
这对我有用。看来比@Dmitry Zaitsev上面提供的解决方案容易。有什么理由为什么这是个坏主意?我似乎什么也没想,但我只想确定。
2013年

1
这对我不起作用。我RelativeLayout在片段中有一个内部,并使用clickeable属性设置了整个视图。@Dmitry的解决方案解决了我的问题。
13年

3
这对我有用。Android中的“ clickable”显然类似于iOS的“ userInteractionEnabled”
mvds 2014年

17
Android为什么要使我们经受苛刻的编码条件?!
罗坦

1
我在ViewPager上遇到了同样的问题。当我在第一页上滚动时,它也会传递到第二页,此解决方案对我不起作用。有任何想法吗?
Gokhan Arik 2015年

72

解决方案非常简单。在第二个片段(与主片段重叠)中,我们只需要捕获onTouch事件:

@Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstance){
    View root = somehowCreateView();

    /*here is an implementation*/

    root.setOnTouchListener(new View.OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
            return true;
        }
    });
    return root;
}

您的解决方案为此工作+1,但是您能告诉我为什么我们需要明确地这样做吗?
2014年

@亨特,你不必。那只是做到这一点的另一种方式(请参见已接受的答案)
德米特里·扎伊采夫

android:clickable =“ true”在第二个片段的xml主布局中。
Rishabh Srivastava 2015年

该解决方案存在一个问题,当您进入可访问性对讲模式为ON时,它将不读取单个元素,而是将焦点集中到根视图。
阿米特·加格

Kotlin版本:root.setOnTouchListener {_,_-> true}
Gal Rom

21

只需添加clickable="true"并添加focusable="true"到父布局

 <android.support.constraint.ConstraintLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:clickable="true"
      android:focusable="true">

      <!--Your views-->

 </android.support.constraint.ConstraintLayout>

如果您正在使用AndroidX,请尝试此

 <androidx.constraintlayout.widget.ConstraintLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:clickable="true"
      android:focusable="true">

          <!--Your views-->

 </androidx.constraintlayout.widget.ConstraintLayout>

这与接受的答案有什么不同吗?focuseable并不是必须的。
德米特里·扎伊采夫

2
我认为focusable="true"这里只是为了避免在Android Studio中发出警告。
Artem M

9

如果在同一容器视图中放置了两个片段,则在显示第二个片段时应隐藏第一个片段。

如果您想了解有关如何解决Fragment问题的更多问题,可以查看我的库:https : //github.com/JustKiddingBaby/FragmentRigger

FirstFragment firstfragment;
SecondFragment secondFragment;
FragmentManager fm;
FragmentTransaction ft=fm.beginTransaction();
ft.hide(firstfragment);
ft.show(secondFragment);
ft.commit();

1
这应该是正确的答案!谢谢你,兄弟。我在另一个项目上解决了这个问题。但是我忘记了如何解决它,最后,我得到了你的答案。谢谢。
Licat Julius

1
我认为这不是正确的解决方案。片段/活动在视图堆栈中工作。从堆栈中弹出顶部片段后,您必须再次调用.show,这意味着必须通知底部片段顶部的片段已消失。它只是添加了额外的逻辑来维护。
XY

4

您需要添加 android:focusable="true"android:clickable="true"

Clickable 表示可以通过指针设备单击它或通过触摸设备点击它。

Focusable表示它可以从键盘等输入设备获得焦点。诸如键盘之类的输入设备无法根据输入本身来决定将其输入事件发送到哪个视图,因此它们会将它们发送到具有焦点的视图。


2
和可聚焦=“true”是必需的,以避免在新的Android Studio中的一个警告
霍山哈桑

2

我们中的一些人为此线程提供了不止一种解决方案,但我还要提及另一种解决方案。如果您不愿意,那么像我一样,将clickable和focusable等同于XML中每个布局的根ViewGroup。如果您有一个像下面这样的产品,也可以将其放在基础上。

override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ) : View? {
        super.onCreateView(inflater, container, savedInstanceState)

        val rootView = inflater.inflate(layout, container, false).apply {
            isClickable = true
            isFocusable = true
        }

        return rootView
    }

您也可以使用内联变量,但由于我的原因,我不喜欢它。

我希望它对那些讨厌布局XML的人有所帮助。


1

可接受的答案将“起作用”,但由于仍在绘制底部的片段,因此还会导致性能成本(透支,方向变化时重新测量)。也许您只需要按标签或ID查找片段,然后在需要再次显示时将可见性设置为GONE或VISIBLE。

在科特林:

fragmentManager.findFragmentByTag(BottomFragment.TAG).view.visibility = GONE

此解决方案优于使用动画时的替代方法hide()show()方法FragmentTransaction。您只需从onTransitionStart()和中onTransitionEnd()的调用它Transition.TransitionListener


1

方法1:

您可以添加到所有片段布局

android:clickable="true"
android:focusable="true"
android:background="@color/windowBackground"

方法2 :(以编程方式)

扩展FragmentBaseetc中的所有片段。然后将此代码添加到FragmentBase

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    getView().setBackgroundColor(getResources().getColor(R.color.windowBackground));
    getView().setClickable(true);
    getView().setFocusable(true);
}

0

您可以做的是,可以通过使用onClick属性为该主要片段的父级布局对上一个片段的布局进行空白单击,并且在活动中您可以创建一个函数,doNothing(View view)而无需在其中编写任何内容。这将为您做到。


0

这听起来像DialogFragment的情况。否则,使用Fragment Manager提交,一个隐藏,另一个显示。那对我有用。


0

的添加android:clickable="true"对我不起作用。当它是父布局时,此解决方案不适用于CoordinatorLayout。这就是为什么我将RelativeLayout设为父级布局,将android:clickable="true"其添加到其中并将CoordinatorLayout放置在此RelativeLayout上的原因。


0

我有多个具有相同xml的片段。
花了几个小时后,我将setPageTransformer其移除并开始工作

   //  viewpager.setPageTransformer(false, new BackgPageTransformer())

我有缩放逻辑。

public class BackgPageTransformer extends BaseTransformer {

    private static final float MIN_SCALE = 0.75f;

    @Override
    protected void onTransform(View view, float position) {
        //view.setScaleX Y
    }

    @Override
    protected boolean isPagingEnabled() {
        return true;
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.