Реализовать обратную навигацию с помощью DrawerLayout и AppCompatActivity без DrawerToggle.

Я искал и думал, как реализовать поведение желания, которое я хочу, при переключении назад и вперед между фрагментами при использовании ящика навигации. На самом деле в документации сказано: При использовании фрагментов в вашем приложении отдельные объекты FragmentTransaction могут представлять изменения контекста, которые должны быть добавлены в задний стек. Например, если вы реализуете поток «главный/подробный» на телефоне путем замены фрагментов, вы должны убедиться, что нажатие кнопки «Назад» на подробном экране возвращает пользователя к основному экрану

Итак, в моем приложении у меня есть MainActivity, которая управляет всем, и макет навигации внутри, который вы можете менять между предопределенными параметрами. Это вид при запуске приложения

введите здесь описание изображения

Когда вы щелкаете элемент в навигационном ящике, он открывает новый фрагмент, который заменяет main_content следующим образом:

введите здесь описание изображения

На этом этапе поведение является правильным, поэтому, если вы хотите изменить параметры, вам нужно снова открыть панель навигации, чтобы переключаться между параметрами меню.

Это основное действие (обратите внимание, что нет переключателя ящиков)

MainActivity.java

public class MainActivity extends AppCompatActivity {

ActionBarDrawerToggle mDrawerToggle;
private DrawerLayout drawerLayout;

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

        mSnackBarView = findViewById(R.id.myCoordinatorLayout);

        setToolbar(); // Set Toolbar como action bar


        if (savedInstanceState != null) {
            mCurrentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION);
            mFromSavedInstanceState = true;
        }
        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        if (navigationView != null) {
            setupDrawerContent(navigationView);
        }

        drawerTitle = getResources().getString(R.string.app_name);
        if (savedInstanceState == null) {
            selectItem(drawerTitle, mCurrentSelectedPosition);
        }

    }

    private void setToolbar() {
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        final ActionBar ab = getSupportActionBar();
        if (ab != null) {
            // Poner ícono del drawer toggle
            ab.setHomeAsUpIndicator(R.drawable.ic_menu);
            ab.setDisplayHomeAsUpEnabled(true);

        }
    }

    private void setupDrawerContent(final NavigationView navigationView) {
        navigationView.setNavigationItemSelectedListener(
                new NavigationView.OnNavigationItemSelectedListener() {
                    @Override
                    public boolean onNavigationItemSelected(MenuItem menuItem) {
                        // Marcar item presionado
                        menuItem.setChecked(true);
                        // Crear nuevo fragmento
                        String title = menuItem.getTitle().toString();
                        int id = menuItem.getItemId();
                        selectItem(title, id);
                        return true;
                    }
                }
        );
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        if (!drawerLayout.isDrawerOpen(GravityCompat.START)) {
            getMenuInflater().inflate(R.menu.menu_main, menu);
            return true;
        }
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                drawerLayout.openDrawer(GravityCompat.START);
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    private void selectItem(String title, int id) {
        Bundle args = new Bundle();
        args.putString(PlaceholderFragment.ARG_SECTION_TITLE, title);

        Fragment fragment = PlaceholderFragment.newInstance(title);
        fragment.setArguments(args);
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager
                .beginTransaction()
                .replace(R.id.main_content, fragment)
                .commit();


        switch (id) {
            case R.id.nav_localizacion:
                //Snackbar.make(mSnackBarView, R.string.menu_localization, Snackbar.LENGTH_SHORT).show();
                mCurrentSelectedPosition = 0;
                LocalizacionFragment fragment_localizacion = new LocalizacionFragment();
//                fragmentManager = getSupportFragmentManager();
                Snackbar.make(mSnackBarView, R.string.menu_localization, Snackbar.LENGTH_SHORT).show();
                fragmentManager
                        .beginTransaction()
                        .replace(R.id.main_content, fragment_localizacion)
                        .commit();
                break;
            case R.id.nav_productos:
                Snackbar.make(mSnackBarView, R.string.menu_productos, Snackbar.LENGTH_SHORT).show();
                mCurrentSelectedPosition = 1;
                fragmentManager
                        .beginTransaction()
                        .replace(R.id.main_content, fragment)
                        .commit();
                break;
            case R.id.nav_consejos:
                Snackbar.make(mSnackBarView, R.string.menu_consejos, Snackbar.LENGTH_SHORT).show();
                mCurrentSelectedPosition = 3;
                ConsejosFragment fragment_consejo = new ConsejosFragment();
                fragmentManager
                        .beginTransaction()
                        .replace(R.id.main_content, fragment_consejo)
                        .commit();
                break;
            default:
                break;
        }


        drawerLayout.closeDrawers(); // Cerrar drawer

        setTitle(title); // título actual

    }

}

Я не использую значок гамбургера, потому что он скрывается под макетом навигации, но вот в чем дело. Когда вы нажимаете «Recetas» в представлении корзины, он открывает новый фрагмент (заменяет), но теперь я хочу отобразить значок курсора вверх и дать правильную обратную навигацию моему приложению.

Вот код класса фрагмента "Consejos"

Consejos.java

public class ConsejosFragment extends Fragment {

    RecyclerView mRecycler;
    ConsejosAdapter mAdapter;
    FragmentActivity mActivity;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        this.mActivity = (FragmentActivity) activity;
        setRetainInstance(true);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setHasOptionsMenu(true);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        List items = new ArrayList();
        items.add(new ConsejosInfo("Recetas", R.drawable.icon_recetas));


        /* Inflamos el layout */
        View v = inflater.inflate(R.layout.consejos_layout_recycler, container, false);
        /* Obtenemos el Recycle */
        mRecycler = (RecyclerView) v.findViewById(R.id.recycler_consejos);

        /* Creamos el adaptador */
        mAdapter = new ConsejosAdapter(mActivity, items);

        /* Set click en adapter */


        return v;
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mRecycler.setHasFixedSize(true);

        mRecycler.setLayoutManager(new LinearLayoutManager(getActivity()));

        mRecycler.setAdapter(mAdapter);
    }
}

И это адаптер, который использует Recyclerview и обрабатывает щелчок по элементу внутри:

Адаптер.java

public class ConsejosAdapter extends RecyclerView.Adapter<ConsejosAdapter.ConsejosViewHolder> {

    private List<ConsejosInfo> _items = new ArrayList<ConsejosInfo>();
    private final FragmentActivity mActivity;
    private Context context;

    public ConsejosAdapter(FragmentActivity mActivity, List<ConsejosInfo> items) {
        this._items = items;
        this.mActivity = mActivity;
    }

    @Override
    public int getItemCount() {
        return _items.size();
    }

    @Override
    public ConsejosViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.cardview_consejos, viewGroup, false);
        return new ConsejosViewHolder(v);
    }

    @Override
    public void onBindViewHolder(ConsejosViewHolder viewHolder, int position) {
        viewHolder.imagen.setImageResource(_items.get(position).get_imagen());
        viewHolder.nombre.setText(_items.get(position).get_nombre());
    }

    public class ConsejosViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        public ImageView imagen;
        public TextView nombre;

        public ConsejosViewHolder(final View itemView) {
            super(itemView);
            imagen = (ImageView) itemView.findViewById(R.id.consejos_imagen);
            nombre = (TextView) itemView.findViewById(R.id.consejos_nombre);
            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            RecetasFragment recetasFragment = new RecetasFragment();
            FragmentManager fragmentManager = mActivity.getSupportFragmentManager();
            fragmentManager
                    .beginTransaction()
                    .replace(R.id.main_content, recetasFragment)
                    .addToBackStack(null)
                    .commit();

        }
    }
}

В адаптере Consejos я добавил фрагмент обратного стека перед вызовом нового фрагмента (внутри фрагмента), и это меняет поведение кнопки «Назад», поэтому до этого, если вы нажмете кнопку «Назад», приложение закроется, но теперь оно приведет вас к Consejos фрагмент, но теперь я хочу добавить каретку вверх и выполнить точно такую ​​же операцию, как при нажатии кнопки «Назад», но я не знаю, как этого добиться.

Пожалуйста, не стесняйтесь запрашивать больше кода

Большое спасибо


person neteot    schedule 19.08.2015    source источник


Ответы (1)


Я дам вам полный ответ: мы будем использовать интерфейсы для связи с MainActivity из RecetasFragment, чтобы мы могли включать и отключать кнопку навигации назад.
RecetasFragment класс:

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by hema on 8/19/2015.
 */
public class RecetasFragment extends Fragment {

    private CommunicateWithActivity mWithActivity;

    public RecetasFragment() {
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);


        try {

            mWithActivity = (CommunicateWithActivity) activity; // MainActivity must implement CommunicateWithActivity interface.

            mWithActivity.enableNavigationBack(true); // We enable navigation back here.

        } catch (ClassCastException e) {

            throw new ClassCastException(activity.toString()
                    + " must implement CommunicateWithActivity");

        }

    }

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

    @Override
    public void onDestroy() {
        super.onDestroy();

        mWithActivity.enableNavigationBack(false); // We disable navigation back here, restore menu icon.

    }

    public interface CommunicateWithActivity {

        void enableNavigationBack(boolean enable);// we will implement this method in MainActivity class.

    }

}

И в классе MainActivity мы реализуем интерфейс CommunicateWithActivity. Измените класс MainActivity (только необходимые изменения):

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;

public class MainActivity extends AppCompatActivity implements RecetasFragment.CommunicateWithActivity {

    private Toolbar mToolbar;
    private DrawerLayout drawerLayout;

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

        mToolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(mToolbar);

        mToolbar.setNavigationIcon(R.drawable.ic_menu);

        mSnackBarView = findViewById(R.id.myCoordinatorLayout);

        if (savedInstanceState != null) {
            mCurrentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION);
            mFromSavedInstanceState = true;
        }
        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        if (navigationView != null) {
            setupDrawerContent(navigationView);
        }

        drawerTitle = getResources().getString(R.string.app_name);
        if (savedInstanceState == null) {
            selectItem(drawerTitle, mCurrentSelectedPosition);
        }

    }

    private void setupDrawerContent(final NavigationView navigationView) {
        navigationView.setNavigationItemSelectedListener(
                new NavigationView.OnNavigationItemSelectedListener() {
                    @Override
                    public boolean onNavigationItemSelected(MenuItem menuItem) {
                        // Marcar item presionado
                        menuItem.setChecked(true);
                        // Crear nuevo fragmento
                        String title = menuItem.getTitle().toString();
                        int id = menuItem.getItemId();
                        selectItem(title, id);
                        return true;
                    }
                }
        );
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        if (!drawerLayout.isDrawerOpen(GravityCompat.START)) {
            getMenuInflater().inflate(R.menu.menu_main, menu);
            return true;
        }
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                drawerLayout.openDrawer(GravityCompat.START);
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    private void selectItem(String title, int id) {
        Bundle args = new Bundle();
        args.putString(PlaceholderFragment.ARG_SECTION_TITLE, title);

        Fragment fragment = PlaceholderFragment.newInstance(title);
        fragment.setArguments(args);
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager
                .beginTransaction()
                .replace(R.id.main_content, fragment)
                .commit();


        switch (id) {
            case R.id.nav_localizacion:
                //Snackbar.make(mSnackBarView, R.string.menu_localization, Snackbar.LENGTH_SHORT).show();
                mCurrentSelectedPosition = 0;
                LocalizacionFragment fragment_localizacion = new LocalizacionFragment();
//                fragmentManager = getSupportFragmentManager();
                Snackbar.make(mSnackBarView, R.string.menu_localization, Snackbar.LENGTH_SHORT).show();
                fragmentManager
                        .beginTransaction()
                        .replace(R.id.main_content, fragment_localizacion)
                        .commit();
                break;
            case R.id.nav_productos:
                Snackbar.make(mSnackBarView, R.string.menu_productos, Snackbar.LENGTH_SHORT).show();
                mCurrentSelectedPosition = 1;
                fragmentManager
                        .beginTransaction()
                        .replace(R.id.main_content, fragment)
                        .commit();
                break;
            case R.id.nav_consejos:
                Snackbar.make(mSnackBarView, R.string.menu_consejos, Snackbar.LENGTH_SHORT).show();
                mCurrentSelectedPosition = 3;
                ConsejosFragment fragment_consejo = new ConsejosFragment();
                fragmentManager
                        .beginTransaction()
                        .replace(R.id.main_content, fragment_consejo)
                        .commit();
                break;
            default:
                break;
        }


        drawerLayout.closeDrawers(); // Cerrar drawer

        setTitle(title); // título actual

    }

    @Override
    public void enableNavigationBack(boolean enable) {

        if(enable) {

            // We enable the navigation back button here

            mToolbar.setNavigationIcon(R.drawable.abc_ic_ab_back_mtrl_am_alpha);

            mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    // On navigation back button clicked.

                    if(getSupportFragmentManager().getBackStackEntryCount() > 0) { // Check if there is fragments in BackStack.

                        getSupportFragmentManager().popBackStack(); // PopBackStack.

                    } else {

                        // You can implement this part as you want.

                        return;

                    }

                }
            });

        } else {

            mToolbar.setNavigationIcon(R.drawable.ic_menu);

            mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
                 @Override
                 public void onClick(View v) {
                     if(drawerLayout != null) {
                         drawerLayout.openDrawer(Gravity.LEFT);
                     }
                 }
            });

        }

    }
}

Пожалуйста, дайте мне знать, если вы что-то не понимаете.

person Ibrahim Disouki    schedule 19.08.2015
comment
Привет @ hema18 Я пытаюсь реализовать предложенный вами ответ, но мне нужно реализовать интерфейс в MainActivity, но я точно не знаю, как это сделать, функция enableNavigationBack определена в классе MainActivity, поэтому она не может быть функцией интерфейса .. а еще я не знаю, зачем ты это делаешь if(savedInstanceState == null) { getSupportFragmentManager().beginTransaction().replace(R.id.container, new MainActivityFragment(), MainActivityFragment.class.getSimpleName()).commit(); } - person neteot; 24.08.2015
comment
привет, @hema18 Я все еще застрял на этом, не могли бы вы мне помочь? Огромное спасибо - person neteot; 26.08.2015
comment
Привет @ hema18, извини за поздний ответ (я занимаюсь коллажем). Я сделал то, что вы сказали, и когда вы нажимаете на recetas, он открывает вид сетки (во фрагменте recetas), а значок гамбургера исчезает и заменяется значком вставки вверх, но всякий раз, когда вы нажимаете, он ничего не делает (даже меню не не появляется) :С - person neteot; 08.09.2015
comment
Мне удалось сделать поведение, которое я хочу! (просто нужно перейти с Recetas Fragment на RecetasViewFragment) единственное, что когда вы возвращаетесь к сетке recetas (идеально), значок курсора вверх исчезает и снова появляется значок меню, дело в том, что это не есть поведение, если вы нажмете на него, ничего не произойдет... не могли бы вы мне помочь? что мне не хватает? - person neteot; 14.09.2015
comment
Что вы хотите делать, когда нажимаете на значок? - person Ibrahim Disouki; 14.09.2015
comment
Привет, @hema18 просто хотела снова показать ящик. но в другом методе enabledNavigationBack (логическое разрешение) в MainActivity я сделал это else { toolbar.setNavigationIcon(R.drawable.ic_menu); setToolbar(); }, и теперь он работает нормально. Большое спасибо. - person neteot; 14.09.2015
comment
Привет, я отредактирую свой ответ, просто измените метод enabledNavigationBack (логическое включение) - person Ibrahim Disouki; 14.09.2015
comment
Я отредактировал свой ответ, пожалуйста, измените только enableNavigationBack (логическое значение enable) - person Ibrahim Disouki; 14.09.2015
comment
Большое спасибо, что помогли мне, @hema18 еще одна вещь (извините за границы, но я понимаю, что у вас, возможно, нет времени), вы когда-нибудь реализовывали CollapsingToolbarLayout и AppBarLayout вместе с панелью инструментов? - person neteot; 14.09.2015
comment
Неважно, нет, но вы можете проверить этот пример github.com/chrisbanes/cheesesquare - person Ibrahim Disouki; 14.09.2015