Fragment.isVisible()即使在Fragment添加且可见

时间:2017-03-15 15:42:37

标签: android android-fragments android-support-library

我对Fragment.isVisible()应该如何工作感到困惑。即使我在Activity.create()中添加了片段,Fragment.isVisible()即使使用FragmentManager.commitNow()也会返回false。

Fragment.isVisible()即使在onResume()中也会返回false。但是,当单击UI按钮时,返回的值是正确的。

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

public final static String TAG = "HideFragmentOnChange";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ((Button)findViewById(R.id.my_button)).setOnClickListener(this);

    if(savedInstanceState == null){
        Fragment fragmentA = new FragmentA();

        Log.d(TAG, "onCreate: Before FragmentTransaction FragA: " + (fragmentA.isVisible() ? "visible" : "not visible"));

        getSupportFragmentManager().beginTransaction()
                .add(R.id.fragment_container, fragmentA, "fragA")
                .commitNow();

        Log.d(TAG, "onCreate: After FragmentTransaction FragA: " + (fragmentA.isVisible() ? "visible" : "not visible"));

    }

    this.runOnUiThread(new Runnable(){
        @Override
        public void run() {
            Fragment fragA = getSupportFragmentManager().findFragmentByTag("fragA");
            Log.d(TAG, "runOnUiThread after onCreate(): FragA: " + (fragA.isVisible() ? "visible" : "not visible"));
        }
    });
}

@Override
protected void onResume() {
    super.onResume();

    Fragment fragA = getSupportFragmentManager().findFragmentByTag("fragA");
    Log.d(TAG, "onResume: FragA: " + (fragA.isVisible() ? "visible" : "not visible"));

    this.runOnUiThread(new Runnable(){
        @Override
        public void run() {
            Fragment fragA = getSupportFragmentManager().findFragmentByTag("fragA");
            Log.d(TAG, "runOnUiThread after onResume(): FragA: " + (fragA.isVisible() ? "visible" : "not visible"));
        }
    });
}

@Override
public void onClick(View v) {
    Fragment fragmentA = getSupportFragmentManager().findFragmentByTag("fragA");
    Log.d(TAG, "onClick(): FragA: " + (fragmentA.isVisible() ? "visible" : "not visible"));
}

}

我最初认为也许是因为主线程还没有机会运行而且FragmentTransaction没有完全正确地提交直到稍后的点。但是,调用runOnUiThread不会更改isVisible()的返回值。

我附上日志以供参考。

03-15 17:22:34.978 14094-14094/ D/HideFragmentOnChange: onCreate: Before FragmentTransaction FragA: not visible
03-15 17:22:34.990 14094-14094/ D/HideFragmentOnChange: onCreate: After FragmentTransaction FragA: not visible
03-15 17:22:34.991 14094-14094/ D/HideFragmentOnChange: runOnUiThread after onCreate(): FragA: not visible
03-15 17:22:34.996 14094-14094/ D/HideFragmentOnChange: onResume: FragA: not visible
03-15 17:22:34.996 14094-14094/ D/HideFragmentOnChange: runOnUiThread after onResume(): FragA: not visible
03-15 17:22:56.683 14094-14094/ D/HideFragmentOnChange: onClick(): FragA: visible

为什么Fragment.isVisible()似乎以如此大的延迟返回正确的值?

我正在使用支持库25.2并支持库片段,尽管本机片段产生相同的行为。

5 个答案:

答案 0 :(得分:5)

Fragments有一种方法:

     getUserVisibleHint();

您可以在official document中找到更多信息。

当片段对用户可见时它给出“true”,当它不可见时给出“false”。

享受!

答案 1 :(得分:1)

您可以使用setUserVisibleHint

形成Documentation

  

为系统设置有关此片段的UI当前是否正确的提示   对用户可见。此提示默认为true且持久   跨片段实例状态保存和恢复。

使用它:

    private static boolean isVisible;

@Override
public void setUserVisibleHint(boolean isVisibleToUser) { 
    super.setUserVisibleHint(isVisibleToUser);
    isVisible = isVisibleToUser;

    if (isVisible) { 
        Log.d("TAG", "this fragment is visible");
    } else {  
        Log.d("TAG", "this fragment is invisible");
    }
}

答案 2 :(得分:0)

你必须记住片段也有自己的生命周期。你基本上是在过早地调用它。如果

,则认为片段可见

Fragment#isVisible

  

如果片段当前对用户可见,则返回true。这意味着它:(1)已被添加,(2)将其视图附加到窗口,并且(3)不被隐藏。

请参阅此SO帖子,了解Activity / Fragment的生命周期 When is onAttach called during the Fragment LifeCycle?

答案 3 :(得分:0)

我注意到在打开一个片段并经历了整个生命周期 (onAttach,onCreate,onStart等..),从onResume()调用isVisible()将返回 false 。但是,如果您只停止片段(即按下主页按钮),则isVisible()将返回 true 。 结论:保留一个类布尔标志:

   private mFirstTimeVisible = true;

并在以下onResume检查中使用它:

   @Override
   public void onResume() {
       super.onResume();
       if (mFistTimeVisible || isVisible()) { 
          //your code...
       }
       mFistTimeVisible = false;
    }

答案 4 :(得分:0)

我找到了解决方法,只是稍微延迟才调用isVisible

 @Override
       public void onResume() {
           new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                Log.d("ONRESUME", isVisible() );
            }
        }, 100);
           
 }