viewpager에서 현재 Fragment 인스턴스 가져 오기


210

아래는 3 Fragment classes3 개의 탭 이 각각 포함 된 코드입니다 ViewPager. 메뉴 옵션이 있습니다. 에 표시된 것처럼 onOptionsItemSelected()옵션을 선택하여 현재 보이는 조각을 업데이트해야합니다. 업데이트하려면 조각 클래스에있는 메소드를 호출해야합니다. 누군가 그 방법을 호출하는 방법을 제안 할 수 있습니까?

public class MainActivity  extends ActionBarActivity {

     ViewPager ViewPager;
     TabsAdapter TabsAdapter;

     @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            ViewPager = new ViewPager(this);
            ViewPager.setId(R.id.pager);
            setContentView(ViewPager);

            final ActionBar bar = getSupportActionBar();

            bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

            //Attaching the Tabs to the fragment classes and setting the tab title.
            TabsAdapter = new TabsAdapter(this, ViewPager);
            TabsAdapter.addTab(bar.newTab().setText("FragmentClass1"),
                    FragmentClass1.class, null);
            TabsAdapter.addTab(bar.newTab().setText("FragmentClass2"),
              FragmentClass2.class, null);
            TabsAdapter.addTab(bar.newTab().setText("FragmentClass3"),
              FragmentClass3.class, null);


            if (savedInstanceState != null) {
                bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
            }

        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {

            switch (item.getItemId()) {

            case R.id.addText:

           **// Here I need to call the method which exists in the currently visible Fragment class**

                    return true;

            }

            return super.onOptionsItemSelected(item);
        }


     @Override
     protected void onSaveInstanceState(Bundle outState) {
      super.onSaveInstanceState(outState);
            outState.putInt("tab", getSupportActionBar().getSelectedNavigationIndex());

     }

     public static class TabsAdapter extends FragmentPagerAdapter
      implements ActionBar.TabListener, ViewPager.OnPageChangeListener {

      private final Context mContext;
            private final ActionBar mActionBar;
            private final ViewPager mViewPager;
            private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();

            static final class TabInfo {
                private final Class<?> clss;
                private final Bundle args;

                TabInfo(Class<?> _class, Bundle _args) {
                    clss = _class;
                    args = _args;
                }
            }

      public TabsAdapter(ActionBarActivity activity, ViewPager pager) {
       super(activity.getSupportFragmentManager());
                mContext = activity;
                mActionBar = activity.getSupportActionBar();
                mViewPager = pager;
                mViewPager.setAdapter(this);
                mViewPager.setOnPageChangeListener(this);
            }

      public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
                TabInfo info = new TabInfo(clss, args);
                tab.setTag(info);
                tab.setTabListener(this);
                mTabs.add(info);
                mActionBar.addTab(tab);
                notifyDataSetChanged();

            }

      @Override
      public void onPageScrollStateChanged(int state) {
       // TODO Auto-generated method stub

      }

      @Override
      public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
       // TODO Auto-generated method stub

      }

      @Override
      public void onPageSelected(int position) {
       // TODO Auto-generated method stub
       mActionBar.setSelectedNavigationItem(position);
      }

      @Override
      public void onTabReselected(Tab tab, FragmentTransaction ft) {
       // TODO Auto-generated method stub

      }

      @Override
      public void onTabSelected(Tab tab, FragmentTransaction ft) {
       Object tag = tab.getTag();
                for (int i=0; i<mTabs.size(); i++) {
                    if (mTabs.get(i) == tag) {
                        mViewPager.setCurrentItem(i);

                    }
                }

                tabPosition = tab.getPosition();
      }

      @Override
      public void onTabUnselected(Tab tab, FragmentTransaction ft) {
       // TODO Auto-generated method stub

      }

      @Override
      public Fragment getItem(int position) {
       TabInfo info = mTabs.get(position);
                return Fragment.instantiate(mContext, info.clss.getName(), info.args);
      }

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

     }

    }

아래에 updateList()내가 호출하려는 메소드가있는 조각 클래스가 있다고 가정 하십시오.

 public class FragmentClass1{

    ArrayList<String> originalData;


    @Override
         public View onCreateView(LayoutInflater inflater, ViewGroup container,
           Bundle savedInstanceState) {

          View fragmentView = inflater.inflate(R.layout.frag1, container, false);

          originalData = getOriginalDataFromDB();

          return fragmentView;

         }


    public void updateList(String text)
    {
       originalData.add(text);
       //Here I could do other UI part that need to added
    }
}

어떤 조각화 방법을 호출 하시겠습니까?
— Biraj Zalavadia

@BirajZalavadia 매개 ​​변수가 있고 뷰를 생성하는 동안 이미 초기화 된 해당 조각 클래스의 인스턴스 변수를 사용하는 자체 정의 된 메서드입니다.
— rick

1
viewpager에있는 조각의 클래스 이름을 줄 수 있습니까?
— Biraj Zalavadia


보이는 조각에 액세스하는 가장 간단한 방법은 stackoverflow.com/questions/7379165/…를 통해 이루어 집니다. 두 가지 답변을 살펴보십시오.
— Luksprog

답변:


205

옵션을 선택하면 현재 보이는 조각을 업데이트해야합니다.

이를 수행하는 간단한 방법은 FragmentPagerAdapter구현 과 관련된 트릭을 사용하는 것입니다 .

case R.id.addText:
     Fragment page = getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + ViewPager.getCurrentItem());
     // based on the current position you can then cast the page to the correct 
     // class and call the method:
     if (ViewPager.getCurrentItem() == 0 && page != null) {
          ((FragmentClass1)page).updateList("new item");     
     } 
return true;

클래스의 이름은 매우 (그래서 혼동하지 변수 이름으로 사용하여 변수 명명 규칙을 다시 생각하십시오 ViewPager ViewPager, 사용 ViewPager mPager예를 들어).


23
API가 변경되면 해당 프래그먼트 태그가 미래를 보장합니까?
— Maarten

7
@Maarten 아니요, 어댑터가 등장한 후 (및 소스 코드를 사용할 수 있음) 사용 된 일반적인 해킹 일 뿐이며 아직 변경되지 않았습니다. 보다 안정적인 것을 원한다면 다른 옵션을 사용해야합니다. 가장 중요한 instantiateItem()방법을 재정의 하고 적절한 조각에 대한 참조를 직접 가져와야합니다.
— Luksprog

5
몇 시간 동안 좌절을 mAdapter.getItem(position)겪고 나서 페이지에서 직접 페이지를 요청한 후 ... 적어도 지금은 다른 8512 재판이 효과가 없다는 것을 알고 있습니다. 감사합니다
— Diolor

29
FragmentPagerAdapter 대신 FragmentStatePagerAdapter를 사용하는 경우에는 작동하지 않습니다.
— Shawn Lauzon 2016 년

3
@ShawnLauzon FragmentStatePagerAdapter는 다른 구현을 가지고 있으며,이 경우 instantiateItem () 메서드를 호출하여 보이는 조각을 가져옵니다.
— Luksprog 2016 년

155
    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);
        }
    }

28
Google은 mCurrentPrimaryItem을 반환하는 FragmentPageAdapter.getCurrentPrimaryItem ()을 제공해야합니다.
— eugene

1
놨 또한 방법과 PagerFragment을 정의로 나는이 기술을 사용 onPageSelected/ onPageDeselected내 호출기 조각을 확장하는 모든하고 있습니다. 그런 다음 setPrimaryitem사용자가 새 페이지로 스 와이프 할 때 이러한 메소드를 적절하게 호출 할 수 있습니다. 즉, 표시되지 않은 페이지에 데이터를로드하기위한 지연 전략을 구현할 수 있습니다. 그러나 페이지 전환 중에 다음 페이지에 이미 데이터가 채워져 있으면 더 좋아 보이므로 모든 데이터를 느리게로드하는 onPageSelected것이 이상적이지 않을 수 있습니다.
— JHH

3
왜 if진술? 조각은 단지 equals객체 의 메소드를 호출하는데 , 이는 얕은 비교입니다. 왜 항상 전화하지 mCurrentFragment = ((Fragment) object);않습니까?
— Overclover

시도하고 제대로 작동하면 getCurrentFragment ()를 특정 조각으로 캐스팅하십시오.
— PhilipJ

113

우선 모든 "활성"단편 페이지를 추적하십시오. 이 경우 ViewPager에서 사용되는 FragmentStatePagerAdapter에서 조각 페이지를 추적합니다.

@Override
public Fragment getItem(int index) {
    Fragment myFragment = MyFragment.newInstance();
    mPageReferenceMap.put(index, myFragment);
    return myFragment;
}

"비활성"프래그먼트 페이지에 대한 참조를 유지하지 않으려면 FragmentStatePagerAdapter의 destroyItem (...) 메소드를 구현해야합니다.

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

현재 표시된 페이지에 액세스해야하는 경우 다음을 호출하십시오.

int index = mViewPager.getCurrentItem();
MyAdapter adapter = ((MyAdapter)mViewPager.getAdapter());
MyFragment fragment = adapter.getFragment(index);

MyAdapter의 getFragment (int) 메소드는 다음과 같습니다.

public MyFragment getFragment(int key) {
    return mPageReferenceMap.get(key);
}

그것이 도움이되기를 바랍니다!


명확하게 설명해 주시겠습니까? 이 FragmentStatePagerAdapter 클래스를 코드에서 어디에 보관해야합니까? BTW 단일 MyFragmentClass가 아닌 3 개의 조각 클래스가 있습니다.
— rick

7
방향 변경 후에도 작동하기 때문에 getItem 대신 instantiateItem에서 mPageReferenceMap을 업데이트하면 더 좋습니다. '@ 공개 개체 재정의 instantiateItem (ViewGroup container, int position) {Fragment fragment = (Fragment) Super.instantiateItem (컨테이너, 위치); mPageReferenceMap.put (위치, 조각); 반환 조각; } '
— pmellaaho

mPageReferenceMap은 어떤 유형입니까?
— DoruAdryan

10
이 답변은 정말 나쁩니다! ViewPager의 캐시는 자체적으로 처리하므로 수동으로 캐시를 유지해서는 안됩니다. ViewPager는 프래그먼트를 할당해야 할 시점, 일시 중지 할 시점 및시기를 결정하여 모든 프래그먼트에 대한 참조를 유지하면 쓸모없는 오버 헤드가 발생하며 메모리에 최적화되지 않습니다.
— Livio

3
이 방법을 시도했지만 불행히도 활동을 다시 만들 때 작동하지 않습니다. Android N 이상에서는 다중 창 기능을 사용할 때이를 볼 수 있습니다. 앱이 열려 있으면 '최근'버튼 (사각형)을 길게 누릅니다. 활동 및 단편이 savedInstanceState에서 다시 작성되고 어댑터가 다시 작성되므로 (mPageReferenceMap이 비어 있음) getItem이 다시 호출되지 않습니다. 맵이 비어있는 상태에서 adapter.getFragment (index)가 충돌합니다.
— Martin Konicek

102

이것이 특정 조각 클래스의 인스턴스 변수에 대해 NullPointerException을 얻지 못하는 유일한 방법입니다. 이것은 같은 것을 고수 한 다른 사람들에게 도움이 될 수 있습니다. onOptionsItemSelected ()에서 아래 방법으로 코딩했습니다.

if(viewPager.getCurrentItem() == 0) {
    FragmentClass1 frag1 = (FragmentClass1)viewPager
                            .getAdapter()
                            .instantiateItem(viewPager, viewPager.getCurrentItem());
    frag1.updateList(text); 
} else if(viewPager.getCurrentItem() == 1) {
    FragmentClass2 frag2 = (FragRecentApps)viewPager
                            .getAdapter()
                            .instantiateItem(viewPager, viewPager.getCurrentItem());
    frag2.updateList(text);
}

3
나는 이것이 가장 올바른 대답이라고 생각 FragmentStatePagerAdapter합니다. 코드를 재정의하지 않고 디자인과 일치 합니다. 사실, 그것은 함수가 return하는 것처럼 간단해야합니다 viewPager.getAdapter().instantiateItem(viewPager, viewPager.getCurrentItem()).
— 존 팡

39

FragmentStatePagerAdapter에는 지정된 매개 변수 값을 기반으로 조각을 반환하는 instantiateItem이라는 이름의 공용 메서드가 있으며이 메서드에는 ViewGroup (ViewPager) 및 위치라는 두 개의 매개 변수가 있습니다.

public Object instantiateItem(ViewGroup container, int position);

이 방법을 사용하여 지정된 위치의 조각을 얻습니다.

Fragment fragment = (Fragment) adaper.instantiateItem(mViewPager, position);

5
그러나 이것은 현재 이미 인스턴스화 된 조각을 반환하지 않지만 대신 새로운 조각을 반환합니까? 따라서 "instantiate"라는 이름을 지정하십시오.
— Ixx

1
@Ixx 아니요 새 조각을 만들지 않습니다. 여기에서 메소드 이름이 잘못되었다고 생각합니다.
— Bugs Happen

15

너무 늦었지만 알고있는 간단한 방법이 있습니다.

// 0 위치에서 조각화

((mFragment) viewPager.getAdapter().instantiateItem(viewPager, 0)).yourMethod();

10

여기에는 실제로 예측할 수있는 방법이 없다는 기본적인 사실을 다루지 않는 많은 답변이 있으며, 그로 인해 앞으로 어느 시점에서 발을 쏠 수는 없습니다.

FragmentStatePagerAdapter조각에 의해 추적되는 조각에 안정적으로 액세스하는 방법을 아는 유일한 클래스입니다 FragmentManager. 조각의 id 또는 태그를 시도하고 추측하려는 시도는 장기적으로 신뢰할 수 없습니다. 또한 상태를 복원 FragmentStatePagerAdapter할 때 콜백을 호출하지 못할 수 있으므로 상태를 저장 / 복원 할 때 인스턴스를 수동으로 추적하려는 시도가 제대로 작동 하지 않을 수 있습니다.

내가 할 수 있었던 유일한 일은 코드를 복사하고 FragmentStatePagerAdapter위치 ( mFragments.get(pos))가 주어지면 조각을 반환하는 메서드를 추가하는 것입니다 . 이 방법은 프래그먼트가 실제로 사용 가능하다고 가정합니다 (즉, 어느 시점에서 볼 수 있음).

특히 모험적이라면 리플렉션을 사용하여 개인 mFragments목록 의 요소에 액세스 할 수 있지만 우리는 정사각형으로 돌아갑니다 (목록의 이름이 동일하게 유지되는 것은 아닙니다).


1
"상태가 저장 / 복원 될 때 제대로 작동하지 않음"을 처리하기 위해 saveState () 메소드를 재정의합니다. 따라서 활동이 일시 정지 될 때 호출기가 단편을 저장하지 않습니다. 효과가있다.
— AntoineP

2
그것은 근본적인 문제를 해결하지 않고 패치 워크에 추가합니다. 나는 그것이 작동하지 않는다고 주장하는 것이 아니라 단지 좋은 구현이 아니라는 것입니다.
— Melllvar

8
getSupportFragmentManager().getFragments().get(viewPager.getCurrentItem());

위의 줄에서 가져온 인스턴스를 작업하려는 조각으로 캐스트하십시오. 완벽하게 작동합니다.

viewPager

조각을 관리하는 호출기 인스턴스입니다.


모든 페이지가 조각으로로드 된 경우에만 작동합니다. 예를 들어 많은 탭 / 페이지가있는 tablayout이있는 경우 모든 탭 / 페이지가로드되는 것은 아니므로 indexoutofbounce 예외가 발생할 수 있습니다.
— progNewbie

@progNewbie 예, 추가 해결 방법 코드가 필요합니다.
— Gaurav Pangam

@progNewbie 예브게니의 대답은 아래 내가 생각하는 상황을 처리 할 것
— Gaurav Pangam

7

옵션을 선택하여 현재 보이는 조각을 업데이트해야합니다.

현재 보이는 프래그먼트에 대한 참조를 얻으려면 ViewPageras에 대한 참조가 있다고 가정하십시오 mPager. 다음 단계는 다음에 대한 참조를 얻습니다 currentFragment.

  1. PageAdapter adapter = mPager.getAdapter();
  2. int fragmentIndex = mPager.getCurrentItem();
  3. FragmentStatePagerAdapter fspa = (FragmentStatePagerAdapter)adapter;
  4. Fragment currentFragment = fspa.getItem(fragmentIndex);

사용 된 유일한 캐스트 라인 3이 일반적으로 유효합니다. FragmentStatePagerAdapterViewPager에 유용한 어댑터입니다.


7

가장 좋은 방법은 CallingFragmentName fragment = (CallingFragmentName) viewPager .getAdapter () .instantiateItem (viewPager, viewPager.getCurrentItem ()); 호출하는 Fragment를 다시 인스턴스화하여 null 포인터 예외를 throw하지 않고 해당 조각의 모든 메소드를 호출합니다.


6

현재 조각 :

프래그먼트 탭바 템플릿으로 프로젝트를 생성 한 경우 작동합니다.

Fragment f = mSectionsPagerAdapter.getItem(mViewPager.getCurrentItem());

이것은 기본 탭 활동 템플리트 구현에서 작동합니다.


30
이것은 getItem () 구현에 따라 다릅니다. 조각의 새 인스턴스를 반환 할 수도 있습니다.
— Tom

이것이 당신이하는 방법입니다. 조각 프로젝트로 tabor를 만들 때 여전히 기본 구성이있는 경우 이 솔루션은 없었습니다. 그래서 도움이 될 것이라고 생각했습니다.
— hasan

3

나는 다음을 사용했다 :

 int index = vpPager.getCurrentItem();
 MyPagerAdapter adapter = ((MyPagerAdapter)vpPager.getAdapter());
 MyFragment suraVersesFragment = (MyFragment)adapter.getRegisteredFragment(index);

1
:이 여기에있는 대답에서 사용자 정의 호출기 구현에 의존 stackoverflow.com/questions/8785221/...
— 톰 레드먼

1
이것은 내가하려고했던 것이지만 재정의 할 방법을 모르면 몇 시간을 낭비했을 것입니다-감사합니다!
— 브론 데이비스

2

FragmentStatePagerAdaptermCurrentPrimaryItem유형 의 개인 인스턴스 변수가 Fragment있습니다. 안드로이드 개발자가 왜 게터를 제공하지 않았는지 궁금 할 것입니다. 이 변수는 setPrimaryItem()메소드 에서 인스턴스화됩니다 . 따라서이 변수에 대한 참조를 얻을 수 있도록이 메소드를 대체하십시오. 나는 단순히 내 자신을 선언 mCurrentPrimaryItem하고 그 내용을 setPrimaryItem()재정의에 복사하는 것으로 끝났습니다 .

당신의 구현에서 FragmentStatePagerAdapter:

private Fragment mCurrentPrimaryItem = null;

@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
    Fragment fragment = (Fragment)object;
    if (fragment != mCurrentPrimaryItem) {
        if (mCurrentPrimaryItem != null) {
            mCurrentPrimaryItem.setMenuVisibility(false);
            mCurrentPrimaryItem.setUserVisibleHint(false);
        }
        if (fragment != null) {
            fragment.setMenuVisibility(true);
            fragment.setUserVisibleHint(true);
        }
        mCurrentPrimaryItem = fragment;
    }
}

public TasksListFragment getCurrentFragment() {
    return (YourFragment) mCurrentPrimaryItem;
}

2

PagerAdapter이와 같이 정의하면 을 (를) 얻을 수 Fragment있습니다 ViewPager.

private class PagerAdapter extends FragmentPagerAdapter {
    private final List<Fragment> mFragmentList = new ArrayList<>();

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

    @Override
    public Fragment getItem(int position) {
        return mFragmentList.get(position);
    }

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

    public void addFragment(Fragment fragment) {
        mFragmentList.add(fragment);
    }
}

현재를 얻으려면 Fragment

Fragment currentFragment = mPagerAdapter.getItem(mViewPager.getCurrentItem());

2

viewPager를 사용할 때 활동에서 프래그먼트 인스턴스에 액세스하는 좋은 방법은 instantiateItem (viewpager, index)입니다. // index- 인스턴스를 원하는 조각의 인덱스.

예를 들어 1 인덱스의 조각 인스턴스에 액세스하고 있습니다.

Fragment fragment = (Fragment) viewPageradapter.instantiateItem(viewPager, 1);

if (fragment != null && fragment instanceof MyFragment) {      
 ((MyFragment) fragment).callYourFunction();

}

1

나는 같은 문제가 있었고이 코드를 사용하여 해결했다.

MyFragment fragment = (MyFragment) thisActivity.getFragmentManager().findFragmentById(R.id.container);

MyFragment 이름을 프래그먼트 이름으로 바꾸고 프래그먼트 컨테이너의 ID를 추가하십시오.


1

이것은 받아 들인 대답보다 미래에 대비합니다.

public class MyFragmentPagerAdapter extends FragmentPagerAdapter {

    /* ------------------------------------------------------------------------------------------ */
    // region Private attributes :

    private Context _context;
    private FragmentManager _fragmentManager;
    private Map<Integer, String> _fragmentsTags = new HashMap<>();

    // endregion
    /* ------------------------------------------------------------------------------------------ */



    /* ------------------------------------------------------------------------------------------ */
    // region Constructor :

    public MyFragmentPagerAdapter(Context context, FragmentManager fragmentManager) {

        super(fragmentManager);

        _context = context;
        _fragmentManager = fragmentManager;
    }

    // endregion
    /* ------------------------------------------------------------------------------------------ */



    /* ------------------------------------------------------------------------------------------ */
    // region FragmentPagerAdapter methods :

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

    @Override
    public Fragment getItem(int position) {

        if(_fragmentsTags.containsKey(position)) {

            return _fragmentManager.findFragmentByTag(_fragmentsTags.get(position));
        }
        else {

            switch (position) {

                case 0 : { return Fragment.instantiate(_context, Tab1Fragment.class.getName()); }
                case 1 : { return Fragment.instantiate(_context, Tab2Fragment.class.getName()); }
            }
        }

        return null;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {

        // Instantiate the fragment and get its tag :
        Fragment result = (Fragment) super.instantiateItem(container, position);
        _fragmentsTags.put(position, result.getTag());

        return result;
    }

    // endregion
    /* ------------------------------------------------------------------------------------------ */
}

대신 WeakHashMap을 사용해야합니다.
— Prakash Nadar

1

문제의 시나리오는 공식 문서에 설명 된대로 각 Fragment가 자체 메뉴 항목을 추가하고 onOptionsItemSelected ()를 직접 처리하여 더 잘 제공됩니다 . 문서화되지 않은 트릭을 피하는 것이 좋습니다.


이 답변은 실제로 수행하는 방법에 대한 자세한 내용을 사용할 수 있습니다. 메뉴 항목을 추가하면 ViewPager문제가 어떻게 해결됩니까?
— Suragch

@Suragch ViewPager 문제는 프래그먼트를 호스팅하는 활동 내에서 메뉴 이벤트가 처리되고 프래그먼트 자체 내에서 이벤트가 처리되는 경우 존재하지 않습니다. 링크는 프래그먼트가 자체 메뉴 항목을 추가하는 방법을 보여줍니다.
— Y2i

1

모든 의견과 답변을 읽은 후이 문제에 대한 최적의 솔루션을 설명하려고합니다. 가장 좋은 옵션은 @rik의 솔루션이므로 내 개선은 그의 것입니다.

각 FragmentClass를 요청하는 대신

if(FragmentClass1){
   ...
if(FragmentClass2){
   ...
}

자신 만의 인터페이스를 만들고 자식 프래그먼트로 구현하십시오.

public interface MyChildFragment {
    void updateView(int position);
}

그런 다음 내부 조각을 시작하고 업데이트하기 위해 이와 같은 작업을 수행 할 수 있습니다.

Fragment childFragment = (Fragment) mViewPagerDetailsAdapter.instantiateItem(mViewPager,mViewPager.getCurrentItem());

if (childFragment != null) {
   ((MyChildFragment) childFragment).updateView();
}

PS 시스템이 실제로 코드를 작성하기 전에 insatiateItem을 호출하는 경우 해당 코드를 어디에 두어야합니까? savedInstanceState 이에 대한 널 (null) 자녀의 조각이 될 것입니다

public void onCreate(@Nullable Bundle savedInstanceState){
      super(savedInstanceState)
}

앱이 다운됩니다.

행운을 빕니다


1

그가 @chahat jain에게 대답 한 내용을 바탕으로 :

"viewPager를 사용할 때 활동에서 프래그먼트 인스턴스에 액세스하는 좋은 방법은 instantiateItem (viewpager, index)입니다. // index- 인스턴스를 원하는 프래그먼트의 인덱스입니다."

kotlin 에서 그렇게하고 싶다면

val fragment =  mv_viewpager.adapter!!.instantiateItem(mv_viewpager, 0) as Fragment
                if ( fragment is YourFragmentFragment)
                 {
                    //DO somthign 
                 }

0 의 조각 인스턴스에 0

// ==================================================== ========================= // // ###################### ######## 사용 예 ############################# // // == ===================================================== ===================== //

여기에 대해 가장 잃어버린 비전을 얻는 완전한 예가 있습니다.

다음은 .xml 파일의 veiewPager입니다.

   ...
    <android.support.v4.view.ViewPager
                android:id="@+id/mv_viewpager"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="5dp"/>
    ...

탭을 삽입 한 홈 활동

...
import kotlinx.android.synthetic.main.movie_tab.*

class HomeActivity : AppCompatActivity() {

    lateinit var  adapter:HomeTabPagerAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
       ...
    }



    override fun onCreateOptionsMenu(menu: Menu) :Boolean{
            ...

        mSearchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
          ...

            override fun onQueryTextChange(newText: String): Boolean {

                if (mv_viewpager.currentItem  ==0)
                {
                    val fragment =  mv_viewpager.adapter!!.instantiateItem(mv_viewpager, 0) as Fragment
                    if ( fragment is ListMoviesFragment)
                        fragment.onQueryTextChange(newText)
                }
                else
                {
                    val fragment =  mv_viewpager.adapter!!.instantiateItem(mv_viewpager, 1) as Fragment
                    if ( fragment is ListShowFragment)
                        fragment.onQueryTextChange(newText)
                }
                return true
            }
        })
        return super.onCreateOptionsMenu(menu)
    }
        ...

}

1

이전 구현에서 나중에 액세스 할 수 있도록 자식 조각 목록을 저장했지만 이는 큰 메모리 누수를 일으키는 잘못된 구현으로 판명되었습니다.

instantiateItem(...)현재 조각을 얻는 방법을 사용합니다 .

val currentFragment = adapter?.instantiateItem(viewPager, viewPager.currentItem)

또는 위치에 다른 조각을 얻으려면 :

val position = 0
val myFirstFragment: MyFragment? = (adapter?.instantiateItem(viewPager, position) as? MyFragment)

에서 문서 :

주어진 위치에 대한 페이지를 작성하십시오. 어댑터는 여기에 제공된 컨테이너에보기를 추가해야하지만 finishUpdate (ViewGroup)에서 리턴 될 때만 수행해야합니다.


0

내 활동에는 다음이 있습니다.

int currentPage = 0;//start at the first tab
private SparseArray<Fragment> fragments;//list off fragments
viewPager.setOnPageChangeListener(new OnPageChangeListener() {

@Override
public void onPageSelected(int pos) {
        currentPage = pos;//update current page
}

@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {}
@Override
public void onPageScrollStateChanged(int arg0) {}
});



@Override
public void onAttachFragment(Fragment fragment) {
    super.onAttachFragment(fragment);
    if(fragment instanceof Fragment1)
        fragments.put(0, fragment);
    if(fragment instanceof Fragment2)
        fragments.put(2, fragment);
    if(fragment instanceof Fragment3)
        fragments.put(3, fragment);
    if(fragment instanceof Fragment4)
        fragments.put(4, fragment);
}

Then I have the following method for getting the current fragment

public Fragment getCurrentFragment() {
    return fragments.get(currentPage);
}

0
final ViewPager.OnPageChangeListener onPageChangeListener =
    new ViewPager.OnPageChangeListener() {
      @Override public void onPageSelected(int position) {
        switch (position) {
          case 0:
            FragmentClass1 frag1 =
                (FragmentClass1) viewPager.getAdapter()
                    .instantiateItem(viewPager, viewPager.getCurrentItem());
            frag1.updateList("Custom text");
            break;
          case 1:
            break;
          case 2:
            break;
        }
      }

      @Override
      public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

      }

      @Override public void onPageScrollStateChanged(int state) {
      }
    };


 viewPager.addOnPageChangeListener(onPageChangeListener);

viewPager.setAdapter(adapter);


viewPager.post(new Runnable() {
  @Override public void run() {
    onPageChangeListener.onPageSelected(viewPager.getCurrentItem());
  }
});

때때로 프래그먼트가 null 객체를 전달할 수 있으므로 처음로드 할 때 문제를 해결하기 위해 새로운 Runnable을 실행할 수 있습니다.

릭 감사합니다


이 코드가 OP의 문제를 해결하는 이유를 설명하는 텍스트를 추가하십시오. 또한, 다른 답변이 몇 개인 지, 왜이 답변이 이미 제공된 답변보다 나은지 설명하십시오. 다른 사람들이 이해하도록 도와주십시오.
— APC

0

FragmentPagerAdapter에서 setPrimaryItem을 재정의하십시오. 객체가 보이는 조각입니다.

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

0

호출기에서 현재 항목을 가져 와서 해당 위치의 조각을 어댑터에 요청하십시오.

 int currentItem = viewPager.getCurrentItem();
    Fragment item = mPagerAdapter.getItem(currentItem);
    if (null != item && item.isVisible()) {
       //do whatever want to do with fragment after doing type checking
        return;
    }

3
어떤 경우에하는 것은 getItem새로운 인스턴스를 생성
— 프라 카쉬 Nadar

0

현재 조각을 얻으려면 -public void onPageSelected (final int position) 에서 ViewPager에서 위치를 가져온 다음

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

SECTNUM- 공개 정적 PlaceholderFragment에 지정된 위치 인수 newInstance (int sectionNumber); 파편

getChildFragmentManager () 또는 getFragmentManager ()-SectionsPagerAdapter 생성 방법에 따라 다름


0

Fragment에서 BroadcastReceiver를 구현하고 어디에서나 Intent를 보낼 수 있습니다. 프래그먼트의 수신자는 특정 액션을 수신하고 인스턴스의 메소드를 호출 할 수 있습니다.

한 가지주의 할 점은 View 구성 요소가 이미 인스턴스화되어 있고 목록 스크롤과 같은 일부 작업의 경우 ListView가 이미 렌더링되어 있는지 확인하는 것입니다.


0

이것은 가장 간단한 해킹입니다.

fun getCurrentFragment(): Fragment? {
    return if (count == 0) null
    else instantiateItem(view_pager, view_pager.currentItem) as? Fragment
}

(코트 린 코드)

전화 instantiateItem(viewPager, viewPager.getCurrentItem()해서로 전송하십시오 Fragment. 아이템이 이미 인스턴스화되었습니다. 확인 표시를 추가 할 수 있습니다 getCount.

모두와 함께 작동 FragmentPagerAdapter하고 FragmentStatePagerAdapter!


0

호출기가 Fragment 안에 있으면 다음을 사용하십시오.

private fun getPagerCurrentFragment(): Fragment? {
    return childFragmentManager.findFragmentByTag("android:switcher:${R.id.myViewPagerId}:${myViewPager.currentItem}")
}

R.id.myViewPagerIdxml 레이아웃 내에서 ViewPager의 ID는 어디에 있습니까 ?


이것은 FragmentStatePageAdapter가 아닌 일반 FragmentPageAdapter에서만 작동합니다.
— progNewbie

0

조각 배열을 레지스터 조각으로 선언 할 수 있습니다

class DashboardPagerAdapter(fm: FragmentManager?) : FragmentStatePagerAdapter(fm!!) {
    // CURRENT FRAGMENT
    val registeredFragments = SparseArray<Fragment>()

    override fun instantiateItem(container: ViewGroup, position: Int): Any {
        val fragment = super.instantiateItem(container, position) as Fragment
        registeredFragments.put(position, fragment)
        return fragment
    }

    override fun getItem(position: Int): Fragment {
        return when (position) {
            0 -> HomeFragment.newInstance()
            1 -> ConverterDashboardFragment.newInstance()
            2 -> CartFragment.newInstance()
            3 -> CustomerSupportFragment.newInstance()
            4 -> ProfileFragment.newInstance()
            else -> ProfileFragment.newInstance()
        }
    }

    override fun getCount(): Int {
        return 5
    }

}

그럼 당신은 그것을 사용할 수 있습니다

adapter?.let {
    val cartFragment = it.registeredFragments[2] as CartFragment?
    cartFragment?.myCartApi(true)
}

그렇게하기로 결정했다면 destroyItem ()을 구현하고 registeredFragments에서 파괴 된 인스턴스를 제거해야합니다. 그렇지 않으면 메모리 누수가 발생합니다.
— dephinera

좋은 조언입니다. 답변을 수정하실 수 있습니다.
— Hamza Khan

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