조각 수명주기-표시 / 숨기기시 어떤 메서드가 호출됩니까?


99

다음 방법을 사용하여 조각을 표시 / 숨겨서 (내 NavigationDrawer에서) 조각간에 전환합니다.

protected void showFragment(int container, Fragment fragment, String tag, String lastTag, boolean addToBackStack ) {

        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();

        if ( lastTag != null && !lastTag.equals("")) {
            Fragment lastFragment = fragmentManager.findFragmentByTag( lastTag );
            if ( lastFragment != null ) {
                transaction.hide( lastFragment );
            }
        }

        if ( fragment.isAdded() ) {
            transaction.show( fragment );
        }
        else {
            transaction.add( container, fragment, tag );
        }

        if ( addToBackStack ) {
            transaction.addToBackStack( tag );
        }

        transaction.commit();

        // set the active tag
        activeFragTag = tag;
    }

내가 명확하지 않은 것은 Fragments 수명주기의 어떤 메소드를 표시하거나 숨길 때 호출되는지입니다. (onShow () 또는 onHide ()와 같은 메소드가 없기 때문에 무엇을 사용 해야할지 모르겠습니다.) 특정 조각을 표시하고 숨길 때 특정 작업을 수행하고 싶습니다.


Fragment.show () 를 호출하면 나중에 어느 시점에서 조각이 트리거 onCreate()되고 onCreateDialog(), 다음에onCreateView()
Someone Somewhere

답변:


122

액티비티 수명주기와 마찬가지로 Android는 조각이 표시되면 onStart ()를 호출합니다 . onStop()일반적으로 조각이 보이지 않을 때 호출되지만 나중에 호출 될 수도 있습니다.

레이아웃에 따라 Android는 onStart()Fragment가 아직 표시되지 않지만 표시되는 상위 컨테이너에 속할 때도 호출 할 수 있습니다 . 예를 들어, 메서드 android.support.v4.view.ViewPager를 재정의해야하는 경우에 유효합니다 Fragment.setUserVisibleHint(). 어쨌든 BroadcastReceivers 또는 다른 리스너를 등록 / 등록 해제해야하는 경우 onStart()onStop()메서드는 항상 호출되므로 안전하게 사용할 수 있습니다 .

참고 : 일부 조각 컨테이너는 보이지 않는 조각을 시작 상태로 유지할 수 있습니다. 이 상황을 처리하기 위해 Fragment.onHiddenChanged(boolean hidden). 문서 에 따르면 사용자가 볼 수 있도록 조각이 시작되고 표시 되어야합니다 (숨겨지지 않음) .

업데이트 : 사용 android.support.v4.widget.DrawerLayout하면 서랍 아래의 조각이 시작된 상태로 유지되고 서랍이 열려 있어도 표시됩니다. 이 경우 및 콜백 을 사용 DrawerLayout.setDrawerListener()하고 수신 해야합니다 .onDrawerClosed()onDrawerOpened()


14
onStop그리고 onPause조각이 트랜잭션을 사용하여 눈에 보이지 않는 될 때 호출되지 않습니다. 그럼에도 불구하고 onHiddenChangeds1rius 답을 알 수 있듯이라고
요안 Hercouet

이것은 NavigationDrawer에서 작동하지 않습니다. onHiddenChanged는 v4 / v11 지원 lib에서 호출되지 않습니다. onStart 및 onResume은 서랍 레이아웃이 열릴 때마다 호출되지 않습니다.
drdrej

@drdrej 문제는 서랍이 아래의 조각을 완전히 숨기지 않는다는 것입니다. 지원 라이브러리에서 DrawerLayout을 사용하는 경우 DrawerListener를 사용해야합니다.
sergej shafarenka

69

이 방법을 @Override하고 내 문제를 해결합니다.

@Override
public void onHiddenChanged(boolean hidden) {
    super.onHiddenChanged(hidden);
    if (hidden) {
        //do when hidden
    } else {
       //do when show
    }
}

1
어떤 해결하기 위해 시도했지만 사용 setUserVisibleHint과 같이 stackoverflow.com/a/18375436/1815624의 작품
CrandellWS

36

물론 다음 메서드를 @Override하여 수행 할 수 있습니다.

@Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {
            // Do your Work
        } else {
            // Do your Work
        }
    }

그리고 다음을 호출하여 조각이 사용자에게 표시되는지 여부를 쉽게 알 수 있습니다.getUserVisibleHint()
ARiF

2
setUserVisibleHint는 뷰 페이저에서 작동하지만 일반 조각 컨테이너에서는 작동하지 않습니다.
MikeL

덕분에이 해결 내 문제 :
라 제쉬 쿠마르 ARUMUGAM

이것은 ViewPager에서 나를 위해 일했습니다. onHiddenChanged가 작동하지 않았습니다.
라이브 러브

내 문제를 해결했습니다!
Jad Chahine 2019

3

뷰 페이저 동작의 조각은 일반 조각 컨테이너와 다릅니다.

이 코드를 시도하십시오.

    boolean mIsVisibleToUser;

    /**
     * is visible to user
     */
    public void show() {
        //do when show
    }

    /**
     * is invisible to user
     */
    public void hide() {
        //do when gone
    }

    @Override
    public void onResume() {
        super.onResume();
        if (!mIsVisibleToUser && getUserVisibleHint()) {
            mIsVisibleToUser = true;
            show();
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        if (mIsVisibleToUser && getUserVisibleHint()) {
            mIsVisibleToUser = false;
            hide();
        }
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isResumed()) {
            if (mIsVisibleToUser != isVisibleToUser) {
                mIsVisibleToUser = isVisibleToUser;
                if (isVisibleToUser) show();
                else hide();
            }
        }
    }

    public boolean isVisibleToUser() {
        return mIsVisibleToUser;
    }

2

이 코드를 시도하십시오.

@Override
public void setUserVisibleHint(boolean visible)
{
    super.setUserVisibleHint(visible);
    if (visible && isResumed())
    {
         onResume();
    }
}

@Override
public void onResume()
{
    super.onResume();
    if (!getUserVisibleHint())
    {
        return;
    }

    //Add your code this section
}

2

'onCreateView'(또는 'onActivityCreated') 및 'onHiddenChanged'를 사용할 수 있습니다. 첫 번째 쇼에는 'onCreateView'를 사용하고 나중에는 'onHiddenChanged'를 사용하십시오. 'setMenuVisibility'는 트랜잭션 제어에서 호출되지 않습니다.

@Override
public View OnCreateView() {
   // fragment will show first
}

@Override
public void onHiddenChanged(boolean hidden) {
    if (!hidden) {
        // fragment will show 
    }
    else {
        // fragment will hide
    }
}

onHiddenChanged ()가 내 프래그먼트와 함께 호출되지 않습니다
matdev

1

setUserVisibleHint () 에서 이것을 시도하십시오.

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if(isVisibleToUser && getView() != null){
        isActive = true;
        init();
    }else if(isVisibleToUser && getView() == null){
        isActive = false;
    }else{
        isActive = true;
    }
}

그리고 onCreateView () 에서 다음 코드를 만듭니다 .

public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
  if(!isActive){
      init();
  }
}

isVisibleToUser && getView() != null나를 위해 완벽하게 작동했습니다!
bobby

1

조각이 표시되고 활동에서 뷰 페이지를 사용하는 경우 조각 메서드를 호출하는 또 다른 방법입니다.

// 먼저 인터페이스를 만듭니다.

public interface ShowFragmentVisible{
      public void showFragment();}

// 그 후이 인터페이스는 Fragment 내부에서 구현됩니다.

      public class MyFragment extends Fragment implements 
         ShowFragmentVisible {
            @Override
public void showFragment() {
}

// 이제 Activity로 이동하여 인터페이스 개체를 만들고 addOnViewpagerListener가 호출되면 내부를 호출합니다.

   ShowFragmentVisible showFragmentVisible;

@Override
public void onAttachFragment(Fragment fragment) {
    super.onAttachFragment(fragment);

    if (fragment instanceof ShowFragmentVisible) {
        showFragmentVisible = (ShowFragmentVisible) fragment;
    }

}
     //your viewpager method
    viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageSelected(int position) {
            if (position==0){
                showFragmentVisible.showFragment();

           }

        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });


this is another alternative,but its work for me successfully

0

setUserVisibleHint전에 전화하십시오 onCreateView. 내가 사용하는 setUserVisibleHint 내부의 뷰를 업데이트 할 수 없습니다.

public void setMenuVisibility(final boolean visible)

가시성을 위해 onHiddenChanged ()는 처음으로 호출하지 않았습니다 . 숨겨진 상태가 변경 될 때 호출됩니다. 때문에 fragment is visible by default. 이 방법을 처음으로 얻으려면 호출 mFragmentTransaction.hide(oldFragment)해야합니다.

노트

setUserVisible 힌트를 사용하고 View를 업데이트 하려면이 방법을 사용하십시오.


0

물론 setUserVisibleHintor를 재정의 할 수 setMenuVisibility있지만 Context또는 액세스해야하는 경우 Activity에는 null이됩니다! 다른 방법이 있습니다onStart항상 컨텍스트를 사용할 수있는 가 있지만 조각 생성시 한 번만 호출되며 호출기에서 조각 사이를 이동하기 시작하면 두 번째보기에서 호출되지 않고 나중에 호출되지 않는다는 것을 알 수 있습니다. .

그럼 .. 이제 어떡해?

해결 방법은 매우 간단 onStart하며 첫 방문과 setMenuVisibility이후 방문에 사용 합니다. 코드는 다음과 같습니다.

조각 클래스 :

public class MyFragmentClass{
    private boolean isCurrentVisible = false;
...

@Override
public void onStart() {
    super.onStart();
    if (isCurrentVisible)
        doSth();
}

@Override
public void setMenuVisibility(boolean menuVisible){
    super.setMenuVisibility(menuVisible);
    this.isCurrentVisible = menuVisible;
    if(menuVisible && getContext() != null)
        doSth();
}

이 방법 Context은 항상 doSth()메소드에서 사용할 수 있습니다 .


0

이것은 나를 위해 일했습니다!! 그리고 setUserVisibleHint(...)이제 더 이상 사용되지 않습니다 (끝에 문서를 첨부했습니다). 즉, 다른 답변이 더 이상 사용되지 않음을 의미합니다 ;-)

public class FragmentFirewall extends Fragment {
    /**
     * Required cause "setMenuVisibility(...)" is not guaranteed to be
     * called after "onResume()" and/or "onCreateView(...)" method.
     */
    protected void didVisibilityChange() {
        Activity activity = getActivity();
        if (isResumed() && isMenuVisible()) {
            // Once resumed and menu is visible, at last
            // our Fragment is really visible to user.
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        didVisibilityChange();
    }

    @Override
    public void setMenuVisibility(boolean visible) {
        super.setMenuVisibility(visible);
        didVisibilityChange();
    }
}

테스트와 작품 NaviagationDrawer아니라, 거기로 isMenuVisible()항상 돌아갑니다 true(그리고 onResume()충분히 보이지만, 우리는 지원하려는 ViewPager너무).

setUserVisibleHint더 이상 사용되지 않습니다. 이 메소드를 재정의하는 경우에 전달할 때 동작이 구현 true이동해야 Fragment.onResume()하며 통과 할 때의 동작이 실행 false으로 이동한다 Fragment.onPause().

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.