Как использовать центр представления как контрольную точку внутри RelativeLayout

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

Мое решение было простым, позиционировало что-то в этом центре и давало ему размеры 1px, поэтому его фактический центр родительского RelativeLayout. Не поймите меня неправильно, это работает, и у меня не было никаких проблем с ним, но если есть более эффективная практика, о которой я хотел бы узнать об этом.

Что касается графического представления того, что я говорю, позвольте мне добавить несколько иллюстраций.

                                                enter image description here

Это первое изображение имеет текстовое TextView, расположенное в центре RelativeLayout, и я дал ему ширину 0dp. Это позволяет мне, как вы можете видеть на следующем изображении, разместить что-нибудь относительно этого центра. Моя точка зрения заключается в том, что мне кажется странным, что вы не можете этого сделать без необходимости добавления дополнительного представления в центр, поскольку я могу видеть такие свойства, как Layout to left of или Layout to right of, но no Layout to center of.

                                                enter image description here

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

Почему я задаю вопросы, на которые нельзя ответить!? Я так настраиваю здесь награду.

Наиболее разумная вещь, которая пока еще (по моему мнению), заключается в том, что я заменяю LinearLayout на LinearLayout на View, который, как я полагаю, занимает немного меньше памяти, даже если он немного меньше. Поэтому я благодарю @yorkw за это. Я удивлен, что никто этого не спрашивал раньше.

Просто пояснить, поскольку, похоже, есть недоразумение относительно того, что я на самом деле после. Я не хочу, чтобы что-то занимало половину родительской ширины/высоты. Я просил использовать его в качестве ориентира (то, что я сказал в названии), чтобы я мог делать такие вещи, как позиционировать изображение слева от центра, не добавляя линейный макет, который занимает половину, а сила тяжести остается или что-то еще.

Update

Поскольку API 14 имеет Space, который является легким подклассом View, который может быть более подходящим для такого рода взлома.

Ответ 1

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

  • Вычислить containerWidth как ширину пикселя вашего, содержащего класс RelativeLayout (вызов этого MyRelativeLayout)
  • Создайте экземпляр MyRelativeLayout.LayoutParams с именем leftHalfWidgetLayoutParams
  • Установите leftHalfWidgetLayoutParams.width = containerWidth/2, либо используя аргумент конструктора, когда он создан выше, либо после факта. После того, как этот факт необходим, если вы хотите позже его отредактировать (например, в переопределении onSizeChanged() в MyRelativeLayout).
  • Каждый раз, когда вы устанавливаете или изменяете leftHalfWidgetLayoutParams.width, вызывайте leftHalfWidget.setLayoutParams(leftHalfWidgetLayoutParams).
  • Вызов requestLayout(), если требуется перерисовать MyRelativeLayout каждый раз, когда изменяется ширина.

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

Теперь я понимаю, что это теряет часть "магии", когда RelativeLayout делает все автоматически, и что там, где ваш подход действительно приятнее. Но RelativeLayout по-прежнему будет применять относительные позиции ваших виджетов, а также может, учитывая добавленное ограничение ширины, которое будет добавлено к параметрам макета вашего leftHalfWidget, поэтому вы не будете переопределять или отказываться от своей общей вклад в этом отношении.

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

Я бы отметил, что если ваш левый виджет всегда будет занимать левую половину контейнера, то я не понимаю, почему горизонтальный LinearLayout (а не RelativeLayout) на верхнем уровне (с вес 0,5 для вашего левого виджета с одинаково взвешенной правой стороной RelativeLayout для оставшейся правой половины), не будет хорошим решением. В этом случае "относительный" материал будет происходить только внутри этой правой половины, поэтому зачем использовать RelativeLayout на верхнем уровне, когда LinearLayout может выполнять работу более кратко? Но, возможно, вы хотите использовать RelativeLayout с левой стороны, чтобы иметь дело с вертикальными отношениями, и поэтому у вас может быть более одного элемента управления в этой левой части.

Ответ 2

Чтобы достичь того, что вы делаете, я использую LinearLayout, layout_width = 0dip и layout_weight = 50. Но это не оптимально, так как он гнездяет другой макет внутри линейного макета. Мне было бы интересно узнать, доступно ли еще лучшее решение.

Ответ 3

Я думаю, что лучше использовать LinearLayout. С атрибутом "layout_weight", я думаю, LinearLayout может решить множество проблем. Использование LinearLayout также нуждается в еще одном пустом представлении внутри LinearLayout, но я думаю, что это лучше, я люблю LinearLayout:) Вот мой код

<LinearLayout android:layout_height="wrap_content"
    android:layout_width="fill_parent"
    android:background="@drawable/your_image">
    <Button android:layout_height="fill_parent"
        android:layout_width="0dip"
        android:layout_weight="1.0"/>
    <View android:layout_height="fill_parent"
        android:layout_width="0dip"
        android:layout_weight="1.0"
        android:visibility="invisible"/>
</LinearLayout>

Наконец, извините за моего бедного английского.

Ответ 4

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

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#ff0000"
    android:weightSum="2" >

    <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:background="#00ff00"
            android:text="@string/hello" />
</LinearLayout>

вы могли бы встроить это в RelativeLayout как есть. Учитывая, что каждый прямой дочерний элемент RelativeLayout имеет определенную роль dev, определенно можно видеть, что дочерний элемент LinearLayout с fill_parent в обоих направлениях является другим слоем RelativeLayout.

Вы можете вставлять произвольные, пустые представления, как указано в другом комментарии с заданным layout_weight, или, как я уже говорил выше, назначить weightSum, чтобы подразумевалось остальное. Я добавил несколько цветов выше, и вот красивая картинка

pretty picture

Ответ 5

В настоящее время нет ничего встроенного в Android, чтобы использовать центр макета в качестве контрольной точки. Однако вы можете сделать это, используя только некоторые расширения и хаки, как было предложено выше в других ответах. Если у Android есть что-то уже для этого, тогда он будет делать то же количество вычислений и работать, как в некоторых из этих ответов. Таким образом, его одно и то же, но он определенно будет выглядеть более чистым, если бы он был встроен.

Ответ 6

Вы можете использовать библиотеку поддержки PercentRelativeLayout.

  • включить его в свой проект: compile 'com.android.support:percent:23.4.0'

  • Используйте PercentRelativeLayout вместо RelativeLayout

  • Сделайте свою кнопку шириной 50% от ее родителя: app:layout_widthPercent="50%"

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