it-swarm.com.ru

Возможно ли получить доступ к текущему фрагменту, просматриваемому ViewPager?

У меня есть приложение с ViewPager и тремя Fragments. Я пытаюсь выяснить, как получить текущую переменную Fragment, чтобы я мог получить ее аргументы. 

У меня есть OnPageChangeListener, получающий индекс текущей страницы, но 

ViewPager.getChildAt(int position);

возвращает View. Какая связь между этим View и текущим Fragment?

69
MitchellSalad

Я наконец нашел ответ который работал для меня. По сути, вы можете получить доступ к фрагменту страницы ViewPager с помощью тега «Android: switcher:» + R.id.viewpager + «: 0». 

46
James

Я решил эту проблему наоборот ... Вместо того, чтобы искать фрагмент из действия, я регистрирую фрагмент во время его метода onAttach () в действии его владельца и отменяю его регистрацию в onStop () метод . Основная идея:

Фрагмент:

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    try{
        mActivity = (IMyActivity)activity;
    }catch(ClassCastException e){
        throw new ClassCastException(activity.toString() +" must be a IMyActivity");
    }

    mActivity.addFragment(this);
}

@Override
public void onStop() {
    mActivity.removeFragment(this);
    super.onStop();
}

IMyActivity:

public interface IFriendActivity {
    public void addFragment(Fragment f);
    public void removeFragment(Fragment f); 
}

MyActivity:

public class MyActivity implements IMyActivity{

    [...]

    @Override
    public void addFragment(Fragment f) {
        mFragments.add(f);
    }

    @Override
    public void removeFragment(Fragment f) {
        mFragments.remove(f);
    }

}
18
sdl

Редактировать - не делай этого. Если у вас есть искушение, прочитайте комментарии, почему это плохая идея.

По случайности вы все еще пытаетесь решить эту проблему:

Расширить FragmentPagerAdapter. В конструкторе создайте необходимые фрагменты и сохраните их в списке (массив/ArrayList) фрагментов. 

private final int numItems = 3;
Fragment[] frags;

public SwipeAdapter (FragmentManager fm) {
    super(fm);

    //Instantiate the Fragments
    frags = new Fragment[numItems];

    Bundle args = new Bundle();
    args.putString("arg1", "foo");

    frags[0] = new MyFragment();
    frags[1] = new YourFragment();
    frags[2] = new OurFragment();
    frags[2].setArguments(args);
}

Тогда для getItem(int position) вы можете сделать что-то вроде 

public Fragment getItem(int position) {
    return frags[position];
}

Я не уверен, является ли это общепринятым способом сделать это, но это сработало для меня.

Правка

Это действительно не очень хороший путь. Если вы планируете обрабатывать изменения ориентации или ваше приложение переходит в фоновый режим, то это, вероятно, нарушит ваш код. Пожалуйста, прочитайте комментарии ниже этого ответа для получения дополнительной информации. Скорее используйте ответ @James

5
Mike T

Да, это возможно, если вы используете FragmentStatePagerAdapter.

ViewPager vp;
//...
YourFragment fragment = (YourFragment) adapter.instantiateItem(vp, vp.getCurrentItem());
4
Volodymyr Kulyk

ПОЖАЛУЙСТА, НЕ ИСПОЛЬЗУЙТЕ ЭТО

Заставьте свой адаптер расширить следующий класс FragmentStatePagerWithCurrentAdapter и вместо реализации getItem внедрить тот же код в getItemAtIndex

Задайте ViewPagerOnPageChangeListener для экземпляра адаптера. 

Когда вам нужно получить доступ к текущему фрагменту, вы просто вызываете adapter.getCurrentItem().

package your.package;
import Android.support.v4.app.Fragment;
import Android.support.v4.app.FragmentManager;
import Android.support.v4.app.FragmentStatePagerAdapter;
import Android.support.v4.view.ViewPager.OnPageChangeListener;
import Android.util.SparseArray;
import Android.view.ViewGroup;

public abstract class FragmentStatePagerWithCurrentAdapter 
extends FragmentStatePagerAdapter 
implements OnPageChangeListener {
    int currentPage = 0;

    private SparseArray<Fragment> mPageReferenceMap = new SparseArray<Fragment>();

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

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

    public abstract Fragment getItemAtIndex(int index);

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {

        super.destroyItem(container, position, object);

        mPageReferenceMap.remove(Integer.valueOf(position));
    }

    public Fragment getCurrentItem() {
        return mPageReferenceMap.get(currentPage);
    }

    @Override
    public void onPageScrollStateChanged(int arg0) {

    }

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

    }

    @Override
    public void onPageSelected(int newPageIndex) {
        currentPage = newPageIndex;
    }

}

Я использовал в качестве ссылки следующее сообщение в блоге: http://tamsler.blogspot.com/2011/11/Android-viewpager-and-fragments-part-ii.html

3
Jorge Garcia

Окончательный ответ, который работает без проблем (но небольшой взлом):

где-то в макете фрагмента страницы:

<FrameLayout Android:layout_width="0dp" Android:layout_height="0dp" Android:visibility="gone" Android:id="@+id/fragment_reference">
     <View Android:layout_width="0dp" Android:layout_height="0dp" Android:visibility="gone"/>
</FrameLayout>

во фрагменте onCreateView (): 

...
View root = inflater.inflate(R.layout.fragment_page, container, false);
ViewGroup ref = (ViewGroup)root.findViewById(R.id.fragment_reference);
ref.setTag(this);
ref.getChildAt(0).setTag("fragment:" + pageIndex);
return root;

и метод для возврата фрагмента из ViewPager, если он существует:

public Fragment getFragment(int pageIndex) {        
        View w = mViewPager.findViewWithTag("fragment:" + pageIndex);
        if (w == null) return null;
        View r = (View) w.getParent();
        return (Fragment) r.getTag();
}
1
Hox

Вы можете сделать это: - В экстенте класса адаптера пейджера представления (такого как PagerAdapter, FragmentStatePagerAdapter ...) переопределить метод instantiateItem:

@Override
public Object instantiateItem(ViewGroup container, int position) {
        final Fragment frag = (Fragment) super.instantiateItem(container, position);
        if(frag instanceof ListNoteOfTypeFragment){                
            final ListNoteOfTypeFragment listNoteOfTypeFragment = (ListNoteOfTypeFragment) frag;
            //do whatever you want with your fragment here
            listNoteOfTypeFragment.setNoteChangeListener(mListener);
        }
        return frag;
    }    
1
Anh Nguyen

Это было объяснено здесь: http://developer.Android.com/guide/topics/fundamentals/fragments.html

В OnCreateView вы должны вернуть представление, чтобы нарисовать пользовательский интерфейс для вашего фрагмента, я думаю, что это отношения.

Также этот вопрос может быть похожим: Сосредоточиться View от ViewPager

1
Dante

FragmentStatePagerWithCurrentAdapter Хорхе Гарсии является очень хорошим решением, но требует небольшого улучшения. В случае, если действие будет уничтожено и воссоздано в ответ на изменение конфигурации или что-то подобное, getItem не будет вызываться для фрагментов, которые были сохранены и извлечены менеджером фрагментов. Поэтому я обычно перезаписываю getItem в своем подклассе и помещаю следующее в FragmentStatePagerWithCurrentAdapter 

@Override
public Object instantiateItem(ViewGroup container, int position) {
    Object item = super.instantiateItem(container, position);
    if ( item instanceof Fragment ) {
        pageReferenceMap.put(position, (Fragment)item);
    }
    return item;
}

InstantiateItem вызывается каждый раз, когда к фрагменту в этой позиции обращаются.

0
dmapr

Или просто сохраните все фрагменты на карте:

public class MyFragment extends Fragment implements OnPageChangeListener {

    private ViewPager viewPager;
    private FragmentStatePagerAdapter viewAdapter;
    private View rootView;
    private Map<Integer, Fragment> fragments = new HashMap<Integer, Fragment>();

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

        rootView = inflater.inflate(R.layout.introdution, container, false);

        viewPager = (ViewPager) rootView.findViewById(R.id.pager);
        viewAdapter = new ViewAdapter(getFragmentManager());
        viewPager.setAdapter(viewAdapter);
        viewPager.addOnPageChangeListener(this);

        return rootView;

    }

    private class ViewAdapter extends FragmentStatePagerAdapter {

        public ViewAdapter(FragmentManager fragmentManager) {
            super(fragmentManager);
        }

        @Override
        public Fragment getItem(int position) {

            Fragment result = null;

            switch (position) {
                case 0: result = Fragment1.newInstance(); break;
                case 1: result = Fragment2.newInstance(); break;
            }

            if (result != null)
                fragments.put(position, result);

            return result;

        }

        @Override
        public int getCount() {

            return 2;
        }

    }

    @Override
    public void onPageScrollStateChanged(int arg0) {
    }

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

    @Override
    public void onPageSelected(int position) {

        Fragment currentFragment = fragments.get(position);

    }

}
0
almisoft