我跟随Creating a Navigation Drawer tutorial (Android Training)。
我已经下载了示例应用,它按预期工作。我打开抽屉,向后按,它就会关闭。
当我用lib/android-support-v4.jar
(大小为741 KB)中的更新版本(修订版20)替换Android-SDK/extras/android/support/v4/android-support-v4.jar
(最初大小为523 KB)时出现问题。更换后,如果我打开抽屉,然后按下设备的后退按钮,应用程序将关闭,而不是关闭抽屉。
我该如何解决?我应该保留旧的 android-support-v4.jar 版本,还是应该在需要时以编程方式拦截关闭抽屉的后退按钮?
更新:我已经继续测试问题,为此我在AndroidStudio中构建了项目。复制示例应用程序(src,res并更新清单)之后运行它:即使DrawerLayout打开,后退按钮也会关闭应用程序。 然后我修改了build.gradle文件,改变了行:
compile 'com.android.support:appcompat-v7:20.0.0'
与
compile 'com.android.support:appcompat-v7:19.0.0'
问题消失了:后退按钮首先关闭抽屉,然后关闭应用程序
活动(Link to the Android Training Source Code)的完整代码:
public class MainActivity extends Activity {
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
private ActionBarDrawerToggle mDrawerToggle;
private CharSequence mDrawerTitle;
private CharSequence mTitle;
private String[] mPlanetTitles;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTitle = mDrawerTitle = getTitle();
mPlanetTitles = getResources().getStringArray(R.array.planets_array);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerList = (ListView) findViewById(R.id.left_drawer);
// set a custom shadow that overlays the main content when the drawer opens
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
// set up the drawer's list view with items and click listener
mDrawerList.setAdapter(new ArrayAdapter<String>(this,
R.layout.drawer_list_item, mPlanetTitles));
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
// enable ActionBar app icon to behave as action to toggle nav drawer
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
// ActionBarDrawerToggle ties together the the proper interactions
// between the sliding drawer and the action bar app icon
mDrawerToggle = new ActionBarDrawerToggle(
this, /* host Activity */
mDrawerLayout, /* DrawerLayout object */
R.drawable.ic_drawer, /* nav drawer image to replace 'Up' caret */
R.string.drawer_open, /* "open drawer" description for accessibility */
R.string.drawer_close /* "close drawer" description for accessibility */
) {
public void onDrawerClosed(View view) {
getActionBar().setTitle(mTitle);
//supportInvalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
public void onDrawerOpened(View drawerView) {
getActionBar().setTitle(mDrawerTitle);
//supportInvalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
if (savedInstanceState == null) {
selectItem(0);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
/* Called whenever we call invalidateOptionsMenu() */
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
// If the nav drawer is open, hide action items related to the content view
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
menu.findItem(R.id.action_websearch).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// The action bar home/up action should open or close the drawer.
// ActionBarDrawerToggle will take care of this.
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle action buttons
switch(item.getItemId()) {
case R.id.action_websearch:
// create intent to perform web search for this planet
Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
intent.putExtra(SearchManager.QUERY, getActionBar().getTitle());
// catch event that there's no activity to handle intent
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
} else {
Toast.makeText(this, R.string.app_not_available, Toast.LENGTH_LONG).show();
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/* The click listner for ListView in the navigation drawer */
private class DrawerItemClickListener implements ListView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectItem(position);
}
}
private void selectItem(int position) {
// update the main content by replacing fragments
Fragment fragment = new PlanetFragment();
Bundle args = new Bundle();
args.putInt(PlanetFragment.ARG_PLANET_NUMBER, position);
fragment.setArguments(args);
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
// update selected item and title, then close the drawer
mDrawerList.setItemChecked(position, true);
setTitle(mPlanetTitles[position]);
mDrawerLayout.closeDrawer(mDrawerList);
}
@Override
public void setTitle(CharSequence title) {
mTitle = title;
getActionBar().setTitle(mTitle);
}
/**
* When using the ActionBarDrawerToggle, you must call it during
* onPostCreate() and onConfigurationChanged()...
*/
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Pass any configuration change to the drawer toggls
mDrawerToggle.onConfigurationChanged(newConfig);
}
/**
* Fragment that appears in the "content_frame", shows a planet
*/
public static class PlanetFragment extends Fragment {
public static final String ARG_PLANET_NUMBER = "planet_number";
public PlanetFragment() {
// Empty constructor required for fragment subclasses
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_planet, container, false);
int i = getArguments().getInt(ARG_PLANET_NUMBER);
String planet = getResources().getStringArray(R.array.planets_array)[i];
int imageId = getResources().getIdentifier(planet.toLowerCase(Locale.getDefault()),
"drawable", getActivity().getPackageName());
((ImageView) rootView.findViewById(R.id.image)).setImageResource(imageId);
getActivity().setTitle(planet);
return rootView;
}
}
}
答案 0 :(得分:22)
将支持库升级到20.0.0后,我遇到了完全相同的问题。
添加以下一行代码可以解决我的问题。 (on myCreate in my activitiy)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
mDrawerLayout = (DrawerLayout) this.findViewById(R.id.drawer_layout);
mDrawerLayout.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); /* add this line */
....
}
答案 1 :(得分:19)
以下是您问题的快速解决方法。只需覆盖Activity / Fragment中的onBackPressed()
方法:
@Override
public void onBackPressed()
{
if (mDrawerLayout.isDrawerOpen(Gravity.START))
mDrawerLayout.closeDrawer(Gravity.START);
else
super.onBackPressed();
}
左侧抽屉使用Gravity.START
,右侧抽屉使用Gravity.END
答案 2 :(得分:14)
在setUpNavDrawer中
mDrawerLayout.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
另外
@Override
public void onBackPressed()
{
if (mDrawerLayout.isOpen())
mDrawerLayout.close();
else
super.onBackPressed();
}
答案 3 :(得分:2)
不推荐使用mDrawerLayout.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
的解决方案,因为如果您在活动中有TextEdit,则无法获得焦点。如前所述,更好地使用onBackPressed()
解决方案。
@Override
public void onBackPressed()
{
if (mDrawerLayout.isOpen())
mDrawerLayout.close();
else
super.onBackPressed();
}
答案 4 :(得分:1)
右键单击您的项目单击属性并转到java构建路径并检查您所需的库是否存在且没有不需要的库..如果您更改了supportlibrary v4,我建议您在appcompat v7库中更改它。 。 其次
onDrawerOpened
当抽屉布局完全浮出你的ui时,如果它没有完全浮出水面,那么活动就会被关闭..
请在文档站点的代码中重新检查这些内容
The main content view (the FrameLayout above) must be the first child in the
DrawerLayout because the XML order implies z-ordering and the drawer must be
on top of the content.
The main content view is set to match the parent view's width and height,
because it represents the entire UI when the navigation drawer is hidden.
The drawer view (the ListView) must specify its horizontal gravity with the
android:layout_gravity attribute. To support right-to-left (RTL) languages,
specify the value with "start" instead of "left" (so the drawer appears on
the right when the layout is RTL).
The drawer view specifies its width in dp units and the height matches
the parent view. The drawer width should be no more than 320dp so the
user can always see a portion of the main content.
最后,我看到您正在使用支持库,如果您使用支持库,则不应使用应使用ActiobBarActivity或FragmentActivity的活动
答案 5 :(得分:1)
焦点在这里是一个问题,但实际上孩子并没有把它的父母的焦点放在抽屉布局(ActionBar / Toolbar)之上。
我在MainActivity.class
中使用了一种非常类似的方法:
@Override
public void onBackPressed() {
if (mDrawerLayout.isDrawerVisible(Gravity.START)) {
mDrawerLayout.closeDrawer(Gravity.START);
return;
}
super.onBackPressed();
}
答案 6 :(得分:0)
尝试此修复:
mDrawerLayout.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
...
mDrawerLayout.setDrawerListener(new DrawerListener() {
@Override
public void onDrawerStateChanged(int arg0) {
}
@Override
public void onDrawerSlide(View arg0, float arg1) {
}
@Override
public void onDrawerOpened(View view) {
mDrawerLayout.post(new Runnable() {
@Override
public void run() {
// request the focus to correctly process pressed
// back key
mDrawerLayout.requestFocus();
}
});
}
@Override
public void onDrawerClosed(View arg0) {
}
});
答案 7 :(得分:0)
无任何警告地工作
@Override
public void onBackPressed() {
if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
drawerLayout.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
答案 8 :(得分:0)
初始化
navigationView.setNavigationItemSelectedListener(this)
actionBarToggle = ActionBarDrawerToggle(this, drawerLayout, 0, 0)
drawerLayout.addDrawerListener(actionBarToggle)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
actionBarToggle.syncState()
然后使用此方法处理
override fun onSupportNavigateUp(): Boolean {
if (this.drawerLayout.isDrawerOpen(GravityCompat.START)) {
this.drawerLayout.closeDrawer(GravityCompat.START)
} else {
this.drawerLayout.openDrawer(GravityCompat.START)
}
return true
}