ViewPager
と3つのFragment
sを持つアプリがあります。現在のFragment
を表示する方法を見つけて、引数を取得できるようにしています。
現在のページインデックスを取得しているOnPageChangeListener
がありますが、
ViewPager.getChildAt(int position);
View
を返します。このView
と現在のFragment
との関係は何ですか?
私はついに 答え を見つけました。基本的に、タグ "Android:switcher:" + R.id.viewpager + ":0"を使用して、viewPagerページのフラグメントにアクセスできます。
私はこの問題を逆に解決しました。アクティビティからフラグメントを検索する代わりに、所有者のアクティビティで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);
}
}
編集-これをしないでください。あなたが誘惑されたら、それが悪い考えである理由についてのコメントを読んでください。
奇妙なことに、あなたはまだこの問題を解決しようとしています:
FragmentPagerAdapter
を拡張します。コンストラクターで、必要なフラグメントを構築し、フラグメントのリスト(配列/配列リスト)に保存します。
_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の答えを使用してください
はい、FragmentStatePagerAdapter
を使用している場合は可能です。
ViewPager vp;
//...
YourFragment fragment = (YourFragment) adapter.instantiateItem(vp, vp.getCurrentItem());
これを使用しないでください
アダプターに次のFragmentStatePagerWithCurrentAdapter
クラスを拡張させ、getItem
を実装する代わりにgetItemAtIndex
に同じコードを実装します
ViewPager
OnPageChangeListener
をアダプターのインスタンスに設定します。
現在のフラグメントにアクセスする必要がある場合は、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
シームレスに機能する決定的な答え(ただし小さなハック):
ページフラグメントのレイアウトのどこかに:
<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();
}
これを行うことができます:-ビューページャーアダプターのクラス範囲(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;
}
ここで説明されています: http://developer.Android.com/guide/topics/fundamentals/fragments.html
OnCreateViewでは、フラグメントのUIを描画するためにビューを返す必要があります。それが関係だと思います。
また、この質問は似ているかもしれません: ViewPagerからフォーカスされたビューを取得する
Jorge Garciaの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は、その位置のフラグメントにアクセスするたびに呼び出されます。
または、すべてのフラグメントをマップに保存するだけです:
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);
}
}