177

Android 開発者は、Navigation Drawer を使用する場合、ActionBar では「Navigation Drawer で表される画面のみが実際に Navigation Drawer 画像を持つべきである」こと、および「他のすべての画面には従来のアップカラットがある」ことを推奨しています。

詳細はこちら:http: //youtu.be/F5COhlbpIbY

1 つのアクティビティを使用して複数のレベルのフラグメントを制御しており、Navigation Drawer の画像をすべてのレベルで表示および機能させることができます。

下位レベルのフラグメントを作成するときに、 を呼び出してActionBarDrawerToggle setDrawerIndicatorEnabled(false)ナビゲーション ドロワーの画像を非表示にし、アップ キャレットを表示することができます。

LowerLevelFragment lowFrag = new LowerLevelFragment();

//disable the toggle menu and show up carat
theDrawerToggle.setDrawerIndicatorEnabled(false);
getSupportFragmentManager().beginTransaction().replace(R.id.frag_layout, 
lowFrag, "lowerFrag").addToBackStack(null).commit();

私が抱えている問題は、元のナビゲーション ドロワー イメージの代わりにアップ カラットがまだ表示されているトップ レベルのフラグメントに戻るときです。トップ レベルのフラグメントの ActionBar を「更新」して、Navigation Drawer の画像を再表示する方法について何か提案はありますか?


解決

トムの提案はうまくいきました。これが私がしたことです:

主な活動

このアクティビティは、アプリ内のすべてのフラグメントを制御します。

他のフラグメントを置き換える新しいフラグメントを準備するときは、DrawerToggleを次のsetDrawerIndicatorEnabled(false)ように設定します。

LowerLevelFragment lowFrag = new LowerLevelFragment();

//disable the toggle menu and show up carat
theDrawerToggle.setDrawerIndicatorEnabled(false);
getSupportFragmentManager().beginTransaction().replace(R.id.frag_layout,   
lowFrag).addToBackStack(null).commit();

次に、 のオーバーライドでonBackPressed、DrawerToggle を次のsetDrawerIndicatorEnabled(true)ように設定して上記を元に戻しました。

@Override
public void onBackPressed() {
    super.onBackPressed();
    // turn on the Navigation Drawer image; 
    // this is called in the LowerLevelFragments
    setDrawerIndicatorEnabled(true)
}

LowerLevelFragments で

onCreate私が変更したフラグメントでは、次のonOptionsItemSelectedようになります。

オプション メニューの構成を有効にするために追加onCreateされました。setHasOptionsMenu(true)また、アクションバーで<setDisplayHomeAsUpEnabled(true)を有効にするように設定します。

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // needed to indicate that the fragment would 
    // like to add items to the Options Menu        
    setHasOptionsMenu(true);    
    // update the actionbar to show the up carat/affordance 
    getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
}

<が押されるたびにアクティビティから が呼び出されonOptionsItemSelected、階層内で 1 レベル上に移動し、Navigation Drawer Image が表示されます。onBackPressed()

@Override
public boolean onOptionsItemSelected(MenuItem item) {   
    // Get item selected and deal with it
    switch (item.getItemId()) {
        case android.R.id.home:
            //called when the up affordance/carat in actionbar is pressed
            getActivity().onBackPressed();
            return true;
        … 
    }
4

12 に答える 12

83

1-2-3と簡単です。

達成したい場合:

1)ドロワー インジケータ- バック スタックにフラグメントがない場合、またはドロワーが開いている場合

2)矢印- 一部のフラグメントがバック スタックにある場合

private FragmentManager.OnBackStackChangedListener
        mOnBackStackChangedListener = new FragmentManager.OnBackStackChangedListener() {
    @Override
    public void onBackStackChanged() {
        syncActionBarArrowState();
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    getSupportActionBar().setDisplayShowHomeEnabled(true);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    mDrawerToggle = new ActionBarDrawerToggle(
            this,             
            mDrawerLayout,  
            R.drawable.ic_navigation_drawer, 
            0, 
            0  
    ) {

        public void onDrawerClosed(View view) {
            syncActionBarArrowState();
        }

        public void onDrawerOpened(View drawerView) {
            mDrawerToggle.setDrawerIndicatorEnabled(true);
        }
    };

    mDrawerLayout.setDrawerListener(mDrawerToggle);
    getSupportFragmentManager().addOnBackStackChangedListener(mOnBackStackChangedListener);
}

@Override
protected void onDestroy() {
    getSupportFragmentManager().removeOnBackStackChangedListener(mOnBackStackChangedListener);
    super.onDestroy();
}

private void syncActionBarArrowState() {
    int backStackEntryCount = 
        getSupportFragmentManager().getBackStackEntryCount();
    mDrawerToggle.setDrawerIndicatorEnabled(backStackEntryCount == 0);
}

3) 形状に応じて動作する両方のインジケータ

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (mDrawerToggle.isDrawerIndicatorEnabled() && 
        mDrawerToggle.onOptionsItemSelected(item)) {
        return true;
    } else if (item.getItemId() == android.R.id.home && 
               getSupportFragmentManager().popBackStackImmediate()) {
        return true;
    } else {
        return super.onOptionsItemSelected(item);
    }
}

PS 3 行インジケーターの動作に関するその他のヒントについては、Creating a Navigation Drawer on Android Developersを参照してください。

于 2013-11-13T12:39:18.907 に答える
30

下位レベルのフラグメントを実装するには、新しいアクティビティで下位レベルのフラグメントを実装するのではなく、既存のフラグメントを置き換えると書いています。

バック機能を手動で実装する必要があると思います。ユーザーがバックを押したときに、スタックをポップするコードがあります (Activity::onBackPressedオーバーライドなど)。そのため、どこでそれを行っても、逆にすることができますsetDrawerIndicatorEnabled

于 2013-06-29T00:39:26.873 に答える
12

アップ アクション バー ボタンが機能しない場合は、リスナーを追加することを忘れないでください。

// Navigation back icon listener
mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            onBackPressed();
        }
});

ホームボタンを使用してドロワーナビゲーションを実装する際に問題が発生しました.アクションボタンを除いてすべてが機能しました.

于 2016-01-14T21:52:31.633 に答える
10

DrawerToggle の状態に応じて、MainActivity でホーム項目の選択を処理してみてください。この方法では、すべてのフラグメントに同じコードを追加する必要はありません。

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Only handle with DrawerToggle if the drawer indicator is enabled.
    if (mDrawerToggle.isDrawerIndicatorEnabled() &&
            mDrawerToggle.onOptionsItemSelected(item)) {
        return true;
    }
    // Handle action buttons
    switch (item.getItemId()) {
        // Handle home button in non-drawer mode
        case android.R.id.home:
            onBackPressed();
            return true;

        default:
            return super.onOptionsItemSelected(item);
    }
}
于 2013-08-02T02:33:37.577 に答える
2

ハンバーガー メニューのビュー ステートを更新するホスティング アクティビティ用のインターフェイスを作成しました。最上位のフラグメントについては、トグルを に設定しtrue、上向きの < 矢印を表示するフラグメントについては、トグルを に設定しますfalse

public class SomeFragment extends Fragment {

    public interface OnFragmentInteractionListener {
        public void showDrawerToggle(boolean showDrawerToggle);
    }

    private OnFragmentInteractionListener mListener;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            this.mListener = (OnFragmentInteractionListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        mListener.showDrawerToggle(false);
    }
}

次に、私のアクティビティで...

public class MainActivity extends Activity implements SomeFragment.OnFragmentInteractionListener {

    private ActionBarDrawerToggle mDrawerToggle;

    public void showDrawerToggle(boolean showDrawerIndicator) {
        mDrawerToggle.setDrawerIndicatorEnabled(showDrawerIndicator);
    }

}
于 2014-09-05T01:20:42.480 に答える
1

この小さな例を見ることができます! https://github.com/oskarko/NavDrawerExample

于 2016-09-26T15:56:21.333 に答える
1

ロジックは明確です。フラグメント バック スタックがクリアされている場合は、[戻る] ボタンを表示します。フラグメント スタックが明確でない場合は、材料のハンバーガー バック アニメーションを表示します。

getSupportFragmentManager().addOnBackStackChangedListener(
    new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            syncActionBarArrowState();
        }
    }
);


private void syncActionBarArrowState() {
    int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount();
    mNavigationDrawerFragment.setDrawerIndicatorEnabled(backStackEntryCount == 0);
}

//add these in Your NavigationDrawer fragment class

public void setDrawerIndicatorEnabled(boolean flag){
    ActionBar actionBar = getActionBar();
    if (!flag) {
        mDrawerToggle.setDrawerIndicatorEnabled(false);
        actionBar.setDisplayHomeAsUpEnabled(true);
        mDrawerToggle.setHomeAsUpIndicator(getColoredArrow());
    } else {
        mDrawerToggle.setDrawerIndicatorEnabled(true);
    }
    mDrawerToggle.syncState();
    getActivity().supportInvalidateOptionsMenu();
}

//download back button from this(https://www.google.com/design/icons/) website and add to your project

private Drawable getColoredArrow() {
    Drawable arrowDrawable = ContextCompat.getDrawable(getActivity(), R.drawable.ic_arrow_back_black_24dp);
    Drawable wrapped = DrawableCompat.wrap(arrowDrawable);

    if (arrowDrawable != null && wrapped != null) {
        // This should avoid tinting all the arrows
        arrowDrawable.mutate();
        DrawableCompat.setTint(wrapped, Color.GRAY);
    }
    return wrapped;
}
于 2015-09-07T12:58:25.277 に答える
1

GMAIL アプリを見て、ここに来てキャレット/アフォーダンス アイコンを検索すると..

これを行うようお願いしますが、上記の回答はどれも明確ではありませんでした。受け入れられた回答を変更できました。

  • NavigationDrawer --> Listview にはサブフラグメントが含まれています。


  • サブフラグメントは次のようにリストされます

  • firstFragment == 位置 0 ---> これにはサブフラグメントがあります --> フラグメント

  • 2 番目のフラグメント
  • thirdFragment など....

firstFragment には、他のフラグメントがあります。

DrawerActivity でこれを呼び出します

getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            if (getFragmentManager().getBackStackEntryCount() > 0) {
                mDrawerToggle.setDrawerIndicatorEnabled(false);
            } else {
                mDrawerToggle.setDrawerIndicatorEnabled(true);
            }
        }
    });

そして断片的に

    setHasOptionsMenu(true);    

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Get item selected and deal with it
    switch (item.getItemId()) {
        case android.R.id.home:
            //called when the up affordance/carat in actionbar is pressed
            activity.onBackPressed();
            return true;
    }
    return false;
}

OnBackPressed Drawer アクティビティ メソッドで、ドロワー トグルを true に設定して、ナビゲーション リスト アイコンを再び有効にします。

ありがとう、プスプ

于 2015-10-07T12:17:15.297 に答える
0

IMO、riwnodenyk または Tom のソリューションで onNavigateUp() (ここに示すように) を使用すると、よりクリーンで、よりうまく機能するようです。onOptionsItemSelected コードを次のコードに置き換えるだけです。

@Override
public boolean onSupportNavigateUp() {
    if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
        // handle up navigation
        return true;
    } else {
        return super.onSupportNavigateUp();
    }
}
于 2014-09-15T12:41:13.380 に答える