SherlockActionbar を使用した動的レイアウトを取得しました。ランドスケープ モードでは、2 つのフラグメントを並べて表示する必要があります。しかし、2 番目のフラグメントは表示されません。
MainActivity onCreate
@Override
public void onCreate(Bundle savedInstanceState) {
if (Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH){
this.setTheme(R.style.Theme_Sherlock);
}
if (savedInstanceState != null)
{
savedInstanceState.remove ("android:support:fragments");
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
actionbar = getSupportActionBar();
actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
tab1 = actionbar.newTab().setText("Search");
tab2 = actionbar.newTab().setText("Found");
tab3 = actionbar.newTab().setText("Account");
Class[] clzs;
String[] tags;
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
clzs = new Class[2];
tags = new String[2];
clzs[0] = ListSearchFragment.class;
tags[0] = "listsearch";
clzs[1] = DetailSearchFragment.class;
tags[1] = "detailsearch";
}
else
{
clzs = new Class[1];
tags = new String[1];
clzs[0] = ListSearchFragment.class;
tags[0] = "listsearch";
}
tab1.setTabListener(new MainTabListener<SherlockFragment>(this, clzs,tags));
clzs = new Class[1];
tags = new String[1];
clzs[0] = AccountOverviewFragment.class;
tags[0] = "accountoverview";
tab2.setTabListener(new MainTabListener<SherlockFragment>(this, clzs,tags));
tab3.setTabListener(new MainTabListener<SherlockFragment>(this, clzs,tags));
actionbar.addTab(tab1);
actionbar.addTab(tab2);
actionbar.addTab(tab3);
}
メインタブリスナー:
public class MainTabListener <T extends SherlockFragment> implements ActionBar.TabListener{
public SherlockFragment fragments[];
private Activity mActivity;
private Class<T>[] mClasses;
private String[] tags;
public MainTabListener(Activity activity, Class<T>[] clzs, String[] tags) {
this.mActivity = activity;
this.mClasses = clzs;
this.tags = tags;
this.fragments = new SherlockFragment[mClasses.length];
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
FragmentManager fragMgr = ((FragmentActivity) mActivity).getSupportFragmentManager();
ft = fragMgr.beginTransaction();
for(int i = 0; i < mClasses.length; i++)
{
if (fragments[i] == null) {
fragments[i] = (SherlockFragment) SherlockFragment.instantiate(mActivity, mClasses[i].getName());
ft.add(R.id.fragment_container, fragments[i],tags[i]);
}
else {
ft.attach(fragments[i]);
}
}
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
FragmentManager fragMgr = ((FragmentActivity) mActivity).getSupportFragmentManager();
ft = fragMgr.beginTransaction();
for(int i = 0; i < mClasses.length; i++)
{
if (fragments[i] != null) {
ft.detach(fragments[i]);
}
}
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
}
画面の向きがランドスケープ モードの場合、レイアウト グラビティと幅は 1/3 と 2/3 に設定されます。
ポートレート モードでは、リストを持つフラグメントが 1 つあります。1 つのアイテムをクリックすると、新しいアクティビティが開始され、他のフラグメントが新しい LinearLayout に追加されます。
詳細アクティビティ:
public class DetailSearchActivity extends SherlockFragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_found_detail);
FragmentManager fragMgr = this.getSupportFragmentManager();
FragmentTransaction ft = fragMgr.beginTransaction();
ft.add(R.id.fragment_container,SherlockFragment.instantiate(this, DetailSearchFragment.class.getName()) ,"detailsearch");
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
fragMgr.executePendingTransactions();
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
finish();
return;
}
Bundle extras = getIntent().getExtras();
try{
DetailSearchFragment fragmentdetail = (DetailSearchFragment) this.getSupportFragmentManager().findFragmentByTag("detailsearch");
if (extras != null) {
String s = extras.getString("title");
String d = extras.getString("description");
fragmentdetail.setText(s, d);
}
}catch(RuntimeException e){
e.printStackTrace();
}
}
}
ポートレート モードの問題は、テキストを設定しようとすると、フラグメント内のビューが初期化されていないように見えることです。膨張した FragmentLayout で Textview を取得しようとすると、NullPointerException が発生します (デフォルトの Text が表示されます)。FragmentLayoutが正常に膨張した後、どうすればsetText()メソッドを呼び出すことができますか?
編集: タグをTabListenerに記録すると、LandscapeModeのときに両方のフラグメント(リストと詳細)がFragmentTransactionに追加されるようです
これを ListItemClickListener に追加すると:
DetailSearchFragment fragmentdetail = (DetailSearchFragment) getActivity().getSupportFragmentManager().findFragmentByTag("detailsearch");
Log.d("detailfrag","exists: "+(fragmentdetail != null) + " is in Layout:" + (fragmentdetail.isInLayout()));
私は得る:
12-23 13:39:07.440: D/detailfrag(13403): exists: true is in Layout:false
Edit2 OK 2つのレイアウトの問題を解決しました。同じコンテナーに 2 つのフラグメントを追加することはできません。
タブリスナー:
public class MainTabListener <T extends SherlockFragment> implements ActionBar.TabListener{
public SherlockFragment fragments[];
private Activity mActivity;
private Class<T>[] mClasses;
private String[] tags;
private View[] myViews;
private int id = 1;
public MainTabListener(Activity activity, Class<T>[] clzs, String[] tags) {
this.mActivity = activity;
this.mClasses = clzs;
this.tags = tags;
this.fragments = new SherlockFragment[mClasses.length];
this.myViews = new View[mClasses.length];
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
FragmentManager fragMgr = ((FragmentActivity) mActivity).getSupportFragmentManager();
ft = fragMgr.beginTransaction();
for(int i = 0; i < mClasses.length; i++)
{
if (fragments[i] == null) {
fragments[i] = (SherlockFragment) SherlockFragment.instantiate(mActivity, mClasses[i].getName());
View myView = (View)new LinearLayout(mActivity);
LinearLayout.LayoutParams llp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
myView.setLayoutParams(llp);
ViewGroup container = (ViewGroup)mActivity.findViewById(R.id.fragment_container);
container.addView(myView);
myView.setId(findId());
myViews[i] = myView;
ft.add(myView.getId(), fragments[i],tags[i]);
}
else {
myViews[i].setVisibility(View.VISIBLE);
}
}
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
for(int i = 0; i < mClasses.length; i++)
{
if (fragments[i] != null) {
myViews[i].setVisibility(View.GONE);
}
}
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
public int findId(){
View v = (ViewGroup)mActivity.findViewById(id);
while (v != null){
v = (ViewGroup)mActivity.findViewById(++id);
}
return id++;
}
}
ポートレート モードで Fragment が 1 つしかない場合、FragmentView が作成される前に setText() メソッドが呼び出されるという問題がまだあります。