Приложете навигация назад с 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 използва и обработва щракването върху елемента вътре:

Adapter.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 Adapter добавих обратно подреждане на фрагмента, преди да извикам новия фрагмент (вътрешен фрагмент) и това променя поведението на бутона за връщане назад, така че преди това, ако натиснете бутона за връщане, затваря приложението, но сега ви отвежда до 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) и иконата на хамбургер изчезва и се замества от иконата за каретка нагоре, но винаги, когато щракнете, не прави нищо (дори менюто не не се появява) :S - person neteot; 08.09.2015
comment
Успях да направя поведението, което искам! (само трябва да промените от Recetas Fragment на RecetasViewFragment) единственото нещо е, че когато се върнете към изгледа на мрежата на recetas (перфектно), иконата на каретката нагоре изчезва и се появява отново иконата на менюто, нещото е, че не е има поведение, ако щракнете върху него, нищо не се случва... можете ли да ми помогнете? какво ми липсва - person neteot; 14.09.2015
comment
Какво искате да направите, когато щракнете върху иконата? - person Ibrahim Disouki; 14.09.2015
comment
Здравей @hema18 просто исках да покажа чекмеджето отново. но в метода else на enabledNavigationBack(boolean enable) в MainActivity направих това else { toolbar.setNavigationIcon(R.drawable.ic_menu); setToolbar(); } и сега работи добре. Много благодаря. - person neteot; 14.09.2015
comment
Здравейте, ще редактирам отговора си, просто променете метода enabledNavigationBack(boolean enable). - person Ibrahim Disouki; 14.09.2015
comment
Редактирах отговора си, моля, променяйте само enabledNavigationBack(булева активация) - 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