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.