ActionBarタブを設定しています。 4つのタブで構成されています。 TabbedFragment
から離れて戻ってくるまでは、すべて問題ありません。
私はこのようなタブを作成します:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ActionBar actionBar = getActionBar();
tabs = Lists.newArrayList();
tabs.add(new TabDefinition<>("Tab 1"));
tabs.add(new TabDefinition<>("Tab 2"));
tabs.add(new TabDefinition<>("Tab 3"));
tabs.add(new TabDefinition<>("Tab 4"));
for (TabDefinition tab : tabs) {
actionBar.addTab(actionBar.newTab()
.setText(tab.text)
.setTag(tab.tag)
.setTabListener(this));
}
}
そして、このようにアダプターを初期化します:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.paging_tab_container, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
viewPager = (ViewPager) view.findViewById(R.id.pager);
viewPager.setAdapter(new FragmentStatePagerAdapter(getFragmentManager()) {
@Override
public Fragment getItem(int position) {
return tabs.get(position).fragment;
}
@Override
public int getCount() {
return tabs.size();
}
});
viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
getActionBar().setSelectedNavigationItem(position);
}
});
viewPager.setCurrentItem(getActionBar().getSelectedNavigationIndex(), true);
}
TabbedFragment
に戻ると、選択したタブとその隣の1にはコンテンツがありません。空のビュー。しかし、現在+ 2を選択すると、フラグメントコンテンツが読み込まれます。その後、最初のフラグメントコンテンツに戻ります。
たとえば、A、B、C、Dのタブがあります。 TabbedFragment
を離れる前に、タブAを選択しました。TabbedFragment
に戻ると、タブAにいますが、空です。タブBも同様です。
しかし、タブCを選択すると、それが作成されてロードされます。タブAに戻り、再作成されます。
ここで何が問題になるのでしょうか?
しばらくして再び同じ問題に遭遇したので、この質問を更新しました。 FragmentStatePagerAdapter
を使用している場合は、getChildFragmentManager()
ではなくgetFragmentManager()
を使用してFragmentManager
を提供する必要があります。参照 問題55068:バックスタックを介して戻るナビゲーション時にViewPagerが子フラグメントを更新しない
さて、FragmentStatePagerAdapter
を使用すると、上記のようにデフォルトでoffScreenPageLimit
がデフォルトで1に設定されているため、複数のフラグメントを離れると、フラグメントが破棄されます。
通常、このクラスは、非常に大きなFragments
のセットがあるアクティビティ、つまり大量のビューをスクロールする必要があるアクティビティに使用されます。アプリケーションで必要なのが3〜4個のタブだけである場合は、代わりにFragmentPagerAdapter
を使用して、offScreenPageLimitを3のように指定することをお勧めします。したがって、4番目のタブに到達すると、それ以前の3つのタブはすべてそのままになります。記憶にある。
これは、私が作成したgithub上のプロジェクトのサンプルコードで、このoffScreenPageLimitを追加したくない場合にフラグメントを動的にロードする方法を示しています。
このクラスのすべてのコードをウォークスルーすると、ViewPager
がスライドされるたびに、フラグメントを動的にロードする方法がわかります。最も注目すべきは下部です。
このコードをダウンロードして、目的のテストベースとして使用できます。 viewPagerのonCreate()メソッドにsetOffScreenPageLimit(2)を追加してみて、異なる動作に注目してください。動作を確認するには、フラグメント1のテキストを編集します。この設定の有無にかかわらず、[離れる]に移動して戻ってください。フラグメントが再作成されることはないため、設定されると、フラグメントのテキストは変更後のテキストのままになります。
質問がある場合は、追加で質問してください。
幸運を
[〜#〜]更新[〜#〜]
private static final String [] fragmentClasses = {"com.example.project.YourFragment1","com.example.project.YourFragment2","com.example.project.YourFragment3"};
viewPager.setAdapter(new FragmentStatePagerAdapter(getFragmentManager()) {
@Override
public Fragment getItem(int position) {
Fragment fragmentAtPosition = null;
// $$$$ This is the Important Part $$$$$
// Check to make sure that your array is not null, size is greater than 0 , current position is greater than equal to 0, and position is less than length
if((fragmentClasses != null) && (fragmentClasses.length > 0)&&(position >= 0)&& (position < fragmentClasses.length))
{
// Instantiate the Fragment at the current position of the Adapter
fragmentAtPosition = Fragment.instantiate(getBaseContext(), fragmentClasses[position]);
fragmentAtPosition.setRetainInstance(true);
}
return fragmentAtPosition;
}
@Override
public int getCount() {
return fragmentClasses.length;
}
});
タブとして使用するフラグメントに問題があると思います。再開しても何も表示されないようです( フラグメントライフサイクル を参照)。現在選択されている+/- 1タブのみが空である「奇妙な」問題は、offScreenPageLimit
の- ViewPager
がデフォルトで1であるためです。このしきい値を超えるすべてのタブが再作成されます。
したがって、値を増やすと(場合によっては)、再開後にすべてのタブが空に表示されます。レイアウトの拡張、アダプタの設定などに使用するライフサイクルメソッドをFragmentコードにチェックインします。これが問題の原因です。
これは、フラグメントのロード中にAndroidが現在とcurrent + 1をロードするため、デバッグすると、すぐ次のフラグメントに対してonPauseが呼び出されないことが原因と考えられます。
TabHost.OnTabChangeListenerのonTabChanged()メソッドでプログラムでコンテンツを再ロードできます。
多くの研究を行った後、これは私のために働いた。フラグメントに3つのタブがあり、他のフラグメントに切り替えられる複雑なレイアウトがあります。ホームボタンを押しても、ViewpagerAdapter
は状態を保持することに気づきました。私の問題は、前後に切り替えると、子フラグメントのUIビュー要素が無効になり、クラッシュすることでした。重要なのは、あなたのnew
をViewPagerAdapter
出さないことです。アダプターのnullチェックを追加するとうまくいきました。また、必要に応じてsetOffscreenPageLimit()
を割り当ててください。また、私が理解していることから、setRetainInstance(true);
はUIを持つフラグメントには使用しないでください。ヘッドレスフラグメント用に設計されています。
タブを保持するフラグメントで:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_tab, container, false);
tabLayout = (TabLayout) view.findViewById(R.id.tablayout);
viewPager = (ViewPager) view.findViewById(R.id.viewPager);
//Important!!! Do not fire the existing adapter!!
if (viewPagerAdapter == null) {
viewPagerAdapter = new ViewPagerAdapter(getChildFragmentManager());
viewPagerAdapter.addFragments(new AFragment(), "A");
viewPagerAdapter.addFragments(new BFragment(), "B");
viewPagerAdapter.addFragments(new CFragment(), "C");
}
//Allocate retention buffers for three tabs, mandatory
viewPager.setOffscreenPageLimit(3);
tabLayout.setupWithViewPager(viewPager);
viewPager.setAdapter(viewPagerAdapter);
return view;
}
または、より簡単にtabbedfragment
に戻るとき(インテントを使用し、フラグメントがアクティビティ内にあると想定)、以下を使用します。
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
これにより、元のアクティビティが保持され、再作成されるのではなくスタックの一番上に移動されるため、viewPagerを再作成する必要はありません。