我的要求如下图所示,我的导航抽屉应该从右侧打开。我已经实现了这一点。我的导航抽屉从右向左打开。但问题是切换图标总是在左侧。如何将切换图标设置在右侧?
我查过以下SO问题,但没有一个有用:
将导航抽屉中的切换按钮图像图标从右改为左
<?xml version="1.0" encoding="utf-8"?>
<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:id="@+id/drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="end">
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.example.nav.MainActivity"
android:foregroundGravity="right">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:layout_gravity="right"
app:popupTheme="@style/AppTheme.PopupOverlay"
android:foregroundGravity="right"
android:textAlignment="viewEnd"
android:touchscreenBlocksFocus="false" />
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main" />
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView
android:id="@+id/navigation_view"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:layout_gravity="end"
app:headerLayout="@layout/nav_header"
app:menu="@menu/menu_navigation"
android:textAlignment="viewEnd" />
</android.support.v4.widget.DrawerLayout>
public class MainActivity extends AppCompatActivity {
private DrawerLayout drawerLayout;
private Toolbar toolbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
initNavigationDrawer();
}
@TargetApi(Build.VERSION_CODES.M)
public void initNavigationDrawer() {
NavigationView navigationView = (NavigationView)findViewById(R.id.navigation_view);
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
int id = menuItem.getItemId();
switch (id){
case R.id.home:
Toast.makeText(getApplicationContext(),"Home",Toast.LENGTH_SHORT).show();
drawerLayout.closeDrawers();
break;
case R.id.settings:
Toast.makeText(getApplicationContext(),"Settings",Toast.LENGTH_SHORT).show();
break;
case R.id.trash:
Toast.makeText(getApplicationContext(),"Trash",Toast.LENGTH_SHORT).show();
drawerLayout.closeDrawers();
break;
case R.id.logout:
finish();
}
return true;
}
});
drawerLayout = (DrawerLayout)findViewById(R.id.drawer);
ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(this,drawerLayout,toolbar,R.string.drawer_open,R.string.drawer_close){
@Override
public void onDrawerClosed(View v){
super.onDrawerClosed(v);
}
@Override
public void onDrawerOpened(View v) {
super.onDrawerOpened(v);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item != null && item.getItemId() == android.R.id.home) {
if (drawerLayout.isDrawerOpen(Gravity.RIGHT)) {
drawerLayout.closeDrawer(Gravity.RIGHT);
}
else {
drawerLayout.openDrawer(Gravity.RIGHT);
}
}
return false;
}
};
drawerLayout.addDrawerListener(actionBarDrawerToggle);
actionBarDrawerToggle.syncState();
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (drawerLayout.isDrawerOpen(Gravity.RIGHT)) {
drawerLayout.closeDrawer(Gravity.RIGHT);
} else {
drawerLayout.openDrawer(Gravity.RIGHT);
}
}
});
}
}
实际上没有(实用的)方法让ActionBarDrawerToggle
做到这一点,因为它总是设置在Start/left-side导航按钮上。但是,该类基本上只是一个DrawerListener
,它管理一个专用的Drawable
,并将一个ImageButton
连接到DrawerLayout
。我们可以将类似的东西放在结尾/右侧抽屉中,并将其与ImageButton
放在Toolbar
的同一侧(这是本例所必需的)。
public class EndDrawerToggle implements DrawerLayout.DrawerListener {
private final DrawerLayout drawerLayout;
private final AppCompatImageButton toggleButton;
private final int openDrawerContentDescRes;
private final int closeDrawerContentDescRes;
private DrawerArrowDrawable arrowDrawable;
public EndDrawerToggle(DrawerLayout drawerLayout, Toolbar toolbar,
int openDrawerContentDescRes, int closeDrawerContentDescRes) {
this.drawerLayout = drawerLayout;
this.openDrawerContentDescRes = openDrawerContentDescRes;
this.closeDrawerContentDescRes = closeDrawerContentDescRes;
toggleButton = new AppCompatImageButton(toolbar.getContext(), null,
R.attr.toolbarNavigationButtonStyle);
toolbar.addView(toggleButton, new Toolbar.LayoutParams(GravityCompat.END));
toggleButton.setOnClickListener(v -> toggle());
loadDrawerArrowDrawable();
}
public void syncState() {
if (drawerLayout.isDrawerOpen(GravityCompat.END)) {
setPosition(1f);
} else {
setPosition(0f);
}
}
public void onConfigurationChanged(Configuration newConfig) {
loadDrawerArrowDrawable();
syncState();
}
@Override
public void onDrawerSlide(@NonNull View drawerView, float slideOffset) {
setPosition(Math.min(1f, Math.max(0f, slideOffset)));
}
@Override
public void onDrawerOpened(@NonNull View drawerView) {
setPosition(1f);
}
@Override
public void onDrawerClosed(@NonNull View drawerView) {
setPosition(0f);
}
@Override
public void onDrawerStateChanged(int newState) {}
private void loadDrawerArrowDrawable() {
arrowDrawable = new DrawerArrowDrawable(toggleButton.getContext());
arrowDrawable.setDirection(DrawerArrowDrawable.ARROW_DIRECTION_END);
toggleButton.setImageDrawable(arrowDrawable);
}
private void toggle() {
final int drawerLockMode = drawerLayout.getDrawerLockMode(GravityCompat.END);
if (drawerLayout.isDrawerVisible(GravityCompat.END)
&& (drawerLockMode != DrawerLayout.LOCK_MODE_LOCKED_OPEN)) {
drawerLayout.closeDrawer(GravityCompat.END);
} else if (drawerLockMode != DrawerLayout.LOCK_MODE_LOCKED_CLOSED) {
drawerLayout.openDrawer(GravityCompat.END);
}
}
private void setPosition(float position) {
if (position == 1f) {
arrowDrawable.setVerticalMirror(true);
setContentDescription(closeDrawerContentDescRes);
} else if (position == 0f) {
arrowDrawable.setVerticalMirror(false);
setContentDescription(openDrawerContentDescRes);
}
arrowDrawable.setProgress(position);
}
private void setContentDescription(int resId) {
toggleButton.setContentDescription(toggleButton.getContext().getText(resId));
}
}
EndDrawerToggle
类的工作方式与ActionBarDrawerToggle
与Toolbar
一起使用时的工作方式完全相同(只是构造函数调用不需要Activity
参数):首先实例化切换,然后将其添加为DrawerListener
,并在Activity
的OnPostCreate()
方法中同步。如果您已经重写了activity
的onConfigurationChanged()
方法,您将希望在那里调用切换的相应方法,就像您对ActionBardrawerToggle
所做的那样。
private EndDrawerToggle drawerToggle;
public void initNavigationDrawer() {
...
drawerLayout = (DrawerLayout) findViewById(R.id.drawer);
drawerToggle = new EndDrawerToggle(drawerLayout,
toolbar,
R.string.drawer_open,
R.string.drawer_close);
drawerLayout.addDrawerListener(drawerToggle);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
drawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
drawerToggle.onConfigurationChanged(newConfig);
}
如果您有两个抽屉,并且需要同时使用ActionBarDrawerToggle
和EndDrawerToggle
,那么这是可能的,但是我们需要处理截取抽屉运动事件并将其调度到正确的切换。
如果您喜欢较少的类,可以将ActionBarDrawerToggle
子类化,并将EndDrawerToggle
的功能合并到其中,将每个DrawerListener
方法调用分派到Super
类或本地结束切换代码。
然而,这里的composition可以说要干净得多,它将允许我们原样使用enddrawertoggle
。此示例是一个DrawerListener
,它将SyncState()
和OnConfigurationChanged()
调用中继到每个切换,但只将侦听器方法调用分派到相应的一个,具体取决于正在移动的抽屉。
public class DualDrawerToggle implements DrawerLayout.DrawerListener {
private final DrawerLayout drawerLayout;
private final Toolbar toolbar;
private final ActionBarDrawerToggle actionBarDrawerToggle;
private final EndDrawerToggle endDrawerToggle;
public DualDrawerToggle(Activity activity, DrawerLayout drawerLayout, Toolbar toolbar,
int startDrawerOpenContDescRes, int startDrawerCloseContDescRes,
int endDrawerOpenContDescRes, int endDrawerCloseContDescRes) {
this.drawerLayout = drawerLayout;
this.toolbar = toolbar;
this.actionBarDrawerToggle =
new ActionBarDrawerToggle(activity, drawerLayout, toolbar,
startDrawerOpenContDescRes, startDrawerCloseContDescRes);
this.endDrawerToggle =
new EndDrawerToggle(drawerLayout, toolbar,
endDrawerOpenContDescRes, endDrawerCloseContDescRes);
}
public void syncState() {
actionBarDrawerToggle.syncState();
endDrawerToggle.syncState();
}
public void onConfigurationChanged(Configuration newConfig) {
actionBarDrawerToggle.onConfigurationChanged(newConfig);
// Fixes bug in ABDT, which only reloads the up nav indicator, for some reason.
final DrawerArrowDrawable dad = new DrawerArrowDrawable(toolbar.getContext());
actionBarDrawerToggle.setDrawerArrowDrawable(dad);
endDrawerToggle.onConfigurationChanged(newConfig);
}
@Override
public void onDrawerSlide(@NonNull View drawerView, float slideOffset) {
if (isStartDrawerView(drawerView, drawerLayout.getLayoutDirection())) {
actionBarDrawerToggle.onDrawerSlide(drawerView, slideOffset);
} else {
endDrawerToggle.onDrawerSlide(drawerView, slideOffset);
}
}
@Override
public void onDrawerOpened(@NonNull View drawerView) {
if (isStartDrawerView(drawerView, drawerLayout.getLayoutDirection())) {
actionBarDrawerToggle.onDrawerOpened(drawerView);
} else {
endDrawerToggle.onDrawerOpened(drawerView);
}
}
@Override
public void onDrawerClosed(@NonNull View drawerView) {
if (isStartDrawerView(drawerView, drawerLayout.getLayoutDirection())) {
actionBarDrawerToggle.onDrawerClosed(drawerView);
} else {
endDrawerToggle.onDrawerClosed(drawerView);
}
}
@Override
public void onDrawerStateChanged(int newState) {}
@SuppressLint("RtlHardcoded")
static boolean isStartDrawerView(View drawerView, int layoutDirection) {
final int gravity = ((DrawerLayout.LayoutParams) drawerView.getLayoutParams()).gravity;
final int horizontalGravity = gravity & GravityCompat.RELATIVE_HORIZONTAL_GRAVITY_MASK;
if ((horizontalGravity & GravityCompat.RELATIVE_LAYOUT_DIRECTION) > 0) {
return horizontalGravity == GravityCompat.START;
} else {
if (layoutDirection == View.LAYOUT_DIRECTION_RTL) {
return horizontalGravity == Gravity.RIGHT;
} else {
return horizontalGravity == Gravity.LEFT;
}
}
}
}
同样,dualdrawertoggle
与toolbar
一起使用时的工作方式与actionbardrawertoggle
完全相同,只是构造函数中有额外的内容描述资源ID。
请注意,一个dualdrawertoggle
在内部创建和管理两个其他切换。您不需要在活动
中设置任何其他切换实例;只有dualdrawertoggle
。
备注:
这里使用的AppCompatimageButton
是Toolbar
的常规子级。如果您正在使用工具栏
上的菜单,该菜单将在布局中优先,并向内推切换。要将其保持在外部,您可以按照上面所述修改类,以设置操作菜单项上的切换。我在这里的回答中有一个例子。
如果您的设计要求您使用装饰提供的操作栏
来代替您自己的工具栏
,那么该菜单项示例也可能很有用。虽然ActionBarDrawerToggle
可以与装饰提供的ActionBar
一起工作,但本例无法正常工作。
我已经设置了一个左右两侧的导航抽屉。除了一件事,一切都很好。 我希望我的另一个动作栏项目切换右边的抽屉菜单。正常的左边动作栏切换效果很好。谷歌Android应用程序通知面板是我希望动作模仿的。 下面是我用来设置右侧切换的代码(现在它在单击时强制关闭): 如果有人知道怎么做,如果你能让我知道就太好了! 谢谢
我想在ActionBar的右侧[而不是默认的左侧]显示ActionBar导航图标。 此外,我需要有相同的幻灯片在动画导航抽屉图标在Gmail和谷歌加应用程序。 有没有什么方法可以轻松实现右侧的动画。 任何形式的帮助或建议都是感激的。 提前道谢!
有人能告诉我如何创建活动到这个主要活动,导航抽屉将看到在所有他们?我需要使用这个特定的MainActivity代码。我不需要使用碎片,只要3个简单的活动将添加到这个抽屉。 NavDrawer布局:
我希望能够使用导航抽屉,并根据导航中的选择在不同片段之间进行更改。 我正在使用Android Studio,基本上我所做的是这样的: 使用内置模板“导航抽屉活动”创建了一个新项目 创建了一个空白片段 然后我更改了onNavigationDrawerItemSelected方法中的一些代码。 我的程序崩溃了,给了我很多我不理解的错误。我做错了什么?
我知道如何改变抽屉图标,如果它在左侧,但我没有找到任何解决方案,改变导航抽屉汉堡图标,如果抽屉是在右侧。任何帮助都是可以感激的。
我正在为我的应用程序实现一个导航抽屉。现在,除了一个小故障外,它工作正常。当我设置导航抽屉图标(ic_Drawer)来替换常规的“HomeAsUp”插入符号图标时,我仍然得到箭头。导航抽屉图标不显示。我已经实现了android开发者网站上的每一种方法。但它似乎不起作用。 以下是我的代码: