检测隐藏片段中的视图可见性

Detect view visibility in hidden fragment

当视图属于 shown/hidden 时,是否有任何方法可以检测视图是否改变了可见性?

该片段有一个方法onHiddenChanged()来通知可见性的变化。

然而,当视图与 window 连接或分离时,它只有回调通知。有没有什么方法可以检测视图内的可见性变化(不是通过片段调用public视图方法)?

这些是我测试过的方法:

  • onAttachedToWindow():未在片段 show() / hide()
  • 上调用
  • onDetachedFromWindow():未在片段 show() / hide()
  • 上调用
  • getGlobalVisibilityRect(): returns 真(可见)无论片段是否 shown/hidden

重要提示:视图是独立的。它不能引用片段,反之亦然,片段不能调用视图上的任何方法。

或者,是否有任何方法可以在不破坏其视图的情况下将片段的视图层次结构与 window 分离?

关于第一个问题,ViewTreeObserver.OnGlobalLayoutListener可能有效。

yourView.setTag(yourView.getVisibility());  //set this somewhere in your code, maybe after you create the view

yourView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

    @Override
    public void onGlobalLayout() {
        int newVisibility = yourView.getVisibility();
        if((int)yourView.getTag() != newVisibility)
        {
            Log.d("VISIBILITY_CHANGE", "Visibility Changed");
        }
    }
});

关于你的第二个问题,是的,有一种方法可以在不破坏片段的情况下将片段的视图层次结构与 window 分离。您可以使用 FragmentTransaction class 的 detach() 方法。

getSupportFragmentManager().beginTransaction().detach(fragment).commit();

Detach the given fragment from the UI. This is the same state as when it is put on the back stack: the fragment is removed from the UI, however its state is still being actively managed by the fragment manager. When going into this state its view hierarchy is destroyed.

@bigO 的回答非常有效,但是有一个更简单的解决方案:

@Override
protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
    super.onVisibilityChanged(changedView, visibility);
    Log.d(TAG, visibility == View.VISIBLE ? "visible" : "invisible");
}

每次片段 shown/hidden 的值分别为 View.VISIBLEView.GONE

时,都会调用此视图方法