Изменение выравнивания кнопок AlertDialog

Беседа часами об изменении выравнивания кнопок внутри AlertDialog (support.v7 one), так как они не будут выравниваться в соответствии с направлением просмотра локали, , несмотря на то, что все приложение выравнивается слева, а также текст внутри AlertDialog.

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

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

TextView messageView = (TextView)dialog.findViewById(android.R.id.message);
messageView.setGravity(Gravity.RIGHT); // or LEFT

Конечно, это не работает на кнопках, так как вместо этого мне нужно изменить гравитацию макета.

Вот как я нахожу кнопки (после того, как я вызываю show() на AlertDialog.Builder, конечно, иначе они будут пустыми):

AppCompatButton accept = (AppCompatButton)dialog.findViewById(android.R.id.button1);
AppCompatButton cancel = (AppCompatButton)dialog.findViewById(android.R.id.button2);

И вот как я пытаюсь изменить их выравнивание внутри своего родительского LinearLayout:

((LinearLayout.LayoutParams)accept.getLayoutParams).gravity = Gravity.RIGHT;
((LinearLayout.LayoutParams)cancel.getLayoutParams).gravity = Gravity.RIGHT;

Я выбрал RIGHT, так как сторона кнопок внутри диалога всегда противоположна стороне, к которой текст привязан. (Да - я тоже попытался LEFT, ничего не изменилось).

Это не работает. У кого-нибудь есть идея, как этого достичь? Кажется, они просто застряли на своем месте.

Изменить: Заголовок также не выровнен, я только что подтвердил это (по какой-то причине он появляется справа, как и моя системная конфигурация, а не как моя локальная конфигурация).

Ответ 1

Проблема не в настройках Gravity... Когда вы смотрите на источник xml (../sdk/platforms/android-23/data/res/layout/alert_dialog_material.xml), макет AlertDialog содержит следующее:

<LinearLayout android:id="@+id/buttonPanel"
    style="?attr/buttonBarStyle"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" ...>

    <Button android:id="@+id/button3"
        style="?attr/buttonBarNeutralButtonStyle" ... />

    <Space
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:visibility="invisible" />

    <Button android:id="@+id/button2"
        style="?attr/buttonBarNegativeButtonStyle" ... />

    <Button android:id="@+id/button1"
        style="?attr/buttonBarPositiveButtonStyle" ... />
</LinearLayout>

С помощью кнопок отображается Space. Этот вид наполняет контейнер весом. Поэтому на самом деле у вас есть виджет, который нажимает кнопки в правом родительском контейнере.

Простое решение может вызвать контейнер родительских кнопок и удалить элемент Space перед установкой силы тяжести.

// get the container
LinearLayout containerButtons = (LinearLayout) dialog.findViewById(R.id.buttonPanel); 
// remove the Space view
containerButtons.removeView(containerButtons.getChildAt(1)); 
// set a gravity to the children buttons
containerButtons.setGravity(Gravity.RIGHT); 

Однако вы должны создать и использовать свой собственный макет, в случае будущих изменений в разработке Google.

Ответ 2

Вы можете полностью настроить AlertDialog. Трюк здесь, вероятно, заключается в использовании пользовательского представления для диалога и создания собственных кнопок в этом представлении.

В качестве примера см. Как добавить пользовательские кнопки в макет AlertDialog?