导航抽屉 Android 最佳实践
Navigation Drawer Android best practice
我正在 android 中寻找有关导航模式的建议。在我正在使用的应用程序的当前状态下,我有一个导航抽屉,可以访问一些大部分动态更改的元素。当我从导航抽屉中单击一个项目时,我会显示一个片段。所以任何时候我想回到左边的菜单。现在,我必须以相同的方式从图片中移动 "New screen" activity 才能访问抽屉。到达 "New screen" activity 的唯一方法是从其中一个片段。
片段 0 有一个项目列表。单击它会打开 "New screen"。我应该如何处理这个 activity 中的抽屉?
我不想有太多的锅炉代码。
它在 android 4.2.2 上已经有问题,我现在只能想象这种修改将如何影响性能。
我需要了解什么是最佳解决方案,对此没有经验。我想要的只是想法,并且可能会获得一些关于此模式的专业知识,这样我就不会导致内存泄漏并且不会重复代码。
感谢您的宝贵时间。
1-我建议创建一个 Base Activity,它将进一步扩展您的 ActionBarActivity。
2-activity_sliding_drawer 此 activity 的布局文件将包含用于添加片段的 main_container 和 DrawerLayout:-
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/frame_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<FrameLayout
android:layout_gravity="bottom"
android:id="@+id/bottom_container"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_width="match_parent"
android:background="@color/white">
</FrameLayout>
</FrameLayout>
<fragment
android:id="@+id/slidingMenuFragment"
android:name="om.ooredoo.fragments.SlidingMenuFragment"
android:layout_width="@dimen/slidingmenu__parent_width"
android:layout_height="fill_parent"
android:layout_gravity="start" />
3- 然后在基础 activity 中,我们将拥有添加和替换片段的所有基本功能以及 2 个处理抽屉菜单图标可见性的功能,即 lockDrawerMenu()
和 unlockDrawerMenu()
.
4- 将以下代码放入您的基础 activity(在我的例子中是 AbstractActivity):-
public abstract class AbstractActivity extends ActionBarActivity {
public DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mDrawerToggle;
private boolean bSupportActionBar = true;
private boolean mSlidingMenuLocked = false;
private BackPressListener mBackPressListener;
private String title;
boolean ismSlidingMenuLocked() {
return mSlidingMenuLocked;
}
@Override
protected void onCreate(final Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
requestWindowFeature(Window.FEATURE_PROGRESS);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sliding_drawer);
if (bSupportActionBar) {
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerLayout.setScrimColor(getResources().getColor(android.R.color.transparent));
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
R.drawable.ic_navigation_drawer, //nav menu toggle icon
R.string.drawer_open, // nav drawer open - description for accessibility
R.string.drawer_close // nav drawer close - description for accessibility
) {
public void onDrawerClosed(View view) {
if (getSupportActionBar().getTitle().equals(getString(R.string.app_name)))
getSupportActionBar().setTitle(title);
invalidateOptionsMenu();
}
public void onDrawerOpened(View drawerView) {
title = (String) getSupportActionBar().getTitle();
getSupportActionBar().setTitle(getString(R.string.app_name));
// calling onPrepareOptionsMenu() to hide action bar icons
invalidateOptionsMenu();
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
unlockDrawerMenu();
}
}
@Override
protected void onStart() {
super.onStart();
setSupportProgressBarIndeterminateVisibility(false);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mHandler != null) {
mHandler.removeCallbacksAndMessages(null);
mHandler = null;
}
}
public void addNewFragmentWithBackStack(Fragment fragment) {
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.frame_container, fragment, fragment.getClass().getSimpleName())
.addToBackStack(fragment.getClass().getSimpleName())
.commit();
} else {
Log.e("AbstractActivity", "Error in creating fragment");
}
}
public void addNewFragmentWithBackStack(Fragment fragment, boolean animation) {
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.slide_up_anim, 0);
fragmentTransaction.replace(R.id.frame_container, fragment, fragment.getClass().getSimpleName())
.addToBackStack(fragment.getClass().getSimpleName())
.commit();
} else {
Log.e("AbstractActivity", "Error in creating fragment");
}
}
public void addNewBottomFragmentWithBackStack(Fragment fragment) {
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.slide_up_anim, 0);
fragmentTransaction.replace(R.id.bottom_container, fragment)
.addToBackStack(fragment.getClass().getSimpleName())
.commit();
} else {
Log.e("AbstractActivity", "Error in creating fragment");
}
}
public void replaceAndClearBackStack(Fragment fragment) {
//clear backStack
FragmentManager fm = getSupportFragmentManager();
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.frame_container, fragment)
.addToBackStack(fragment.getClass().getSimpleName());
transaction.commit();
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
if (bSupportActionBar)
mDrawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Pass any configuration change to the drawer toggles
if (bSupportActionBar)
mDrawerToggle.onConfigurationChanged(newConfig);
}
public void lockDrawerMenu() {
((DrawerLayout) findViewById(R.id.drawer_layout)).setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
if (bSupportActionBar) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mDrawerToggle.setDrawerIndicatorEnabled(false);
}
mSlidingMenuLocked = true;
}
public void unlockDrawerMenu() {
((DrawerLayout) findViewById(R.id.drawer_layout)).setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
mSlidingMenuLocked = false;
mDrawerToggle.setDrawerIndicatorEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// toggle nav drawer on selecting action bar app icon/title
if (!ismSlidingMenuLocked() && mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle action bar actions click
switch (item.getItemId()) {
case android.R.id.home:
if (ismSlidingMenuLocked()) {
onBackPressed();
return true;
}
return true;
default: {
return super.onOptionsItemSelected(item);
}
}
}
public BackPressListener getBackPressListener() {
return mBackPressListener;
}
public void setBackPressListener(BackPressListener mBackPressListener) {
this.mBackPressListener = mBackPressListener;
}
@Override
public void onBackPressed() {
if (getSupportFragmentManager().getFragments().size() > 0) {
for (Fragment frag : getSupportFragmentManager().getFragments()) {
if (frag != null && frag.isAdded() && frag instanceof AbstractParentFragment) {
if (frag.getChildFragmentManager().getBackStackEntryCount() > 0) {
frag.getChildFragmentManager().popBackStack();
return;
}
}
}
}
if (mBackPressListener != null) {
if (mBackPressListener.onBackPress())
return;
} else {
if (getSupportFragmentManager().getBackStackEntryCount() == 1) {
this.finish();
return;
}
super.onBackPressed();
}
}
void supportActionBar(boolean support) {
bSupportActionBar = support;
}}
5- 现在创建一个滑动抽屉 activity 来扩展您的基础 activity 并在该主要片段中启动您的主要片段 打开您在滑动抽屉中单击项目的其他片段基础知识。
现在你有两个函数来处理滑动抽屉,如果滑动抽屉图标可见,那么它在点击项目的基础上工作,否则它将是一个带有操作栏的普通片段。
希望这对您有所帮助。 !!!
我正在 android 中寻找有关导航模式的建议。在我正在使用的应用程序的当前状态下,我有一个导航抽屉,可以访问一些大部分动态更改的元素。当我从导航抽屉中单击一个项目时,我会显示一个片段。所以任何时候我想回到左边的菜单。现在,我必须以相同的方式从图片中移动 "New screen" activity 才能访问抽屉。到达 "New screen" activity 的唯一方法是从其中一个片段。
片段 0 有一个项目列表。单击它会打开 "New screen"。我应该如何处理这个 activity 中的抽屉? 我不想有太多的锅炉代码。 它在 android 4.2.2 上已经有问题,我现在只能想象这种修改将如何影响性能。 我需要了解什么是最佳解决方案,对此没有经验。我想要的只是想法,并且可能会获得一些关于此模式的专业知识,这样我就不会导致内存泄漏并且不会重复代码。
感谢您的宝贵时间。
1-我建议创建一个 Base Activity,它将进一步扩展您的 ActionBarActivity。
2-activity_sliding_drawer 此 activity 的布局文件将包含用于添加片段的 main_container 和 DrawerLayout:-
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/frame_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<FrameLayout
android:layout_gravity="bottom"
android:id="@+id/bottom_container"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_width="match_parent"
android:background="@color/white">
</FrameLayout>
</FrameLayout>
<fragment
android:id="@+id/slidingMenuFragment"
android:name="om.ooredoo.fragments.SlidingMenuFragment"
android:layout_width="@dimen/slidingmenu__parent_width"
android:layout_height="fill_parent"
android:layout_gravity="start" />
3- 然后在基础 activity 中,我们将拥有添加和替换片段的所有基本功能以及 2 个处理抽屉菜单图标可见性的功能,即 lockDrawerMenu()
和 unlockDrawerMenu()
.
4- 将以下代码放入您的基础 activity(在我的例子中是 AbstractActivity):-
public abstract class AbstractActivity extends ActionBarActivity {
public DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mDrawerToggle;
private boolean bSupportActionBar = true;
private boolean mSlidingMenuLocked = false;
private BackPressListener mBackPressListener;
private String title;
boolean ismSlidingMenuLocked() {
return mSlidingMenuLocked;
}
@Override
protected void onCreate(final Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
requestWindowFeature(Window.FEATURE_PROGRESS);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sliding_drawer);
if (bSupportActionBar) {
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerLayout.setScrimColor(getResources().getColor(android.R.color.transparent));
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
R.drawable.ic_navigation_drawer, //nav menu toggle icon
R.string.drawer_open, // nav drawer open - description for accessibility
R.string.drawer_close // nav drawer close - description for accessibility
) {
public void onDrawerClosed(View view) {
if (getSupportActionBar().getTitle().equals(getString(R.string.app_name)))
getSupportActionBar().setTitle(title);
invalidateOptionsMenu();
}
public void onDrawerOpened(View drawerView) {
title = (String) getSupportActionBar().getTitle();
getSupportActionBar().setTitle(getString(R.string.app_name));
// calling onPrepareOptionsMenu() to hide action bar icons
invalidateOptionsMenu();
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
unlockDrawerMenu();
}
}
@Override
protected void onStart() {
super.onStart();
setSupportProgressBarIndeterminateVisibility(false);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mHandler != null) {
mHandler.removeCallbacksAndMessages(null);
mHandler = null;
}
}
public void addNewFragmentWithBackStack(Fragment fragment) {
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.frame_container, fragment, fragment.getClass().getSimpleName())
.addToBackStack(fragment.getClass().getSimpleName())
.commit();
} else {
Log.e("AbstractActivity", "Error in creating fragment");
}
}
public void addNewFragmentWithBackStack(Fragment fragment, boolean animation) {
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.slide_up_anim, 0);
fragmentTransaction.replace(R.id.frame_container, fragment, fragment.getClass().getSimpleName())
.addToBackStack(fragment.getClass().getSimpleName())
.commit();
} else {
Log.e("AbstractActivity", "Error in creating fragment");
}
}
public void addNewBottomFragmentWithBackStack(Fragment fragment) {
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.slide_up_anim, 0);
fragmentTransaction.replace(R.id.bottom_container, fragment)
.addToBackStack(fragment.getClass().getSimpleName())
.commit();
} else {
Log.e("AbstractActivity", "Error in creating fragment");
}
}
public void replaceAndClearBackStack(Fragment fragment) {
//clear backStack
FragmentManager fm = getSupportFragmentManager();
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.frame_container, fragment)
.addToBackStack(fragment.getClass().getSimpleName());
transaction.commit();
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
if (bSupportActionBar)
mDrawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Pass any configuration change to the drawer toggles
if (bSupportActionBar)
mDrawerToggle.onConfigurationChanged(newConfig);
}
public void lockDrawerMenu() {
((DrawerLayout) findViewById(R.id.drawer_layout)).setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
if (bSupportActionBar) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mDrawerToggle.setDrawerIndicatorEnabled(false);
}
mSlidingMenuLocked = true;
}
public void unlockDrawerMenu() {
((DrawerLayout) findViewById(R.id.drawer_layout)).setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
mSlidingMenuLocked = false;
mDrawerToggle.setDrawerIndicatorEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// toggle nav drawer on selecting action bar app icon/title
if (!ismSlidingMenuLocked() && mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle action bar actions click
switch (item.getItemId()) {
case android.R.id.home:
if (ismSlidingMenuLocked()) {
onBackPressed();
return true;
}
return true;
default: {
return super.onOptionsItemSelected(item);
}
}
}
public BackPressListener getBackPressListener() {
return mBackPressListener;
}
public void setBackPressListener(BackPressListener mBackPressListener) {
this.mBackPressListener = mBackPressListener;
}
@Override
public void onBackPressed() {
if (getSupportFragmentManager().getFragments().size() > 0) {
for (Fragment frag : getSupportFragmentManager().getFragments()) {
if (frag != null && frag.isAdded() && frag instanceof AbstractParentFragment) {
if (frag.getChildFragmentManager().getBackStackEntryCount() > 0) {
frag.getChildFragmentManager().popBackStack();
return;
}
}
}
}
if (mBackPressListener != null) {
if (mBackPressListener.onBackPress())
return;
} else {
if (getSupportFragmentManager().getBackStackEntryCount() == 1) {
this.finish();
return;
}
super.onBackPressed();
}
}
void supportActionBar(boolean support) {
bSupportActionBar = support;
}}
5- 现在创建一个滑动抽屉 activity 来扩展您的基础 activity 并在该主要片段中启动您的主要片段 打开您在滑动抽屉中单击项目的其他片段基础知识。 现在你有两个函数来处理滑动抽屉,如果滑动抽屉图标可见,那么它在点击项目的基础上工作,否则它将是一个带有操作栏的普通片段。
希望这对您有所帮助。 !!!