ViewPager에서 조각 검색


248

세 가지 조각을 호스팅 ViewPager하기 FragmentStatePagerAdapter위해 와 함께 사용하고 있습니다 .

  • [Fragment1]
  • [Fragment2]
  • [Fragment3]

나는 싶어 할 때 Fragment1으로부터 ViewPager에서 FragmentActivity.

무엇이 문제이며 어떻게 해결합니까?

답변:


504

주요 답변은 프레임 워크에서 생성되는 이름에 의존합니다. 이것이 변경되면 더 이상 작동하지 않습니다.

이 솔루션에 대해 무엇을, 무시 instantiateItem()하고destroyItem() 당신의 Fragment(State)PagerAdapter:

public class MyPagerAdapter extends FragmentStatePagerAdapter {
    SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();

    public MyPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public int getCount() {
        return ...;
    }

    @Override
    public Fragment getItem(int position) {
        return MyFragment.newInstance(...); 
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Fragment fragment = (Fragment) super.instantiateItem(container, position);
        registeredFragments.put(position, fragment);
        return fragment;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        registeredFragments.remove(position);
        super.destroyItem(container, position, object);
    }

    public Fragment getRegisteredFragment(int position) {
        return registeredFragments.get(position);
    }
}

이것은 사용 가능한 조각을 다룰 때 나에게 효과가있는 것 같습니다. 아직 인스턴스화되지 않은 조각은을 호출 할 때 null을 반환 getRegisteredFragment합니다. 그러나 나는 이것을 전류를 Fragment꺼내기 위해 주로 사용했습니다 .ViewPager : adapater.getRegisteredFragment(viewPager.getCurrentItem())이것은 반환하지 않습니다 null.

이 솔루션의 다른 단점은 없습니다. 있다면, 알고 싶습니다.


41
이것은 내가 생각할 수있는 최고의 솔루션입니다. 파괴 된 조각이 가비지 수집되지 않도록 보장하기 위해를 포장 Fragment하는 WeakReference것이 좋습니다. 그냥 옳은 일처럼 보인다 ...
Alex Lockwood

7
MyPagerAdapter수명주기 (예 : 회전)로 인해 파괴 되면 어떻게됩니까 registerdFragments? 는 것 Activity/ Fragment사용 MyPagerAdapter에 저장해야 onSaveInstanceState하고 새로 업데이트 할 필요가 FragmentManager심판?
Steven Byle

10
내가 실수하지 않으면 (그리고 이것을 확인해야한다면) getItem 메소드는 알다시피 호출되지 않지만 회전 후 프레임 워크에 의해 복원되는 모든 Fragment에 대해 instantiateItem 메소드가 호출됩니다.
보스턴의 거리

6
예 , 페이저에서 보유한 상태를 복원하기 getItem때문에 회전 할 때 (이미 생성 된 조각에 대해) 다시 호출되지 않는 것을 확인했습니다 . 경우 각각의 경우에 불려 복원,이 솔루션은 사실에 더 안전하고 미래의 증거 광산 또는 허용 대답보다. 나는 이것을 직접 시도하는 것을 고려할 것이다. FragmentManagerFragmentsinstantiateItemFragment
Steven Byle

6
@Dori 나는 그것을 깨뜨리지 않습니다. 내 솔루션은 'getItem ()'호출의 결과를 사용하지 않습니다. 대신 'instantiateItem ()'호출에서 저장된 결과를 사용하고 있습니다. 저장된 조각은 'destroyItem ()'호출의 희소 배열에서 제거되므로 조각의 수명주기가 손상되지 않습니다.
보스턴의 거리

85

ViewPager에서 조각을 잡으려면 여기 및 기타 관련 SO 스레드 / 블로그에 많은 답변이 있습니다. 내가 본 사람은 모두 부서졌으며 일반적으로 아래에 나열된 두 가지 유형 중 하나에 해당하는 것 같습니다. 이처럼 현재 조각 만 잡고 싶다면 다른 유효한 솔루션 이 있습니다. 이 스레드에서 다른 대답.

사용하는 경우 FragmentPagerAdapter아래 를 참조하십시오. 이것FragmentStatePagerAdapter 의 가치를 사용 하는 경우 . FragmentStateAdapter에서 현재 인덱스가 아닌 인덱스를 가져 오는 것은 그 특성에 따라 유용하지 않습니다. 인덱스가 완전히 종료되거나 offScreenLimit 범위를 벗어났습니다.

불행한 길

잘못됨 : FragmentPagerAdapter.getItem()호출 될 때 추가 된 자체 내부 조각 목록 유지

  • 일반적으로 사용 SparseArray또는Map
  • 내가 본 많은 예제 중 하나도 수명주기 이벤트를 설명하지 않으므로이 솔루션은 취약합니다. 으로 getItem만 페이지에 스크롤이 처음이라고합니다 (또는 경우 얻을 당신의 ViewPager.setOffscreenPageLimit(x)> 0)에서 ViewPager호스팅이 경우, Activity/ Fragment후 사망하거나 재시작 할 때 내부는 SpaseArray사용자 정의 FragmentPagerActivity 다시 만들 때 전멸됩니다 만, 뒤에서 ViewPagers 내부 조각 재 작성됩니다 및 getItem합니다 NOT 인덱스의 요구 될 수 있으므로 인덱스에서 조각을 얻을 수있는 능력은 영원히 손실됩니다. 당신은 밖으로 절약을 통해 이러한 단편 참조를 복원하여 설명 할 수 FragmentManager.getFragment()putFragment하지만 시작은 지저분한 이럴을 얻을 수 있습니다.

잘못 : 후드에서 사용 된 것과 일치하는 자신의 태그 ID를 구성FragmentPagerAdapter 하고 이것을 사용하여 페이지 조각을 검색하십시오.FragmentManager

  • 이 최초의 내부 배열 솔루션에서 패배 한 - 조각 - 참조 문제 대처 이것은 더 나은 지라,하지만 바로 위의 다른 곳에 그물에 대한 답변에서 지적 - 그것은 그것으로 해키 느낌이 개인 내부의 방법 ViewPager즉 수 언제든지 또는 모든 OS 버전을 변경할 수 있습니다.

이 솔루션에 대해 재현 된 방법은

private static String makeFragmentName(int viewId, long id) {
    return "android:switcher:" + viewId + ":" + id;
}

행복한 길 : ViewPager.instantiateItem()

getItem()위와 비슷 하지만 수명주기를 벗어나지 않는 비슷한 방법 은 인덱스를 만들거나 액세스 할 때마다 전자가 호출되므로 instantiateItem()대신 연결하는 것입니다 getItem(). 이 답변을 참조하십시오

행복한 길 : 자신 만의 길을 만드십시오 FragmentViewPager

최신 지원 libFragmentViewPager소스 에서 사용자 고유의 클래스를 구성 하고 조각 태그를 생성하기 위해 내부적으로 사용되는 메소드를 변경하십시오. 아래와 같이 교체 할 수 있습니다. 이는 태그 생성이 절대 변경되지 않으며 항상 개인 API / 메소드에 의존하지 않는다는 이점이 있습니다.

/**
 * @param containerViewId the ViewPager this adapter is being supplied to
 * @param id pass in getItemId(position) as this is whats used internally in this class
 * @return the tag used for this pages fragment
 */
public static String makeFragmentName(int containerViewId, long id) {
    return "android:switcher:" + containerViewId + ":" + id;
}

doc이 말했듯이 인덱스에 사용 된 조각을 가져 오려면 getItem이 아직 호출되지 않은 경우 FragmentPagerAdapter결과 가 null수 있음을 인식 하고이 메소드와 같은 것을 호출하십시오 (사용자 정의 또는 하위 클래스에 넣을 수 있음) 해당 페이지 즉, 아직 작성되지 않은 페이지입니다.

/**
 * @return may return null if the fragment has not been instantiated yet for that position - this depends on if the fragment has been viewed
 * yet OR is a sibling covered by {@link android.support.v4.view.ViewPager#setOffscreenPageLimit(int)}. Can use this to call methods on
 * the current positions fragment.
 */
public @Nullable Fragment getFragmentForPosition(int position)
{
    String tag = makeFragmentName(mViewPager.getId(), getItemId(position));
    Fragment fragment = getSupportFragmentManager().findFragmentByTag(tag);
    return fragment;
}

이것은 간단한 솔루션이며 웹 어디에서나 발견되는 다른 두 가지 솔루션의 문제를 해결합니다.


6
이것은 작동하지만 ViewPager 클래스를 자신의 소스 코드에 복사해야합니다. ViewPager의 호출기 어댑터의 'instantiateItem ()'및 'destroyItem ()'에 의존하면 조각의 수명주기가 작동하고 조각화됩니다 (이 두 가지 방법은 조각이 저장된 인스턴스 상태에서 생성 될 때도 호출됩니다). 'getItem ()'에 의존하는 것은 좋은 생각이 아니며 개인 API를 사용하는 것도 좋지 않습니다.
보스턴의 거리

+1 나는 이것이 또한 해결책이며 위의 편집에 동의합니다. 유일한 차이점은 위의 내용 은 수명주기 이벤트가 발생한 instantiateItem() 아직 방문하지 않고 수명주기 이벤트 전에 방문한 프래그먼트에 액세스하려는 경우의 하나 이상의 사용 사례에서 작동한다는 것 입니다 . 내가 아는 작은 차이점이지만 내 프로그램에 미묘한 버그가 생겨서 이것을 조사하고 있습니다.
Dori

setOffscreenPageLimit = 1 (기본값) 인 경우 FragmentStatePageAdapter는 뷰 페이지에 액세스 할 때 메모리 내외부 프래그먼트 교환을 시작합니다. getItem ()을 호출하면 다시 방문한 페이지 / 조각의 새 인스턴스가 작성됩니다. 이러한 재 방문시, 시스템에 새 인스턴스를 작성하지 않고 이전에 작성된 인스턴스를 재개하도록 지시하는 방법이 있습니까?
carl

페이지 제한을 벗어나면 새 것을 만들어야하지만 저장된 상태로 전달해야합니다. 오래된 것을 유지하려면 페이지 제한을 늘릴 수 있습니다
Dori

@Dori getItemId(pos)내부 는 없습니다FragmentStatePagerAdapter
Jemshit Iskenderov

70

FragmentPagerAdapter에 다음 메소드를 추가하십시오.

public Fragment getActiveFragment(ViewPager container, int position) {
String name = makeFragmentName(container.getId(), position);
return  mFragmentManager.findFragmentByTag(name);
}

private static String makeFragmentName(int viewId, int index) {
    return "android:switcher:" + viewId + ":" + index;
}

getActiveFragment (0)이 작동해야합니다.

다음은 ViewPager https://gist.github.com/jacek-marchwicki/d6320ba9a910c514424d에 구현 된 솔루션 입니다. 무언가 실패하면 좋은 충돌 로그가 표시됩니다.


고마워요 :). 통해 다른 방법으로 처리기를 사용하여 조각을 게시했습니다. 이것은 매우 적합하지는 않지만 마침내 문제를 해결했습니다. 그건 그렇고, 당신은 훌륭합니다 :)
Qun Qin

12
이 방법을 사용하고 있었지만 API 17 (?)으로 옮길 때 작동이 중지되었다고 생각합니다. 다른 방법을 추천하고 Google이 위치에 따라 ViewPager에서 Fragment를 검색하는 API를 게시 한 경우 선호합니다.
gcl1 2019

나는 두 번째 조각을 부르는 데 문제가 있습니다.이 방법은 새로운 조각을 만듭니다
Vasil Valchev

2
일부 API 버전 makeFragmentName 메소드가 개인용 정적 문자열로 변경되었으므로 String makeFragmentName (int viewId, long id) {return "android : switcher :"+ viewId + ":"+ id; } 이제 getActiveFragment 메소드는 다음과 같아야합니다 (두 번째 인수에 위치 대신 getItemId 사용) public Fragment getActiveFragment (ViewPager container, int position) {String name = makeFragmentName (container.getId (), getItemId (position)); 반환 mFragmentManager.findFragmentByTag (이름); }
유진 포포비치

1
실제로 작동하지만 뷰 호출기의 내부 구현을 중계하고 Google이 구현을 변경하면 나쁜 일이 발생할 수 있습니다. 나는 goole이 라이브 프래그먼트를 얻을 수있게되기를 바랍니다
shem

38

또 다른 간단한 해결책 :

    public class MyPagerAdapter extends FragmentPagerAdapter {
        private Fragment mCurrentFragment;

        public Fragment getCurrentFragment() {
            return mCurrentFragment;
        }
//...    
        @Override
        public void setPrimaryItem(ViewGroup container, int position, Object object) {
            if (getCurrentFragment() != object) {
                mCurrentFragment = ((Fragment) object);
            }
            super.setPrimaryItem(container, position, object);
        }
    }

1
이것은 현재 조각 요구에 완벽하게 보입니다.
danny117

현재 선택된 Fragment를 얻는 것만으로도 충분합니다. setPrimaryItem 메소드는 연결시 설정되고 Fragment의 내부 세트에 현재 항목으로 업데이트됩니다.
Graeme

1
이것은 좋은 해결책처럼 들리지만 그것을 사용할 수없는 후에setPrimaryItem() 불립니다 :-( ViewPager.OnPageChangeListener#onPageSelected()
hardysim

21

나는 이것이 약간의 답변을 가지고 있다는 것을 알고 있지만, 이것은 누군가를 도울 것입니다. 내가 얻을 필요로 할 때 나는 비교적 간단한 솔루션을 사용하고 있습니다 Fragment내에서 ViewPager. 당신에 Activity또는 Fragment을 잡고 ViewPager, 당신은 모든 순환이 코드를 사용할 수 Fragment는 보유하고 있습니다.

FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {
    Fragment viewPagerFragment = fragmentPagerAdapter.getItem(i);
    if(viewPagerFragment != null) {
        // Do something with your Fragment
        // Check viewPagerFragment.isResumed() if you intend on interacting with any views.
    }
}
  • 당신이 당신의 위치를 알고있는 경우 Fragment의를 ViewPager, 당신은 단지 호출 할 수 있습니다 getItem(knownPosition).

  • 당신이 당신의 위치를 모르는 경우 Fragment의를 ViewPager, 당신은 당신의 아이들이 수 Fragments와 같은 방법으로 인터페이스를 구현 getUniqueId()하고 구별하기 위해 그것을 사용합니다. 또는 전체를 순환하고 다음 Fragments과 같은 클래스 유형을 확인할 수 있습니다.if(viewPagerFragment instanceof FragmentClassYouWant)

!!! 편집하다 !!!

나는 처음에 각각 을 생성해야 할 때 getItem만 호출 된다는 것을 발견했다. 그 후에 는를 사용하여 재활용 된 것으로 보인다 . 이 방법으로의 많은 구현은 에서 새로운 을 만듭니다 . 위의 방법을 사용하면의 모든 항목을 살펴볼 때마다 호출 할 때마다 새을 만듭니다 . 이 때문에 나는 대신에 (허용 된 답변 을 사용하여) 를 사용하는 더 나은 접근 방식을 찾았습니다 . 이것은보다 완벽한 솔루션이며 나를 위해 잘 작동했습니다.FragmentPagerAdapterFragmentFragmentsFragmentManagerFragmentPagerAdapter FragmentgetItemFragmentgetItemFragmentPagerAdapterFragmentManagerFragment

FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {
    String name = makeFragmentName(mViewPager.getId(), i);
    Fragment viewPagerFragment = getChildFragmentManager().findFragmentByTag(name);
    // OR Fragment viewPagerFragment = getFragmentManager().findFragmentByTag(name);
    if(viewPagerFragment != null) {

        // Do something with your Fragment
        if (viewPagerFragment.isResumed()) {
            // Interact with any views/data that must be alive
        }
        else {
            // Flag something for update later, when this viewPagerFragment
            // returns to onResume
        }
    }
}

이 방법이 필요합니다.

private static String makeFragmentName(int viewId, int position) {
    return "android:switcher:" + viewId + ":" + position;
}

1
방금 findFragmentByTag ()를 찾을 수 있지만 조각으로 TAG를 어디에서 설정할 수 있습니까 ??
VinceStyling

@vince ViewPager자체가 해당 태그를 설정합니다. 이 솔루션은 "숨겨진"명명 규칙을 알고 있어야하기 때문에 취약합니다 ViewPager. 보스턴의 대답 거리는 훨씬 포괄적 인 솔루션으로,이 접근법 대신 프로젝트에서 사용합니다.
Steven Byle

이것은 잘 작동합니다! 하지만 화면 외부의 ListFragment 페이지를 업데이트해야하므로 "if (viewPagerFragment.isResumed ())"조건을 제거했습니다. 그런 다음 사용자가 ListFragment 페이지로 돌아 가면 모두 새 데이터로 업데이트됩니다.
JDJ

10

필자의 경우 위의 해결책 중 어느 것도 효과가 없었습니다.

그러나 Fragment에서 Child Fragment Manager를 사용하고 있으므로 다음이 사용되었습니다.

Fragment f = getChildFragmentManager().getFragments().get(viewPager.getCurrentItem());

Manager의 조각이 viewpager 항목과 일치하는 경우에만 작동합니다.


이것은 활동 또는 프래그먼트가 다시 생성 될 때 view pager에서 오래된 프래그먼트를 얻는 완벽한 대답입니다.
Smeet

7

ViewPager에서 현재 보이는 조각 을 얻으려면 . 이 간단한 진술을 사용하고 있으며 잘 작동합니다.

      public Fragment getFragmentFromViewpager()  
      {
         return ((Fragment) (mAdapter.instantiateItem(mViewPager, mViewPager.getCurrentItem())));
      }

3

먼저 모든 조각 목록을 만들어서 처리했습니다.List<Fragment> fragments; ) 만든 다음 호출기에 추가하여 현재 본 조각을 쉽게 처리 할 수있었습니다.

그래서:

@Override
onCreate(){
    //initialise the list of fragments
    fragments = new Vector<Fragment>();

    //fill up the list with out fragments
    fragments.add(Fragment.instantiate(this, MainFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, MenuFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, StoresFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, AboutFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, ContactFragment.class.getName()));


    //Set up the pager
    pager = (ViewPager)findViewById(R.id.pager);
    pager.setAdapter(new MyFragmentPagerAdapter(getSupportFragmentManager(), fragments));
    pager.setOffscreenPageLimit(4);
}

그래서 이것을 호출 할 수 있습니다 :

public Fragment getFragment(ViewPager pager){   
    Fragment theFragment = fragments.get(pager.getCurrentItem());
    return theFragment;
}

그런 다음 올바른 조각에있는 경우에만 실행되는 if 문에서 척킹 할 수 있습니다.

Fragment tempFragment = getFragment();
if(tempFragment == MyFragmentNo2.class){
    MyFragmentNo2 theFrag = (MyFragmentNo2) tempFragment;
    //then you can do whatever with the fragment
    theFrag.costomFunction();
}

그러나 그것은 내 핵 및 슬래시 접근 방식이지만 저에게 효과적이었습니다. 뒤 버튼을 누를 때 현재 표시된 조각에 관련 변경을 수행합니다.


1
나에게 가장 적합한 답변
Sonu Kumar

3

이것은 위의 Steven의 답변을 기반으로합니다. 부모 활동에 이미 첨부 된 조각의 실제 인스턴스를 반환합니다.

FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
    for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {

        Fragment viewPagerFragment = (Fragment) mViewPager.getAdapter().instantiateItem(mViewPager, i);
        if(viewPagerFragment != null && viewPagerFragment.isAdded()) {

            if (viewPagerFragment instanceof FragmentOne){
                FragmentOne oneFragment = (FragmentOne) viewPagerFragment;
                if (oneFragment != null){
                    oneFragment.update(); // your custom method
                }
            } else if (viewPagerFragment instanceof FragmentTwo){
                FragmentTwo twoFragment = (FragmentTwo) viewPagerFragment;

                if (twoFragment != null){
                    twoFragment.update(); // your custom method
                }
            }
        }
    }

2

나는 이것을 할 수있는 간단하고 깨끗한 방법을 찾을 수 없었습니다. 그러나 ViewPager 위젯은 조각을 호스팅하는 또 다른 ViewGroup입니다. ViewPager에는 이러한 조각이 직계 자식으로 있습니다. 따라서 .getChildCount () 및 .getChildAt ()를 사용하여 반복하여 찾고있는 프래그먼트 인스턴스가 현재 ViewPager에로드되어 참조를 얻을 수 있는지 확인할 수 있습니다. 예를 들어 정적 고유 ID 필드를 사용하여 조각을 구별 할 수 있습니다.

ViewPager는 ListView와 같은 가상화 컨테이너이므로 찾고있는 조각을로드하지 않았을 수 있습니다.


1
답변 해 주셔서 감사합니다. adpter.getItem (); 저는 안드로이드 프로그래밍의 신입생입니다. 정말 고마워요 이제 ListFragment를 검색 할 수 있고 footerView를 추가하고 싶습니다. 내 활동 에서이 작업을 수행하는 동안 logcat 인쇄 : "java.lang.IllegalStateException : 아직 컨텐츠보기가 생성되지 않았습니다." 그것으로.
Qun Qin

1
FragmentActivity에 onAttachFragment () 메서드가 있으며 ViewPager whit 조각 내용에 대해이 작업을 수행합니까?
Vasil Valchev

2

FragmentPagerAdapter는 프래그먼트의 팩토리입니다. 여전히 메모리에있는 경우 위치를 기반으로 조각을 찾으려면 다음을 사용하십시오.

public Fragment findFragmentByPosition(int position) {
    FragmentPagerAdapter fragmentPagerAdapter = getFragmentPagerAdapter();
    return getSupportFragmentManager().findFragmentByTag(
            "android:switcher:" + getViewPager().getId() + ":"
                    + fragmentPagerAdapter.getItemId(position));
}

v4 지원 API의 샘플 코드.


onresume ()에서 널을 리턴합니다. 왜 그 아이디어를 고쳐야합니까?
seema

2

당신은 하지 않습니다 호출 할 필요가 getItem()a의 참조 얻을 이후 단계에서 다른 방법 Fragment호스팅 내부 ViewPager. 내부의 일부 데이터를 업데이트 Fragment하려면 다음 방법을 사용하십시오. ViewPager를 동적으로 업데이트 하시겠습니까?

열쇠는 내부에 새로운 데이터를 설정 Adaper하고 호출 하여을 notifyDataSetChanged()호출 getItemPosition()하여 참조를 전달 Fragment하고 업데이트 할 수있는 기회를 제공합니다. 다른 모든 방법을 사용하려면 자신이나 좋은 해결책이 아닌 다른 핵을 참조해야합니다.

@Override
public int getItemPosition(Object object) {
    if (object instanceof UpdateableFragment) {
        ((UpdateableFragment) object).update(xyzData);
    }
    //don't return POSITION_NONE, avoid fragment recreation. 
    return super.getItemPosition(object);
}

여기서 이해할 수 없습니다. getItemPosition ()을 사용하려면 Fragment에 대한 참조가 필요하므로 getItemPosition을 사용하지 않을 수도 있습니다.

getItemPosition()어댑터의 메소드입니다. 직접 호출하지 않습니다. 어댑터에 대한 참조가 있으므로 s의 참조를 전달하여 어댑터를 adapter.notifyDataSetChanged()호출 getItemPosition()합니다 Fragment. 여기서 전체 구현을 확인할 수 있습니다. stackoverflow.com/questions/19891828/…
M-WaJeEh

나는 그것을 끝까지 읽었지만 여전히 그것을 얻지 못한다. 여전히 조각에 대해 전화를 걸려면 해당 조각에 대한 직접적인 참조가 필요합니까? 당신은 그것을 핵으로 언급하지만 대안을 보지 못합니다. adapter.getItem (i)이 작동하지 않습니다.

2
Ok 더 명확하게 답변을 업데이트했습니다. 물론 참조를 업데이트하려면 참조가 필요 Fragment하지만 참조를 얻는 방법은 논쟁의 여지가 있습니다. 다른 솔루션에서 참조를 얻을 FragmentManager비슷한 문자열을 사용 "android:switcher:"+id하거나 반환 POSITION_NONE에서 getItemosition()자신을 다시 모든 조각을 유발.
M-WaJeEh

고마워, 이것은 훨씬 더 의미가 있고 내 경험과 일치합니다 (따라서 잘못하고 있지 않을 수도 있습니다).

2

FragmentPagerAdapterViewPager 어댑터 클래스로 확장해야 합니다.
당신이 사용 FragmentStatePagerAdapter하면 당신은 Fragment그것으로 당신을 찾을 수 없습니다ID

public static String makeFragmentName(int viewPagerId, int index) {
  return "android:switcher:" + viewPagerId + ":" + index;
}

이 방법을 사용하는 방법 :-

Fragment mFragment = ((FragmentActivity) getContext()).getSupportFragmentManager().findFragmentByTag(
       AppMethodUtils.makeFragmentName(mViewPager.getId(), i)
);
InterestViewFragment newFragment = (InterestViewFragment) mFragment;

2

이봐, 난이 질문에 대답했다 여기 . 기본적으로 재정의해야합니다

공용 객체 instantiateItem (ViewGroup 컨테이너, int 위치)

FragmentStatePagerAdapter의 메소드입니다.


1

가장 좋은 해결책은 CodePath 에서 만든 SmartFragmentStatePagerAdapter 라는 확장을 사용하는 것입니다 . 이 가이드에 따라 ViewPager에서 조각 및 현재 선택된 조각을 훨씬 쉽게 검색 할 수 있습니다. 또한 어댑터에 임베드 된 프래그먼트의 메모리를 관리하는 데 도움이됩니다.


0

가장 쉽고 가장 간결한 방법입니다. 모든 조각 ViewPager이 다른 클래스 인 경우 다음과 같이 검색하고 구분할 수 있습니다.

public class MyActivity extends Activity
{

    @Override
    public void onAttachFragment(Fragment fragment) {
        super.onAttachFragment(fragment);
        if (fragment.getClass() == MyFragment.class) {
            mMyFragment = (MyFragment) fragment;
        }
    }

}

ViewPager를 사용할 때 여러 조각이 첨부되어 있기 때문에 이것은 잘못된 것입니다. 현재 페이지 조각이 있고 왼쪽에 하나, 오른쪽에 하나가 있습니다. 이를 통해 사용자는 사용자가 도달 할 때만 초기화하지 않고도 슬라이드 사이를 이동할 수 있습니다.
안드로이드 개발자

0

나는 조금 다른 접근 방식으로 이것을 쉽게 구현했습니다.

내 사용자 정의 FragmentAdapter.getItem 메소드가 새 MyFragment ()가 아니라 FragmentAdapter 생성자에서 작성된 MyFragment 인스턴스를 리턴했습니다.

내 활동에서 어댑터에서 조각을 가져 와서 instanceOf 필요한 조각인지 확인한 다음 필요한 메소드를 캐스팅하고 사용하십시오.


0

/values/integers.xml에 정수 자원 ID 작성

<integer name="page1">1</integer>
<integer name="page2">2</integer>
<integer name="page3">3</integer>

그런 다음 PagerAdapter getItem 함수에서 :

public Fragment getItem(int position) {

        Fragment fragment = null;

        if (position == 0) {
            fragment = FragmentOne.newInstance();
            mViewPager.setTag(R.integer.page1,fragment);

        }
        else if (position == 1) {

            fragment = FragmentTwo.newInstance();
            mViewPager.setTag(R.integer.page2,fragment);

        } else if (position == 2) {

            fragment = FragmentThree.newInstance();
            mViewPager.setTag(R.integer.page3,fragment);

        }

        return fragment;
        }

그런 다음 활동 에서이 함수를 작성하여 조각 참조를 얻으십시오.

private Fragment getFragmentByPosition(int position) {
    Fragment fragment = null;

    switch (position) {
        case 0:
            fragment = (Fragment) mViewPager.getTag(R.integer.page1);
            break;

        case 1:

            fragment = (Fragment) mViewPager.getTag(R.integer.page2);
            break;

        case 2:
            fragment = (Fragment) mViewPager.getTag(R.integer.page3);
            break;
            }

            return fragment;
    }

위 함수를 호출하여 조각 참조를 가져온 다음 사용자 지정 조각으로 캐스트하십시오.

Fragment fragment = getFragmentByPosition(position);

        if (fragment != null) {
                    FragmentOne fragmentOne = (FragmentOne) fragment;
                    }

0

프래그먼트 관리자에서 프래그먼트를 반복하는 쉬운 방법. public static PlaceholderFragment newInstance (int sectionNumber)에 배치 된 섹션 위치 인수가있는 viewpager를 찾으십시오 .

public PlaceholderFragment getFragmentByPosition(Integer pos){
    for(Fragment f:getChildFragmentManager().getFragments()){
        if(f.getId()==R.id.viewpager && f.getArguments().getInt("SECTNUM") - 1 == pos) {
            return (PlaceholderFragment) f;
        }
    }
    return null;
}

0

조각으로

public int getArgument(){
   return mPage;
{
public void update(){

}

FragmentActivity에서

List<Fragment> fragments = getSupportFragmentManager().getFragments();
for(Fragment f:fragments){
    if((f instanceof PageFragment)&&(!f.isDetached())){
          PageFragment pf = (PageFragment)f;   
          if(pf.getArgument()==pager.getCurrentItem())pf.update();
    }
}

0

TabLayout에는 Fragment에 대한 여러 탭이 있습니다. 조각의 색인을 사용하여 태그별로 조각을 찾을 수 있습니다.

예를 들어. Fragment1의 인덱스는 0이므로 findFragmentByTag()메소드에서 조각 페이지를 추가하고 조각을 대체 할 수있는 fragmentTransaction을 사용하여 Viewpager의 태그를 전달하십시오.

String tag = "android:switcher:" + R.id.viewPager + ":" + 0; Fragment1 f = (Fragment1) getSupportFragmentManager().findFragmentByTag(tag);


-1

어댑터 확인 FragmentStatePagerAdapter 대한 해결책은 다음과 같습니다.

FragmentActivity에서 :

ActionBar mActionBar = getSupportActionBar(); 
mActionBar.addTab(mActionBar.newTab().setText("TAB1").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment1.class.getName())));
mActionBar.addTab(mActionBar.newTab().setText("TAB2").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment2.class.getName())));
mActionBar.addTab(mActionBar.newTab().setText("TAB3").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment3.class.getName())));

viewPager = (STViewPager) super.findViewById(R.id.viewpager);
mPagerAdapter = new MyPagerAdapter(getSupportFragmentManager(), mActionBar);
viewPager.setAdapter(this.mPagerAdapter);

그리고 클래스 FragmentActivity에서 메소드를 작성하십시오-그래서 메소드는 당신이 당신의 Fragment에 액세스 할 수 있도록, 당신이 원하는 조각의 위치를 ​​지정해야합니다 :

public Fragment getActiveFragment(int position) {
String name = MyPagerAdapter.makeFragmentName(position);
return getSupportFragmentManager().findFragmentByTag(name);
}

어댑터에서 :

public class MyPagerAdapter extends FragmentStatePagerAdapter {

private final ActionBar actionBar;
private final FragmentManager fragmentManager;

public MyPagerAdapter(FragmentManager fragmentManager, com.actionbarsherlock.app.ActionBarActionBar mActionBar) {super(fragmentManager);
this.actionBar = mActionBar;
this.fragmentManager = fragmentManager;
}

@Override
public Fragment getItem(int position) {
getSupportFragmentManager().beginTransaction().add(mTchatDetailsFragment, makeFragmentName(position)).commit();
return (Fragment)this.actionBar.getTabAt(position);
}

@Override
public int getCount() {
return this.actionBar.getTabCount();
}

@Override
public CharSequence getPageTitle(int position) {
return this.actionBar.getTabAt(position).getText();
}

private static String makeFragmentName(int viewId, int index) {
return "android:fragment:" + index;
}

}

-1
Fragment yourFragment = yourviewpageradapter.getItem(int index);

indexfragment1먼저 추가 한 것처럼 어댑터에서 조각의 장소 이므로 나머지는 0으로 검색 fragment1패스 index를 반복합니다.

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