将后退按钮添加到工具栏,用于打开导航抽屉的主页片段以外的所有片段
Add back button to Toolbar for all Fragments other than Home Fragment which opens Navigation Drawer
当我的应用程序打开时显示主屏幕 first.On 我的主屏幕 NavigationDrawer
在按下 HamburgerIcon
后打开。稍后我转到不同的 fragments.When 我我在除主页以外的其他片段中 Activity
我需要在 Toolbar
上显示后退按钮才能回到上一个 fragment.But 每次显示汉堡包 icon.How 来执行此操作?
这是在 XML
中设置 Toolbar
的代码
<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>
如何实现?
你可以试试
@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;
}
}
[...]
}
如果我没理解错的话,你使用的是 activity 片段替换。所以,看看 你会得到这样的东西:
重要:Activity 主题应扩展 Theme.AppCompat.Light.NoActionBar
Activity:
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();
}
}
从activity向片段发送backpress事件的接口:
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}
* <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 扩展。
当我的应用程序打开时显示主屏幕 first.On 我的主屏幕 NavigationDrawer
在按下 HamburgerIcon
后打开。稍后我转到不同的 fragments.When 我我在除主页以外的其他片段中 Activity
我需要在 Toolbar
上显示后退按钮才能回到上一个 fragment.But 每次显示汉堡包 icon.How 来执行此操作?
这是在 XML
Toolbar
的代码
<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>
如何实现?
你可以试试
@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;
}
}
[...]
}
如果我没理解错的话,你使用的是 activity 片段替换。所以,看看
重要:Activity 主题应扩展 Theme.AppCompat.Light.NoActionBar
Activity:
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();
}
}
从activity向片段发送backpress事件的接口:
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}
* <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 扩展。