另一个片段问题的片段

Posted

技术标签:

【中文标题】另一个片段问题的片段【英文标题】:Fragment over another fragment issue 【发布时间】:2012-05-10 12:04:30 【问题描述】:

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

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

编辑

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

【问题讨论】:

根据您提供给我们使用的内容,您应该尝试在不使用时将您的main FragmentVisibility 设置为GONE 没有看到你如何实现你的 onClicked 方法,我猜你在点击时返回“false”。 @DeeV, onClick 方法不返回任何内容。但是你给出一个想法,谢谢(我会尽快发布答案)。 哦。你说得对。 onTouch 返回它。我只是希望我能理解为什么一个触摸事件会从一个片段中消失。如果您不发出触摸事件,则不应这样做。 @DeeV,看起来如果您的视图(例如在其他视图之上)没有捕获 onTouch 事件,那么系统会继续搜索具有相同坐标的其他视图。 【参考方案1】:

解决方案非常简单。在我们的第二个片段(与我们的主片段重叠)中,我们只需要捕获 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,但您能告诉我为什么我们需要明确地这样做吗? @Hunt 你不必这样做。这只是另一种方法(请参阅接受的答案) android:clickable="true" 在第二个片段的 xml 主布局上。 这个解决方案有一个问题,当您进入辅助功能对讲模式时,它不会读取单个元素,而是将焦点转移到根视图。 Kotlin 版本:root.setOnTouchListener _, _ -> true【参考方案2】:

将第二个片段视图上的clickable 属性设置为true。视图将捕获事件,以便它不会传递给主片段。所以如果第二个片段的视图是一个布局,这将是代码:

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

【讨论】:

这对我有用。这似乎比@Dmitry Zaitsev 上面给出的解决方案更容易。有什么理由说明这是一个坏主意吗?我似乎想不出来,但我只是想确定一下。 这对我不起作用。我在片段中有一个RelativeLayout,我使用clickeable 属性设置了整个视图。 @Dmitry 的解决方案解决了我的问题。 这对我有用。 Android 中的“可点击”显然有点像 ios 的“userInteractionEnabled” 为什么 Android 会让我们面临苛刻的编码条件?! 我在使用 ViewPager 时遇到了同样的问题。当我在第一页滚动时,它也传递到第二页,这个解决方案对我不起作用。有什么想法吗?【参考方案3】:

你可以做的是你可以通过使用 onClick 属性来给前一个片段的布局一个空白点击该主片段的父布局,并且在活动中你可以创建一个函数doNothing(View view) 并且不要在其中写入任何内容。这将为您完成。

【讨论】:

【参考方案4】:

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

【讨论】:

【参考方案5】:

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

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

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

【讨论】:

这应该是正确的答案!谢谢你,兄弟。我已经在另一个项目中解决了这个问题。但我忘记了我是如何解决的,最后,我得到了你的答案。谢谢。 我认为这不是正确的解决方案。片段/活动在视图堆栈中工作。将顶部片段从堆栈中弹出后,您必须再次调用 .show,这意味着必须通知底部片段,顶部片段已消失。它只是添加了额外的逻辑来维护。【参考方案6】:

只需将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_
      android:layout_
      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_
      android:layout_
      android:clickable="true"
      android:focusable="true">

          <!--Your views-->

 </androidx.constraintlayout.widget.ConstraintLayout>

【讨论】:

这与接受的答案有什么不同吗? focuseable 没有必要。 我认为focusable="true" 只是为了避免在 Android Studio 中出现警告。【参考方案7】:

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

【讨论】:

【参考方案8】:

可接受的答案将“有效”,但也会导致性能成本(过度绘制,重新测量方向变化),因为底部的片段仍在绘制中。也许您应该简单地通过标签或 ID 找到片段,并在需要再次显示时将可见性设置为 GONE 或 VISIBLE。

在 Kotlin 中:

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

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

【讨论】:

【参考方案9】:

我有多个具有相同 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;
    

【讨论】:

【参考方案10】:

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

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

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

【讨论】:

并且需要 focusable="true" 以避免在新的 Android Studio 中出现警告【参考方案11】:

方法一:

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

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

方法 2:(以编程方式)

FragmentBase等扩展所有片段,然后将此代码添加到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);

【讨论】:

【参考方案12】:

我们中的一些人为此线程贡献了不止一种解决方案,但我还想提一下另一种解决方案。如果您不喜欢像我一样在 XML 中将可点击和可聚焦等于 true 的每个布局的根 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 的人有所帮助。

【讨论】:

以上是关于另一个片段问题的片段的主要内容,如果未能解决你的问题,请参考以下文章

Android - 如何将一个片段放在另一个片段上

使用意图从另一个片段调用一个片段

改变另一个片段的片段(列表)

片段与另一个片段重叠

与另一个片段通信的片段接口

片段中的视频视图与另一个片段重叠