Как открыть навигационный ящик справа налево

Прежде всего, я знаю, что этот вопрос появился здесь раньше, но после многих попыток все еще не получилось. Я работаю над примером из Сайт разработчиков Android.

Я пытаюсь открыть меню справа налево, а не как его реализация в примере (слева направо). Кроме того, я хочу переместить открытую кнопку меню в правую сторону панели действий. Я также добавил некоторые ответы здесь, например в этом ответе.

Я пытаюсь изменить гравитацию представлений и макетов, но получаю ошибку:

не найдено ни одного обзора ящика с абсолютной силой тяжести LEFT

Не могли бы вы помочь мне разобраться, в чем проблема в моем коде, и что я должен изменить, чтобы открыть меню справа и переместить кнопку панели действий вправо?

код xml находится здесь:

<android.support.v4.widget.DrawerLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_gravity="right"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <FrameLayout
        android:id="@+id/content_frame"
        android:layoutDirection="rtl"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

    <ListView android:id="@+id/left_drawer"
        android:layout_width="200dp"
        android:layout_height="match_parent"
        android:layout_gravity="right"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="10dp"
        android:background="#111"/>

</android.support.v4.widget.DrawerLayout>

Ответ 1

В вашем основном макете установите гравитацию ListView вправо:

android:layout_gravity="right" 

Также в вашем коде:

mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
            R.drawable.ic_drawer, R.string.drawer_open,
            R.string.drawer_close) {

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item != null && item.getItemId() == android.R.id.home) {
            if (mDrawerLayout.isDrawerOpen(Gravity.RIGHT)) {
                mDrawerLayout.closeDrawer(Gravity.RIGHT);
            } 
            else {
                mDrawerLayout.openDrawer(Gravity.RIGHT);
            }
        }
        return false;
    }
};

надеюсь, что это работает:)

Ответ 2

Добавьте этот код в манифест:

<application android:supportsRtl="true">

а затем напишите этот код в Oncreate:

getWindow().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_RTL);

Это работает для меня.;)

Ответ 3

Решение


your_layout.xml:

<?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_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="end">

    <include layout="@layout/app_bar_root"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="end"
        android:fitsSystemWindows="true"
        app:itemTextColor="@color/black"
        app:menu="@menu/activity_root_drawer" />

</android.support.v4.widget.DrawerLayout>

YourActivity.java:

@Override
protected void onCreate(Bundle savedInstanceState) {
//...
toolbar = (Toolbar) findViewById(R.id.toolbar);

drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();

toolbar.setNavigationOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            if (drawer.isDrawerOpen(Gravity.RIGHT)) {
                drawer.closeDrawer(Gravity.RIGHT);
            } else {
                drawer.openDrawer(Gravity.RIGHT);
            }
        }
    });
//...
}

Ответ 4

Этот ответ полезен для того, чтобы навигация была открыта справа налево, но у него нет решения, чтобы установить ее значок справа. Этот код может это исправить. Если вы зададите ему drawer в качестве первого параметра и ViewCompat.LAYOUT_DIRECTION_RTL в качестве второго параметра, для более полной компоновки будет установлено значение RTL. Это быстрое и простое решение, но я не думаю, что оно может быть правильным решением для тех, кто хочет только открыть меню справа налево и установить его значок справа. (Хотя это зависело от вашей цели.) Однако я предлагаю дать toolbar вместо drawer. Таким образом, просто панель инструментов стала RTL. Поэтому я думаю, что комбинация из этих двух ответов может сделать именно то, что вы хотите.

Согласно этим описаниям, ваш код должен выглядеть следующим образом:

(Добавьте эти строки в метод onCreate)

final DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); // Set it final to fix the error that will be mention below.

    ViewCompat.setLayoutDirection(toolbar, ViewCompat.LAYOUT_DIRECTION_RTL);

    toolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (drawer.isDrawerOpen(Gravity.RIGHT))
                drawer.closeDrawer(Gravity.RIGHT);
            else
                drawer.openDrawer(Gravity.RIGHT);
        }
    });

Обратите внимание, что вы должны сделать ящик окончательным, в противном случае вы получите эту ошибку:

Переменная 'ящик' доступна изнутри внутреннего класса, должна быть объявлен окончательным

И не забудьте использовать end вместо start в методе onNavigationItemSelected:

drawer.closeDrawer(GravityCompat.END);

и в вашем activity_main.xml

<android.support.v4.widget.DrawerLayout 
   android:id="@+id/drawer_layout"
   tools:openDrawer="end">

   <android.support.design.widget.NavigationView
      android:id="@+id/nav_view"
      android:layout_gravity="end"/>
</android.support.v4.widget.DrawerLayout>

Ответ 5

Вот документация на ящике, и кажется, что вы можете настроить ее на выход слева или справа.

Позиционирование и расположение ящика управляется с помощью атрибута android: layout_gravity для дочерних представлений, соответствующих той стороне представления, которую вы хотите, чтобы ящик выходил из: влево или вправо. (Или начало/конец на версиях платформы, поддерживающих направление макета.)

http://developer.android.com/reference/android/support/v4/widget/DrawerLayout.html

Ответ 6

Взгляните на это: слайд ExpandableListView в форме DrawerLayout справа налево

Я предполагаю, что реализован ActionBarDrawerToggle, трюк заключается в том, чтобы переопределить метод onOptionsItemSelected(MenuItem item) внутри объекта ActionBarDrawerToggle следующим образом:

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item != null && item.getItemId() == android.R.id.home) {
            if (mDrawer.isDrawerOpen(Gravity.RIGHT)) {
                mDrawer.closeDrawer(Gravity.RIGHT);
            } else {
                mDrawer.openDrawer(Gravity.RIGHT);
            }
            return true;
        }
        return false;
    }

убедитесь в этом и вызовите это из onOptionsItemSelected(MenuItem item) в Управлении:

@Override
public boolean onOptionsItemSelected(MenuItem item) {

if(mDrawerToggle.onOptionsItemSelected(item)) {
    return true;
}

return super.onOptionsItemSelected(item);
}

Это позволит вам использовать функциональность кнопки "Дом". Чтобы переместить кнопку в правую сторону панели действий, вам нужно будет реализовать пользовательский элемент действия и, возможно, некоторые другие вещи, чтобы заставить его работать так, как вы хотите.

Ответ 7

Вы должны сначала поместить этот код в свой AppManifest.xml в тег приложения:

android:supportsRtl="true"

то в файле activity_main.xml поместите этот фрагмент кода:

android:layout_direction="rtl"

Ответ 8

основная проблема со следующей ошибкой:

не найдено ни одного обзора ящика с абсолютной силой тяжести LEFT

заключается в том, что вы определили

android:layout_gravity="right"

для просмотра списка справа, но попробуйте открыть ящик слева, вызвав эту функцию:

mDrawerToggle.syncState();

и нажав на значок гамбургера!

просто прокомментируйте вышеприведенную функцию и попытайтесь обработать открытие/закрытие меню, например, @Rudi!

Ответ 9

Я решил эту проблему, изменив гравитацию навигационного обзора

android:layout_gravity

закончить вместо начала

<android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="end"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header"
        app:menu="@menu/activity_drawer" />

Это сработало для меня.

Ответ 10

Я сделал следующую модификацию для примера Activity Drawer в Android Studio. В библиотеках поддержки 25.3.1.

MainActivity.java:

private DrawerLayout mDrawerLayout;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    ActionBar actionBar = getSupportActionBar();
    if (actionBar != null) {
        actionBar.setDisplayHomeAsUpEnabled(true);
    }

    mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);
}

@Override
public void onBackPressed() {
    if (mDrawerLayout.isDrawerOpen(GravityCompat.END)) {
        mDrawerLayout.closeDrawer(GravityCompat.END);
    } else {
        super.onBackPressed();
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int itemId = item.getItemId();
    switch (itemId) {
        case android.R.id.home:
            finish();
            return true;

        case R.id.action_right_drawer:
            if (mDrawerLayout.isDrawerOpen(GravityCompat.END)) {
                mDrawerLayout.closeDrawer(GravityCompat.END);
            } else {
                mDrawerLayout.openDrawer(GravityCompat.END);
            }
            return true;

        default:
            return super.onOptionsItemSelected(item);
    }
}

@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.

    mDrawerLayout.closeDrawer(GravityCompat.END);
    return true;
}

main.xml(скачать ic_menu_white_24px из https://material.io/icons/):

<?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item android:id="@+id/action_right_drawer"
        android:title="Drawer menu"
        android:icon="@drawable/ic_menu_white_24px"
        android:orderInCategory="100"
        app:showAsAction="always" />
</menu>

В изменении activity_main.xml

android:layout_gravity="start"

к

android:layout_gravity="end"

Ответ 11

Сделать его открытым с rtl не очень удобно для пользователей, чтобы он реагировал на пользовательский язык. Я просто добавил следующую строку к моим параметрам DrawerLayout:

android:layoutDirection="locale"

Добавил его в мой AppBarLayout, чтобы макет гамбургера соответствовал направлению открытия ящика.