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


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

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

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

вид ящика не найден с абсолютной гравитацией слева

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

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>
11 67

11 ответов:

в вашем основном макете установите свой 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;
    }
};

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

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

<application android:supportsRtl="true">

а затем написать этот код на Oncreate:

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

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

решение


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>

Ваша активность.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);
            }
        }
    });
//...
}

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

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

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

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

android:supportsRtl="true"

затем в activity_main.xml-файл, поместите этот кусок кода:

android:layout_direction="rtl"

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

вид ящика не найден с абсолютной гравитацией слева

это то, что вы определили

android:layout_gravity="right"

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

mDrawerToggle.syncState();

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

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

Я решил эту проблему, изменив гравитацию navigationview до конец вместо start и это работает для меня

взгляните на это: слайд 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);
}

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

Я сделал следующее изменение в Примере активности навигационного ящика в 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;
}

главная.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 change

android:layout_gravity="start"

до

android:layout_gravity="end"

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

android:layoutDirection="locale"

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

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

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

(добавьте эти строки в метод 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>