Добавить кнопку «Назад» на панель инструментов для всех фрагментов, кроме домашнего фрагмента, который открывает панель навигации.

Когда мое приложение открыто, сначала отображается главный экран. На главном экране у меня есть NavigationDrawer, который открывается после нажатия HamburgerIcon. Позже я перехожу к другим фрагментам. перейти к предыдущему фрагменту. Но он каждый раз показывает значок гамбургера. Как это сделать?
Это код для установки Toolbar в XML

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/drawerLayout"
    tools:context="biz.fyra.myApp.ActivityTwo">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#ccc"
            android:minHeight="?attr/actionBarSize">
            <ImageView
                android:id="@+id/tooImage"
                android:src="@drawable/latest"
                android:layout_width="match_parent"
                android:layout_gravity="center_horizontal"
                android:layout_height="40dp" />
        </android.support.v7.widget.Toolbar>
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/frame">
        </FrameLayout>
    </LinearLayout>
    <android.support.design.widget.NavigationView
        android:layout_width="300dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/nav_header"
        android:id="@+id/navigationView"
        app:menu="@menu/actionmenu"
        android:background="@android:color/white">
    </android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>  

Как этого добиться?


person Satyam Gondhale    schedule 29.03.2018    source источник
comment
stackoverflow.com/questions/21093287/   -  person Ankita    schedule 29.03.2018
comment
Возможно дублирование stackoverflow .com/questions/36579799/   -  person Amjad Khan    schedule 29.03.2018


Ответы (2)


Если я правильно понимаю, вы используете одно действие с заменой фрагментов. Итак, глядя на что, у вас будет что-то вроде этого:

Важно. Тема Activity должна расширять Theme.AppCompat.Light.NoActionBar.


Активность:

public class MainActivity extends AppCompatActivity
    implements NavigationView.OnNavigationItemSelectedListener {
private DrawerLayout drawer;
private Toolbar toolbar;
private ActionBarDrawerToggle toggle;

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

    drawer = findViewById(R.id.drawer);
    toolbar = findViewById(R.id.toolbar);

    setSupportActionBar(toolbar);
    toggle = new ActionBarDrawerToggle(
            this,
            drawer,
            toolbar,
            R.string.navigation_drawer_open,
            R.string.navigation_drawer_close
    );
    drawer.addDrawerListener(toggle);
    toggle.syncState();

    NavigationView navigationView = findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);

    // First creation
    if (savedInstanceState == null)
        showFragment(StartFragment.newInstance());
}
/**
* Using in Base Fragment
*/
protected ActionBarDrawerToggle getToggle() {
    return toggle;
}

@Override
public void onBackPressed() {
    Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.frame);

    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else if (fragment instanceof OnBackPressedListener) {
        ((OnBackPressedListener) fragment).onBackPressed();
    } else {
        super.onBackPressed();
    }
}

@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
    drawer.closeDrawer(GravityCompat.START);
    switch (item.getItemId()) {
        case R.id.start: {
            showFragment(StartFragment.newInstance());
            break;
        }
        case R.id.orders: {
            showFragment(OrdersFragment.newInstance());
            break;
        }
        case R.id.category: {
            showFragment(CategoryFragment.newInstance());
            break;
        }
        case R.id.calendar: {
            showFragment(CalendarFragment.newInstance());
            break;
        }
        case R.id.settings: {
            showFragment(SettingsFragment.newInstance());
            break;
        }
        case R.id.about: {
            showFragment(AboutFragment.newInstance());
            break;
        }
    return true;
}

private void showFragment(Fragment fragment) {
    getSupportFragmentManager().beginTransaction().replace(R.id.frame, fragment).commit();
}
}

Интерфейс для отправки событий обратной печати из активности во фрагменты:

public interface OnBackPressedListener {
    void onBackPressed();
}

И абстрактный базовый фрагмент, который вы должны расширить и реализовать методы:

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;

import ...
/**
 * Abstract fragment with FAB button, Toolbar and 2 interfaces: 
OnClick, OnBackPress
 *
 */
public abstract class BaseFragment extends Fragment implements 
View.OnClickListener, OnBackPressedListener {

protected FloatingActionButton fab;
protected Toolbar toolbar;
protected ActionBar actionBar;
protected ActionBarDrawerToggle toggle;
protected DrawerLayout drawer;
protected boolean mToolBarNavigationListenerIsRegistered = false;

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    fab = ((MainActivity)getActivity()).findViewById(R.id.fab);
    toolbar = ((MainActivity) getActivity()).findViewById(R.id.toolbar);
    actionBar = ((MainActivity) getActivity()).getSupportActionBar();
    drawer = ((MainActivity) getActivity()).findViewById(R.id.drawer_layout);
    toggle = ((MainActivity) getActivity()).getToggle();
    fab.setOnClickListener(this);
}

/**
* Simplify fragment replacing in child fragments
*/
protected void replaceFragment(@NonNull Fragment fragment) {
    FragmentManager fm = getActivity().getSupportFragmentManager();
    fm.beginTransaction().replace(R.id.container, fragment).commit();
}

// hide FAB button
protected void hideFab() {
    fab.hide();
}

//show FAB button
protected void showFab() {
    fab.show();
}

/**
 * Shows Home button as Back button
 * Took from here {@link}https://stackoverflow.com/a/36677279/9381524
 * <p>
 * To keep states of ActionBar and ActionBarDrawerToggle synchronized,
 * when you enable on one, you disable on the other.
 * And as you may notice, the order for this operation is disable first, then enable - VERY VERY IMPORTANT!!!
 *
 * @param show = true to show <showHomeAsUp> or show = false to show <Hamburger> button
 */
protected void showBackButton(boolean show) {

    if (show) {
        // Remove hamburger
        toggle.setDrawerIndicatorEnabled(false);
        // Show back button
        actionBar.setDisplayHomeAsUpEnabled(true);
        // when DrawerToggle is disabled i.e. setDrawerIndicatorEnabled(false), navigation icon
        // clicks are disabled i.e. the UP button will not work.
        // We need to add a listener, as in below, so DrawerToggle will forward
        // click events to this listener.
        if (!mToolBarNavigationListenerIsRegistered) {
            toggle.setToolbarNavigationClickListener(v -> onBackPressed());
            mToolBarNavigationListenerIsRegistered = true;
        }

    } else {
        // Remove back button
        actionBar.setDisplayHomeAsUpEnabled(false);
        // Show hamburger
        toggle.setDrawerIndicatorEnabled(true);
        // Remove the/any drawer toggle listener
        toggle.setToolbarNavigationClickListener(null);
        mToolBarNavigationListenerIsRegistered = false;
    }
    // So, one may think "Hmm why not simplify to:
    // .....
    // getSupportActionBar().setDisplayHomeAsUpEnabled(enable);
    // mDrawer.setDrawerIndicatorEnabled(!enable);
    // ......
    // To re-iterate, the order in which you enable and disable views IS important #dontSimplify.
}

/**
* Simplify setTitle in child fragments
*/
protected void setTitle(int resId) {
    getActivity().setTitle(getResources().getString(resId));
}

//
@Override
public abstract void onClick(View v);

// Handles BackPress events from MainActivity
@Override
public abstract void onBackPressed();
}

Все фрагменты с кнопкой «Назад», используемые в MainActivity, должны расширяться из этого BaseFragment.

person Jurij Pitulja    schedule 29.03.2018

Вы можете попробовать что-то вроде

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {   super.onCreate(savedInstanceState);
[...]
        if (getSupportActionBar() != null)
        {   getSupportActionBar().setDisplayHomeAsUpEnabled(true);
            getSupportActionBar().setHomeButtonEnabled(true);
        }
[...]
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {   if (getSupportFragmentManager().getBackStackEntryCount() > 0)
        {   switch (item.getItemId())
            {   case android.R.id.home:
                    onBackPressed();
                    return true;
            }
        }

[...]
    }
person Jerome    schedule 29.03.2018