12

アプリケーションにタブ付きActionBarSherlockを実装するために使用しています。ActionBarアプリを起動してタブからタブに切り替えると、すべて問題ありません。ただし、ポートレート モードからランドスケープ モードに変更すると、最後にアクティブだったタブのコンテンツが表示されたままになります。別のタブに変更すると、古いコンテンツの上に新しいコンテンツが描画されます (画像を参照)。

ここに画像の説明を入力

私の主なクラス:

public class TreinVerkeer extends SherlockFragmentActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setupTabs(savedInstanceState);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getSupportMenuInflater();
        inflater.inflate(R.menu.menu, menu);
        return true;
    }

    private void setupTabs(Bundle savedInstanceState) {
        ActionBar actionBar = getSupportActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        Tab tab = actionBar.newTab().setText("STATIONS").setTabListener(new TabListener<StationsFragment>(this, "stations", StationsFragment.class));
        actionBar.addTab(tab);

        tab = actionBar.newTab().setText("ROUTE").setTabListener(new TabListener<RouteFragment>(this, "route", RouteFragment.class));
        actionBar.addTab(tab);

        tab = actionBar.newTab().setText("DELAYS").setTabListener(new TabListener<DelaysFragment>(this, "delays", DelaysFragment.class));
        actionBar.addTab(tab);

        if (savedInstanceState != null) {
            actionBar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("tab", getSupportActionBar().getSelectedNavigationIndex());
    }
}

TabListener ( Android 開発者サイトの「Adding Navigations Tabs」から、若干の変更を加えたもの):

public class TabListener<T extends SherlockFragment> implements com.actionbarsherlock.app.ActionBar.TabListener {
    private SherlockFragment mFragment;
    private final Activity mActivity;
    private final String mTag;
    private final Class<T> mClass;

    /**
     * Constructor used each time a new tab is created.
     * 
     * @param activity
     *            The host Activity, used to instantiate the fragment
     * @param tag
     *            The identifier tag for the fragment
     * @param clz
     *            The fragment's Class, used to instantiate the fragment
     */
    public TabListener(Activity activity, String tag, Class<T> clz) {
        mActivity = activity;
        mTag = tag;
        mClass = clz;
    }

    /* The following are each of the ActionBar.TabListener callbacks */

    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        // Check if the fragment is already initialized
        if (mFragment == null) {
            // If not, instantiate and add it to the activity
            mFragment = (SherlockFragment) SherlockFragment.instantiate(mActivity, mClass.getName());
            ft.add(android.R.id.content, mFragment, mTag);
        } else {
            // If it exists, simply attach it in order to show it
            ft.attach(mFragment);
        }
    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        if (mFragment != null) {
            // Detach the fragment, because another one is being attached
            ft.detach(mFragment);
        }
    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {
        // User selected the already selected tab. Usually do nothing.
    }
}

StationsFragment(RouteFragmentDelaysFragmentは同じで、テキストが異なるだけです)

public class StationsFragment extends SherlockFragment {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.stationsfragment, container, false);
    }
}

それで、のレイアウトファイルStationsFragment

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Stations" />

</LinearLayout>

最後にマニフェスト ファイル:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.myapp"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".TreinVerkeer"
            android:label="@string/app_name"
            android:theme="@style/Theme.Sherlock.Light" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

アプリを起動した直後に同じ問題が発生しました (そのため、向きを変更することさえありません)。これは、メイン クラスの を削除することsetContentView(R.layout.main)で解決されました。onCreateしかし、これに対する解決策が見つかりません。誰でもこれで私を助けることができますか?

4

3 に答える 3

19

FragmentManager構成の変更時に現在表示されているフラグメント (および履歴) を自動的に復元します。findFragmentByTag新しいインスタンスを作成してアタッチする前に、ターゲット フラグメントのインスタンスが既に存在するかどうかを確認するために呼び出します。

于 2012-05-08T07:22:39.983 に答える
15

Jake のおかげで、onTabSelectedメソッドを次のように更新しました。

public void onTabSelected(Tab tab, FragmentTransaction ft) {
    SherlockFragment preInitializedFragment = (SherlockFragment) mActivity.getSupportFragmentManager().findFragmentByTag(mTag);

    // Check if the fragment is already initialized
    if (mFragment == null && preInitializedFragment == null) {
        // If not, instantiate and add it to the activity
        mFragment = (SherlockFragment) SherlockFragment.instantiate(mActivity, mClass.getName());
        ft.add(android.R.id.content, mFragment, mTag);
    } else if (mFragment != null) {
        // If it exists, simply attach it in order to show it
        ft.attach(mFragment);
    } else if (preInitializedFragment != null) {
        ft.attach(preInitializedFragment);
        mFragment = preInitializedFragment;
    }
}

この回答は明確化のみを目的としており、クレジットはジェイクに送られます:)

于 2012-05-08T10:00:14.700 に答える
5

Niekが投稿した変更に加えて、行う必要のある些細な変更がいくつかあります。主にActivityをSherlockFragmentActivityに変更するだけです。

他の人の利益のために、これが正しく機能しているように見える私の最終バージョンです。

   public static class TabListener<T extends SherlockFragment> implements ActionBar.TabListener
   {
      private SherlockFragment mFragment;
      private final SherlockFragmentActivity mActivity;
      private final String mTag;
      private final Class<T> mClass;

      /** Constructor used each time a new tab is created.
       * @param activity  The host Activity, used to instantiate the fragment
       * @param tag  The identifier tag for the fragment
       * @param clz  The fragment's Class, used to instantiate the fragment
       */
      public TabListener(Activity activity, String tag, Class<T> clz)
      {
         mActivity = (SherlockFragmentActivity) activity;
         mTag = tag;
         mClass = clz;
      }


      public void onTabSelected(Tab tab, FragmentTransaction ft)
      {
         // Check if the fragment has already been initialised
         SherlockFragment  preInitializedFragment = (SherlockFragment) mActivity.getSupportFragmentManager().findFragmentByTag(mTag);
         if (mFragment != null)
         {
            // If it exists, simply attach it in order to show it
            ft.attach(mFragment);
         }
         else if (preInitializedFragment != null)
         {
            mFragment = preInitializedFragment;
            ft.attach(mFragment);
         }
         else
         {
            // Not found, so instantiate and add it to the activity
            mFragment = (SherlockFragment) SherlockFragment.instantiate(mActivity, mClass.getName());
            ft.add(android.R.id.content, mFragment, mTag);
         }
      }


      public void onTabUnselected(Tab tab, FragmentTransaction ft)
      {
         if (mFragment != null) {
            // Detach the fragment, because another one is being attached
            ft.detach(mFragment);
         }
      }


      public void onTabReselected(Tab tab, FragmentTransaction ft)
      {
         // User selected the already selected tab. Usually do nothing.
      }
   }
于 2012-08-05T19:11:58.133 に答える