web-dev-qa-db-ja.com

Androidナビゲーションドロワーフラグメントの状態

現在、Android APPにナビゲーションドロワーを使用しています。最初のフラグメントには、FacebookのGraph APIを使用してデータをロードするフラグメントがあります。したがって、アプリを最初にロードすると、最初に最初のフラグメントに移動します。

First

次に、ナビゲーションドロワーを使用して、別のフラグメントをクリックして表示します。

Second Fragment

そして最後に、ナビゲーションドロワーを再利用して、最初のフラグメントに戻って表示します。

First Fragment

私が直面している問題は、ナビゲーションドロワーアイテムが選択されるたびにフラグメントを再作成するのではなく、一度作成されたフラグメントをどのように利用するかです。フラグメントを切り替えるための私のコードは次のとおりです。

private void displayView(int position) {
    // update the main content by replacing fragments
    Fragment fragment = null;
    switch (position) {
    case 0:
        fragment = new SelectionFragment();
        break;
    case 1:
        fragment = new HomeFragment();
        break;
    case 2:
        fragment = new PhotosFragment();
        break;
    case 3:
        fragment = new CommunityFragment();
        break;
    case 4:
        fragment = new PagesFragment();
        break;
    case 5:
        fragment = new SplashFragment();
        break;
    default:
        break;
    }

    if (fragment != null) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction()
                .replace(R.id.frame_container, fragment).commit();

        // update selected item and title, then close the drawer
        mDrawerList.setItemChecked(position, true);
        mDrawerList.setSelection(position);
        setTitle(navMenuTitles[position]);
        mDrawerLayout.closeDrawer(mDrawerList);
    } else {
        // error in creating fragment
        Log.e("MainActivity", "Error in creating fragment");
    }
}

オプションが選択されるたびに、フラグメントの「新しい」インスタンスが実際に存在することに気づきました。 Fragmentインスタンスを作成するロジックを実装して[〜#〜] once [〜#〜]で再利用する方法を教えてください。そうすれば、Fragmentを何度も繰り返しロードする必要がなくなります。 。

14
Arvind Dinivra

私と同じ問題に遭遇した人には、私はなんとか解決策を見つけることができました。

コンテナフレームでは、以下に示すように、使用する特定のフラグメントビューを定義する必要があります。

Specific fragments

各フラグメントビューで、以下に示すように、"Android:name"属性を介して実際のフラグメント自体に「リンク」する必要があります。パスに注意してください。 =フラグメントに、私の場合の例はcom.example.confesssionsrp.SelectionFragmentです。

<fragment
    Android:id="@+id/selectionFragment"
    Android:name="com.example.confessionsrp.SelectionFragment"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent" />

MainActivity(またはフラグメントを表示しているアクティビティ)で、以下に示すように各フラグメントの変数を作成します。

Variables

その後、MainActivity(または特定のアクティビティ)のOncreateで、以下に示すようにさまざまなフラグメントを初期化します。

OnCreate

以下に示すように、「ShowFragment "」という新しいメソッドの作成に進みます。

private void showFragment(int fragmentIndex, boolean addToBackStack) {
    FragmentManager fm = getSupportFragmentManager();
    FragmentTransaction transaction = fm.beginTransaction();
    for (int i = 0; i < fragments.length; i++) {
        if (i == fragmentIndex) {
            transaction.show(fragments[i]);
            if (Session.getActiveSession().isClosed()) {
                mDrawerLayout
                        .setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
            }
        } else {
            transaction.hide(fragments[i]);
        }
    }
    if (addToBackStack) {
        transaction.addToBackStack(null);
    }
    transaction.commit();
}

それ以降、フラグメントの切り替えで、以下に示すように、選択したフラグメントを使用して "ShowFragment"メソッドを手動で呼び出します。

Show Fragment

このすべてを全体的に行うと、フラグメントを表示するたびにリセットされることはないため、答えの解決策になります。これまで私を助けてくれた人に感謝します:)!

17
Arvind Dinivra

誰かがこれに対する別のアプローチを望んでいる場合:スタック上でフラグメントを見つけることができます:

// check if this fragment is on the backstack to avoid creating a new one
    Fragment foundFragment =  fragmentManager.findFragmentByTag("unique_fragment_tag");
    if (foundFragment != null) {
          fragmentManager.popBackStackImmediate("unique_fragment_tag", 0);
            return;
    }
0
aarcoraci

2番目のオプションは、Android SDKが提供するnavigationDrawerの例から始めることです。プロジェクトの作成時にアクティビティのテンプレートを選択すると、以前の回答のほとんどすべてのコードが自動的に生成されます。

デバイスのローテーションなどの後でフラグメントを保持する場合は別のことですが、フラグメントを保持する必要があります。そうでない場合は、フラグメントの新しいインスタンスを変数に保存し、それがnullかどうかを確認して、新しいインスタンスを作成するか、古いインスタンスを使用する必要があります。

0
XaviGG

私は次のコードを使用しています:

@Override
public void onNavigationDrawerItemSelected(int position) {

    // update the main content by replacing fragments
    FragmentManager fragmentManager = getFragmentManager();
    if(position==0){// selection of tabs content
        fragmentManager
        .beginTransaction()
        .replace(R.id.container,
                SimulatorFragment.newInstance(position + 1)).commit();
    }else if(position==1){
        fragmentManager
        .beginTransaction()
        .replace(R.id.container,
                HudFragment.newInstance(position + 1)).commit();
    }else if(position==2){
        // Display the fragment as the main content.
        fragmentManager
        .beginTransaction()
        .replace(R.id.container, 
                SettingsBasicFragment.newInstance(position +1)).commit();
    }else{

    }
}

初めて新しいインスタンスに置き換えてフラグメントを保存できます。nullでない場合は、保存されているフラグメントに置き換えます。

アクティビティはNavigationDrawerFragment.NavigationDrawerCallbacksを実装する必要があります

フラグメントコンストラクターとnewInstanceメソッドは次のようになります。

public final class HudFragment extends Fragment {
/**
 * The fragment argument representing the section number for this
 * fragment.
 */
private static final String ARG_SECTION_NUMBER = "section_number";

/**
 * Returns a new instance of this fragment for the given section number.
 * @param simulation 
 */
public static HudFragment newInstance(int sectionNumber) {  
    HudFragment fragment = new HudFragment();
    Bundle args = new Bundle();
    args.putInt(ARG_SECTION_NUMBER, sectionNumber);
    fragment.setArguments(args);
    return fragment;
}

public HudFragment() {
}

コードでフラグメントを切り替えるには、NavigationDrawerFragment内で次のメソッドを使用します。

/**
 * Select a different section
 * @param position
 */
public void select(int position){
    selectItem(position);
}

private void selectItem(int position) {
    mCurrentSelectedPosition = position;
    if (mDrawerListView != null) {
        mDrawerListView.setItemChecked(position, true);
    }            
    if (mDrawerLayout != null) {
        mDrawerLayout.closeDrawer(mFragmentContainerView);
    }
    if (mCallbacks != null) {
        mCallbacks.onNavigationDrawerItemSelected(position);
    }
}
0
XaviGG