4

FragmentTwo次の状況でバックスタックから消えるのはなぜですか。

  • 私のアプリにはがFragment呼び出さFragmentOneれましたActivity
  • FragmentOneを保持しButtonます。クリックすると起動し、バックスタックFragmentTwoに追加されFragmentます。
  • FragmentTwoがありButton、クリックすると、ActionBarリンクされている2つFragmentsのタブに2つのタブが追加さFragmentThreeれますFragmentFourFragmentThreeが表示されます。
  • ここで戻るボタンをクリックすると、が表示されるはずFragmentTwoです。代わりに、表示されますFragmentOne。どこに行ったFragmentTwoの?

onKeyDown()自分のバックスタックをオーバーライドして実装を開始する前に、Fragments私が見逃している明らかなものがあるかどうかを尋ねたいと思いましたか?これをテストするとき、構成の変更は発生しないことに注意してください。

ここにリンクの説明を入力してください

詳細:

FragmentOneのボタンクリックハンドラーには次のものが含まれます。

    FragmentTransaction ft = getFragmentManager().beginTransaction();
    FragmentTwo fragment = new FragmentTwo();
    ft.addToBackStack(null);
    ft.replace(android.R.id.content, fragment).commit();

FragmentTwoボタンのクリックは、アクティビティで処理されます。

    getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    FragmentFour fragmentThree = new FragmentThree();
    FragmentFive fragmentFive = new FragmentFive();

    ActionBar.Tab tab = getActionBar().newTab().setText("Frag 3").setTabListener(new CustomTabListener<FragmentThree>(fragmentThree));
    getActionBar().addTab(tab);
    tab = getActionBar().newTab().setText("Frag 4").setTabListener(new CustomTabListener<FragmentFour>(fragmentFour));
    getActionBar().addTab(tab);

タブリスナーは次のとおりです。

public static class CustomTabListener<T extends Fragment> implements TabListener {
    Fragment fragment;

    public CustomTabListener(Fragment fragment) {
        this.fragment = fragment;
    }

    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        ft.replace(android.R.id.content, fragment);
    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        ft.remove(fragment);
    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {

    }
}

Fragments表示される前にバックスタックにさらに追加するFragmentThreeと、それは常に、そのFragment直前だけFragmentThreeが消えます。

戻るキーを押してタブ付きユーザービューを終了し、に戻るとFragmentOne、タブは引き続き表示されます。にリセットする必要があることは理解していますActionBarが、の代わりにが表示されNAVIGATION_MODE_STANDARDている理由は明らかではありません。FragmentOneFragmentTwo

4

5 に答える 5

2

問題は、タブを作成するかどうかだと思います

public void onTabSelected(Tab tab, FragmentTransaction ft) {
    ft.replace(android.R.id.content, fragment);
}

が呼び出され、前のフラグメントはバックスタックに追加されません

電話をかけようとしましたか

ft.addToBackStack(null);

フラグメント2ボタン処理コード。

onBackPressed()ただし、タブを削除するには、とにかく実装する必要があります。タブで新しい活動をしていきたいと思います。

于 2013-01-08T14:39:44.353 に答える
2

@Pierre Rymiortz、私はこの問題の回避策を実行しました。以下のコードを参照してください。

public class StartActivity extends SherlockFragmentActivity implements
    TabListener, OnBackStackChangedListener {

private Context mContext = null;

private ActionBar mActionBar;

private Tab mTab;

private Fragment mSelectFragment;

private final static int ONE = 0;
private final static int TWO = 1;
private final static int THREE = 2;
private final static int PLAYERS = 3;

private MenuItem mPlayerItem = null;

private FragmentTransaction mFragmentTransaction = null;

/**
 * by default is false - TABS were taken in the starting true - when we are
 * changing back to TABS from STANDARD
 */
private boolean mTabsChanges = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    mContext = this;

    mActionBar = getSupportActionBar();

    // hiding the ActionBar icon
    mActionBar.setDisplayShowHomeEnabled(true);

    // for displaying the Arrow button
    mActionBar.setDisplayHomeAsUpEnabled(true);

    // hide Actionbar title
    mActionBar.setDisplayShowTitleEnabled(true);

    // Create Actionbar Tabs
    mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    // Create first Tab
    mTab = mActionBar.newTab().setTabListener(this);
    mTab.setText("One");
    mActionBar.addTab(mTab);

    // Create Second Tab

    mTab = mActionBar.newTab().setTabListener(this);
    mTab.setText("Two");
    mActionBar.addTab(mTab);

    // Create Three Tab
    mTab = mActionBar.newTab().setTabListener(this);
    mTab.setText("Three");
    mActionBar.addTab(mTab);

    getSupportFragmentManager().addOnBackStackChangedListener(this);

}

@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
    mFragmentTransaction = ft;
    if (mTabsChanges) {
        // nothing to do here
        mTabsChanges = false;
    } else {
        switch (mActionBar.getSelectedNavigationIndex()) {
        case ONE:
            clearBackStack(mTabsChanges);
            mSelectFragment = new Fragment1();
            ft.replace(R.id.fragment_container, mSelectFragment, ONE + "");
            break;
        case TWO:
            clearBackStack(mTabsChanges);
            mSelectFragment = new Fragment2();
            ft.replace(R.id.fragment_container, mSelectFragment, TWO + "");
            break;
        case THREE:
            clearBackStack(mTabsChanges);
            mSelectFragment = new Fragment3();
            ft.replace(R.id.fragment_container, mSelectFragment, THREE + "");
            break;
        }
    }

}

@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    Toast.makeText(
            mContext,
            "tab unselected." + mActionBar.getSelectedNavigationIndex()
                    + "", Toast.LENGTH_SHORT).show();
}

@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
    Toast.makeText(
            mContext,
            "tab reselected." + mActionBar.getSelectedNavigationIndex()
                    + "", Toast.LENGTH_SHORT).show();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // TODO Auto-generated method stub
    MenuInflater mInflate = getSupportMenuInflater();
    mInflate.inflate(R.menu.header_menu, menu);

    mPlayerItem = menu.findItem(R.id.men_set_players);

    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == R.id.men_set_players) {
        addFragmentToStack();
        return true;
    }
    return false;
}

private void addFragmentToStack() {

    // Add the fragment to the activity, pushing this transaction
    // on to the back stack.
    mActionBar.setTitle(getResources().getString(R.string.menu_players));
    mSelectFragment = new PlayersFragment();
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    ft.replace(R.id.fragment_container, mSelectFragment, "Players");
    ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
    ft.addToBackStack("players");
    ft.commit();
}

@Override
public void onBackStackChanged() {
    FragmentManager fm = getSupportFragmentManager();
    if (fm.getBackStackEntryCount() > 0) {
        int TOP = fm.getBackStackEntryCount() - 1;
        Log.i("BACKSTACK", TOP + ".."
                + fm.getBackStackEntryAt(TOP).getName());
        if (fm.getBackStackEntryAt(TOP).getName()
                .equalsIgnoreCase("players")) {
            if (mActionBar.getNavigationMode() == ActionBar.NAVIGATION_MODE_TABS) {
                mTabsChanges = false;
                mActionBar
                        .setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
            }
        } else {
            if (mActionBar.getNavigationMode() == ActionBar.NAVIGATION_MODE_STANDARD) {
                mTabsChanges = true;
                mActionBar
                        .setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
            }
        }

    } else {
        if (mActionBar.getNavigationMode() == ActionBar.NAVIGATION_MODE_STANDARD) {
            mTabsChanges = true;
            mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        } else if (mActionBar.getNavigationMode() == ActionBar.NAVIGATION_MODE_TABS) {
            mTabsChanges = false;
        }
    }

    Toast.makeText(mContext,
            "FM Back count." + fm.getBackStackEntryCount(),
            Toast.LENGTH_SHORT).show();
}

public void clearBackStack(boolean callFromSelection) {
    if (!callFromSelection) {
        FragmentManager fm = getSupportFragmentManager();
        for (int i = 0; i < fm.getBackStackEntryCount(); i++) {
            fm.popBackStackImmediate();
        }
    } else {
        Toast.makeText(mContext, "callfromreapprearence",
                Toast.LENGTH_SHORT).show();
    }
}

}
于 2013-08-07T13:34:26.850 に答える
1

フラグメントを置き換えるには、常にこのコードブロックを使用してください。

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(android.R.id.content, YOUR_FRAGMENT);
ft.addToBackStack(null);
ft.commit();
于 2013-01-10T23:34:43.767 に答える
1

replaceはすでにこれを行っているのでft.remove、関数内のを削除する必要があると思います。onTabUnselected()

于 2013-01-16T22:12:09.467 に答える
1

上に示したコードによると、Fragment2をバックスタックに追加することはありません。

@ gabe、@ Pierre、addToBackStack()リスナーで使用してIllegalStateExceptionが発生する理由は、APIhttp://developer.android.com/reference/android/app/ActionBar.TabListener.htmlに記載されています

public abstract void onTabSelected (ActionBar.Tab tab, FragmentTransaction ft)  

APIレベル11で追加

タブが選択された状態になったときに呼び出されます。

[パラメータ]タブ選択されたタブ

ftタブ切り替え中に実行するフラグメント操作をキューに入れるためのFragmentTransaction。前のタブの選択解除とこのタブの選択は、単一のトランザクションで実行されます。

このFragmentTransactionは、バックスタックへの追加をサポートしていません。

これを回避する簡単な方法は、FragmentManagerを使用してTabListener内に独自のFragmentTransactionを取得し、それをバックスタックに追加することです。このようなもの

    public static class CustomTabListener<T extends Fragment> implements TabListener {
    Fragment fragment;

    public CustomTabListener(Fragment fragment) {
        this.fragment = fragment;
    }

    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        FragmentManager fm = getFragmentManager();
        FragmentTransaction newFragTrans = fm.beginTransaction();
        newFragTrans.replace(android.R.id.content, fragment);
        newFragTrans.addToBackStack(null);
        newFragTrans.commit()
        
    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        ft.remove(fragment);
    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {

    }
}

onTabSelectedのみを変更しましたが、要点はわかります。commit()また、リスナーは自動的commit()に提供されたもののみを実行するため、このトランザクションを忘れないでくださいFragmentTransaction ft

最後に、トランザクションの実行後に呼び出していることを確認addToBackStack()してください。これは、実際のフラグメントではなく、スタックに追加するものだからです。上記のコードでは、これはFragment1のボタンクリックでは実行されませんでした。

お役に立てれば。

于 2013-01-17T22:51:17.970 に答える