使用DrawerLayout和AppCompatActivity实现后退导航而不使用DrawerToggle

时间:2015-08-19 12:10:05

标签: android android-fragments navigation-drawer drawerlayout appcompat-v7-r22.2

在使用导航抽屉时,我一直在搜索和思考如何在片段之间来回切换时实现我想要的行为。实际上文档说: 在应用中使用片段时,各个FragmentTransaction对象可能表示应添加到后台堆栈的上下文更改。例如,如果您通过交换片段在手机上实现主/详细信息流,则应确保按详细信息屏幕上的“返回”按钮将用户返回到主屏幕

所以在我的应用程序中,我有一个MainActivity控制一切,你可以在预定义选项之间切换导航布局。这是启动应用程序时的视图

enter image description here

当您单击导航抽屉中的某个项目时,它会打开一个替换main_content的新片段,如下所示:

enter image description here

此时行为是正确的,因此如果您想更改选项,则需要再次打开导航栏以在菜单选项之间切换。

这是主要活动(请注意,没有抽屉切换)

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适配器中,我在调用新片段(内部片段)之前添加了反向堆栈片段并且更改了后退按钮的行为,所以在此之前如果按下后退按钮关闭应用程序但是现在它需要你到Consejos片段,但是现在我想添加插入符号并进行与单击后退按钮完全相同的操作,但我不知道如何实现它。

请随时索取更多代码

非常感谢

1 个答案:

答案 0 :(得分:0)

我会给你完整的答案: 我们将使用这些接口与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);
                     }
                 }
            });

        }

    }
}

如果您有什么不明白的地方,请告诉我。