同僚!回避方法がわからない例外があります。SherlockFragmentActivity の ViewPager で TabHost を作成しました。TabHost にはフラグメントが含まれています。
アクティビティ:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tabs_fragment_layout);
mTabHost = (TabHost) findViewById(android.R.id.tabhost);
mViewPager = (ViewPager) findViewById(R.id.pager);
mTabHost.setup();
setupTabs();
if (savedInstanceState != null) {
mTabHost.setCurrentTabByTag(savedInstanceState.getString(CURRENT_TAB_KEY));
}
}
private void setupTabs() {
nameTabs = getResources().getStringArray(R.array.tabs);
mTabsAdapter = new TabsAdapter(this, mTabHost, mViewPager);
mTabsAdapter.addTab(newTab(TABS_TAG_1, R.drawable.ic_action_countries,
nameTabs[COUNTRIES_TAB_INDEX]), CountryTabFragment.class, null);
mTabsAdapter.addTab(newTab(TABS_TAG_2, R.drawable.ic_action_settings_dark,
nameTabs[SETTINGS_TAB_INDEX]),UltiPreferenceFragment.class, null);
mTabsAdapter.addTab(newTab(TABS_TAG_3, R.drawable.ic_action_about,
nameTabs[ABOUT_TAB_INDEX]), AboutFragment.class, null);
}
private TabSpec newTab (String tag, int iconId, String tabTitle) {
TabSpec tab = mTabHost.newTabSpec(tag);
tab.setIndicator(tabTitle, getResources().getDrawable(iconId));
return tab;
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(CURRENT_TAB_KEY, mTabHost.getCurrentTabTag());
}
private Fragment getFragmentByIndex(ViewPager container, int position) {
String name = makeFragmentName(container.getId(), position);
return getSupportFragmentManager().findFragmentByTag(name);
}
private String makeFragmentName(int viewId, int index) {
return getString(R.string.fragment_name_pattern, viewId, index);
}
public static class TabsAdapter extends FragmentPagerAdapter
implements TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener {
private final Context mContext;
private final TabHost mTabHost;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
static final class TabInfo {
private final String tag;
private final Class<?> clss;
private final Bundle args;
TabInfo(String tag, Class<?> clss, Bundle args) {
this.tag = tag;
this.clss = clss;
this.args = args;
}
}
static class DummyTabFactory implements TabHost.TabContentFactory {
private final Context mContext;
public DummyTabFactory(Context context) {
mContext = context;
}
@Override
public View createTabContent(String tag) {
View view = new View(mContext);
view.setMinimumWidth(0);
view.setMinimumHeight(0);
return view;
}
}
public TabsAdapter(FragmentActivity activity, TabHost tabHost, ViewPager pager) {
super(activity.getSupportFragmentManager());
mContext = activity;
mTabHost = tabHost;
mViewPager = pager;
mTabHost.setOnTabChangedListener(this);
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
mViewPager.setId(R.id.view_pager);
}
public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
tabSpec.setContent(new DummyTabFactory(mContext));
String tag = tabSpec.getTag();
TabInfo info = new TabInfo(tag, clss, args);
mTabs.add(info);
mTabHost.addTab(tabSpec);
notifyDataSetChanged();
}
@Override
public int getCount() {
return mTabs.size();
}
@Override
public Fragment getItem(int position) {
TabInfo info = mTabs.get(position);
return Fragment.instantiate(mContext, info.clss.getName(), info.args);
}
@Override
public int getItemPosition(Object object) {
return PagerAdapter.POSITION_NONE;
}
@Override
public void onTabChanged(String tabId) {
int position = mTabHost.getCurrentTab();
mViewPager.setCurrentItem(position);
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
TabWidget widget = mTabHost.getTabWidget();
int oldFocusability = widget.getDescendantFocusability();
widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
mTabHost.setCurrentTab(position);
widget.setDescendantFocusability(oldFocusability);
}
@Override
public void onPageScrollStateChanged(int state) {
}
}
7 インチのデバイスでは、TabHost の FirstFragment に縦向きと横向きの 2 つのレイアウトがあります。画面を回転させると、レイアウトを変更する必要があります。残念ながら、画面の回転中にアプリで利用できるダイアログ (DialogFragment) やその他の長期的なプロセスのコンテキストが失われるため、アクティビティを再作成することはできません。だから、1)私は AndroidManifest.xml で使用します
android:configChanges="orientation|screenSize"
2) アクティビティの onConfigurationChanged() メソッドをオーバーライドします。
@Override
public void onConfigurationChanged(Configuration newConfig) {
int oldConfigOrientation = getRequestedOrientation();
super.onConfigurationChanged(newConfig);
if (newConfig.orientation != oldConfigOrientation) {
Toast.makeText(this, "orientation changed!", Toast.LENGTH_SHORT).show();
mTabsAdapter.notifyDataSetChanged();
}
}
3) タブの再レイアウトのための FragmentPagerAdapter の ovveride getItemPosition() メソッド。画面を回転すると問題が発生し、2 パネル レイアウトではなく 1 つのフラグメントで 1 パネル レイアウトをロードする必要があります。
04-12 12:30:44.019: E/AndroidRuntime(11151): java.lang.IllegalArgumentException: No view found for id 0x7f05004f (com.ziko.widget:id/setup_layout_fragment) for fragment SetupCityFragment{410fac80 #1 id=0x7f05004f}
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:903)
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1088)
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1070)
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1861)
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1474)
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:931)
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.support.v4.app.FragmentManagerImpl.attachFragment(FragmentManager.java:1264)
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:672)
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1444)
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:461)
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.support.v4.view.ViewPager.populate(ViewPager.java:1011)
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:522)
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:494)
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.support.v4.view.ViewPager.dataSetChanged(ViewPager.java:874)
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.support.v4.view.ViewPager$PagerObserver.onChanged(ViewPager.java:2688)
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.database.DataSetObservable.notifyChanged(DataSetObservable.java:35)
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.support.v4.view.PagerAdapter.notifyDataSetChanged(PagerAdapter.java:276)
04-12 12:30:44.019: E/AndroidRuntime(11151): at com.ziko.widget.ui.ConfigurationActivity.onConfigurationChanged(ConfigurationActivity.java:140)
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.app.ActivityThread.performConfigurationChanged(ActivityThread.java:3461)
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.app.ActivityThread.handleConfigurationChanged(ActivityThread.java:3585)
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1220)
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.os.Handler.dispatchMessage(Handler.java:99)
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.os.Looper.loop(Looper.java:137)
04-12 12:30:44.019: E/AndroidRuntime(11151): at android.app.ActivityThread.main(ActivityThread.java:4424)
04-12 12:30:44.019: E/AndroidRuntime(11151): at java.lang.reflect.Method.invokeNative(Native Method)
04-12 12:30:44.019: E/AndroidRuntime(11151): at java.lang.reflect.Method.invoke(Method.java:511)
04-12 12:30:44.019: E/AndroidRuntime(11151): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
04-12 12:30:44.019: E/AndroidRuntime(11151): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:558)
04-12 12:30:44.019: E/AndroidRuntime(11151): at dalvik.system.NativeStart.main(Native Method)
この問題は、1 パネル (縦) レイアウトから 2 パネル (横) レイアウトに画面を回転させたときに発生したことはありませんが、反対の場合は常に発生します。メソッド mTabsAdapter.notifyDataSetChanged(); の呼び出し中に例外がスローされます。onConfigurationChanged() で。
例外の理由と、今後それを回避する方法を説明できる人はいますか? 画面を回転させながらタブのレイアウトを変更する方法が他にあるのではないでしょうか?