programing

View Pager에서 조각 검색

powerit 2023. 9. 5. 20:49
반응형

View Pager에서 조각 검색

사용 중입니다.ViewPagerFragmentStatePagerAdapterfragment를 : 개의 다합호스다니트세을각조른.

  • [분절1]
  • [분절2]
  • [분절3]

내가 얻고 싶을 때Fragment1ViewPager에 시대에FragmentActivity.

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

기본 응답은 프레임워크에서 생성되는 이름에 의존합니다.만약 그것이 바뀌면, 그것은 더 이상 작동하지 않을 것입니다.

이 해결책은 어때요, 오버라이드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);
    }
}

이것은 사용 가능한 Fragment를 처리할 때 저에게 효과가 있는 것 같습니다.는 직는아을은호출시다니환반합않인을 합니다.getRegisteredFragment하지만 난 이걸 주로 전류를 얻기 위해 사용해왔어요Fragment에서 .ViewPager:adapater.getRegisteredFragment(viewPager.getCurrentItem())그리고 이것은 돌아오지 않을 것입니다.null.

저는 이 솔루션의 다른 단점을 알지 못합니다.있다면 알고 싶습니다.

ViewPager에서 단편을 수집하는 방법은 여기 및 기타 관련 SO 스레드/블로그에 많은 답변이 있습니다.제가 본 사람들은 모두 고장이 났고, 일반적으로 아래 두 가지 유형 중 하나에 해당하는 것 같습니다.이 스레드의 다른 답변과 같이 현재 조각만 가져오려는 경우 다른 유효한 해결책이 있습니다.

사용하는 경우 아래를 참조하십시오.이것을 볼 가치가 있다면요.FragmentStateAdapter에서 현재 인덱스가 아닌 인덱스를 가져오는 것은 그 특성상 완전히 해체되는 것만큼 유용하지 않습니다. 이러한 인덱스는 보기에서 사라지거나 화면 밖으로 사라집니다.

불행한 길들

Wrong: 내부 조각 목록을 관리하고 다음에 추가합니다.FragmentPagerAdapter.getItem()를 라고 합니다.

  • 일반적으로 a를 사용합니다.SparseArray또는Map
  • 라이프사이클 이벤트를 설명하는 많은 예 중 하나가 아니기 때문에 이 솔루션은 취약합니다.getItem페이지를 처음으로 스크롤할 때만 호출됩니다.ViewPager.setOffscreenPageLimit(x) > 0) ViewPager가 주최가라면.Activity/Fragment작동이 중지되거나 다시 시작되면 내부가SpaseArray FragmentPager 때되지만, 되고 "FragmentPager Activity", "ViewPager" 및 "Fragment"가 재생성됩니다.getItem인덱스에 대해 호출되지 않으므로 인덱스에서 조각을 가져오는 기능이 영구히 손실됩니다.다음을 통해 이러한 조각 참조를 저장하고 복원하여 이 문제를 해결할 수 있습니다.FragmentManager.getFragment()그리고.putFragmentIMHO가 엉망이 되기 시작합니다.

Wrong: 후드 아래에 사용되는 태그 ID와 일치하도록 자체 태그 ID를 구성하고 이 ID를 사용하여 페이지 Fragments를 검색합니다.FragmentManager

  • 이것은 첫 번째 내부 어레이 솔루션에서 손실-분절-참조 문제를 처리하는 것과 같은 경우에 더 낫지만, 위와 인터넷의 다른 곳에서 올바르게 지적된 바와 같이, 내부의 개인적인 방법만큼이나 진부하게 느껴집니다.ViewPager언제든지 또는 OS 버전에 따라 변경될 수 있습니다.

이 솔루션에 대해 다시 생성된 방법은 다음과 같습니다.

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

한 경로: 행한길복:ViewPager.instantiateItem()

위와 유사한 접근 방식이지만 라이프사이클 파괴가 아닌 접근 방식은 다음과 같습니다.instantiateItem()getItem()인덱스가 생성/액세스될 때마다 전자가 호출되기 때문입니다. 답변 보기

PATH: 만의 길을 .FragmentViewPager

만의 접직을 합니다.FragmentViewPager최신 지원 lib 소스에서 클래스를 생성하고 fragment 태그를 생성하는 데 내부적으로 사용되는 메서드를 변경합니다.아래와 같이 대체할 수 있습니다.이는 태그 생성이 변경되지 않고 항상 위험한 개인 api/method에 의존하지 않는다는 것을 가지고 있습니다.

/**
 * @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;
}

처럼 인덱스에 싶을 때 에 넣을 수)을 불러주세요.FragmentPagerAdaptergetItem이 해당 페이지에 대해 아직 호출되지 않은 경우(즉, 아직 생성되지 않은 경우) 결과가 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;
}

이것은 간단한 솔루션이며 웹의 모든 곳에서 발견되는 다른 두 솔루션의 문제를 해결합니다.

FragmentPager 어댑터에 다음 메서드를 추가합니다.

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 에 구현된 솔루션입니다.무언가 실패하면 양호한 충돌 로그가 표시됩니다.

또 다른 간단한 솔루션:

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

이것이 몇 가지 답을 가지고 있다는 것을 알지만, 아마도 이것은 누군가에게 도움이 될 것입니다.비교적 간단한 솔루션을 사용했습니다.Fragment의 게서에서.ViewPager의 신의에서.Activity또는FragmentViewPager이 코드를 사용하여 다음과 같이 순환할 수 있습니다.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할 때는 " 과같방법인로구터현다니합를스이페다으음은▁like▁an▁with▁interface"와 같은 방법을 합니다.getUniqueId()그리고 그것을 사용하여 그들을 차별화합니다.또는 모두 순환할 수 있습니다.Fragments유형을 합니다. 를 들어, 클래스 유형을 확인합니다.if(viewPagerFragment instanceof FragmentClassYouWant)

편집!!!

는 그것을 했습니다.getItem에 의해서만 호출됩니다.FragmentPagerAdapter각각의 경우에Fragment처음 생성되어야 하고, 그 후에, 그것은 나타납니다.Fragments▁the를 사용하여 됩니다.FragmentManager 식으로, 이한방식로, 구이현많의 많은 이 있습니다.FragmentPagerAdapter새로 만들기 Fragment죄를 짓는getItem위의 방법을 사용하면, 이것은 우리가 새로운 것을 만들 것이라는 것을 의미합니다.Fragment 번매getItem우리가 모든 항목을 검토할 때 호출됩니다.FragmentPagerAdapter이로 인해, 저는 더 나은 접근법을 찾았습니다.FragmentManager각각을 얻기 위해Fragment대신(승인된 답변 사용).이것은 더 완벽한 해결책이며, 저에게 잘 작동하고 있습니다.

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

저의 경우, 위의 해결책 중 하나도 효과가 없었습니다.

그러나 fragment에서 하위 fragment Manager를 사용하고 있기 때문에 다음이 사용되었습니다.

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

이것은 관리자의 조각이 보기 페이지 항목과 일치하는 경우에만 작동합니다.

ViewPager에서 현재 Visible fragment를 가져오려면 다음과 같이 하십시오.저는 이 간단한 문구를 사용하고 있으며 잘 작동하고 있습니다.

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

했습니다. (우 모 조 처 습 했 니 리 다 로 것 으 는 선 하 든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();
}

하지만 그것은 단지 나의 해킹과 슬래시 접근법일 뿐이지만, 그것은 나에게 효과가 있었고, 나는 뒤로 버튼을 눌렀을 때 현재 표시된 내 조각에 관련된 변경을 하는 것을 사용합니다.

이것은 위의 스티븐의 답변에 근거한 것입니다.이렇게 하면 부모 활동에 이미 연결된 조각의 실제 인스턴스가 반환됩니다.

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
                }
            }
        }
    }

저는 이것을 하는 간단하고 깨끗한 방법을 찾을 수 없었습니다.그러나 ViewPager 위젯은 조각을 호스트하는 또 다른 ViewGroup일 뿐입니다.ViewPager에는 이러한 조각이 즉시 하위 항목으로 포함되어 있습니다.따라서 .getChildCount() 및 .getChildAt()를 사용하여 이를 반복하고, 찾고 있는 조각 인스턴스가 현재 ViewPager에 로드되어 있는지 확인하고 참조할 수 있습니다. 예를 들어 정적 고유 ID 필드를 사용하여 조각을 구분할 수 있습니다.

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

FragmentPagerAdapter는 fragment의 팩토리입니다.메모리에 남아 있는 경우 위치를 기준으로 fragment를 찾으려면 다음을 사용합니다.

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

v4 지원 API의 샘플 코드입니다.

전화할 필요가 없습니다.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);
}

을 확장해야 .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;

안녕하세요, 저는 여기서 이 질문에 답했습니다.기본적으로, 당신은 당신을 무시할 필요가 있습니다.

공용 개체 인스턴스화 항목(ViewGroup 컨테이너, 위치)

FragmentStatePagerAdapter 메서드입니다.

최상의 솔루션은 SmartFragmentStatePagerAdapter라는 CodePath에서 만든 확장을 사용하는 것입니다.이 안내서를 사용하면 ViewPager에서 조각 및 현재 선택한 조각을 훨씬 쉽게 검색할 수 있습니다.또한 어댑터에 내장된 단편의 메모리를 더 잘 관리할 수 있습니다.

가장 쉽고 간결한 방법. 조이들각든에 있는 ViewPager검색하여 다음과 같이 구분할 수 있는 클래스가 서로 다릅니다.

public class MyActivity extends Activity
{

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

}

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

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

활동 중에 어댑터에서 fragment를 가져와 instanceOf required fragment인지 확인한 다음 필요한 메소드를 캐스트하여 사용합니다.

/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;
        }

그런 다음 활동 중에 이 함수를 작성하여 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에 캐스트합니다.

Fragment fragment = getFragmentByPosition(position);

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

fragment 관리자에서 fragment를 쉽게 반복할 수 있습니다.공개 정적 플레이스홀더 조각 newInstance(int sectionNumber)에 배치된 횡단 위치 인수가 있는 뷰페이지를 찾습니다.

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

조각 속에

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

}

조각 작업 중

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

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

를 들어,이므로, fragment1은 0입니다.findFragmentByTag()메서드는 Viewpager에 대한 태그를 전달합니다.fragmentTransaction을 사용한 후 추가할 수 있는 fragment를 바꿉니다.

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

입니다.FragmentStatePagerAdapter해결책에 자금을 지원합니다.

조각 작업:

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

클래스에 메서드를 만듭니다. Fragment Activity - 이 메서드를 사용하면 Fragment에 액세스할 수 있습니다. 원하는 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;
}

}
Fragment yourFragment = yourviewpageradapter.getItem(int index);

index당신이 추가한 것처럼 어댑터의 조각 위치입니다.fragment1최초의 소굴의fragment1통과하다index휴식을 위해 0 등으로

언급URL : https://stackoverflow.com/questions/8785221/retrieve-a-fragment-from-a-viewpager

반응형