Intereting Posts
Видео не воспроизводится на Android Android: включение / выключение Wi-Fi-точки доступа по программе Android Marshmallow (6.0) Пользовательский массив ArrayAdapter в ListFragment Android – восстановление последнего просмотра Активность Различие может вызывать «java.lang.NullPointerException» Android – Можно ли использовать навигационный ящик с правой стороны? Ошибка: невозможно получить заблокированный буффер, очень вероятный клиент пытается заблокировать больше, чем maxImages buffers Как я могу выполнить что-то только один раз для запуска приложения? Отключить Google Analytics из отчетов перед запуском Android Java.lang.NoClassDefFoundError: com / android / utils / ILogger в visual studio 2015 Для Android-событий, почему операторы switch более распространены, чем цепочки if-else? VerifyError в инструментах для сборки тестовых проектов android v17 Android: Как запросить курсор для обновления ListView после удаления строки базы данных? Отменить загрузку в WebView на Android Изменение источника ImageView

RelativeLayout в вычислении ширины StackLayout

У меня есть странная проблема с RelativeLayouts, вложенным в StackLayout, кажется, что StackLayout вычисляет ширину своих элементов, должен использовать ширину RelativeLayout, а затем RelativeLayout снова вычисляет ее. Это приводит к тому, что дочерний элемент управления представляет собой квадрат относительной ширины, но следующие элементы управления размещаются как по относительной ширине.

Является ли это ошибкой или я делаю что-то неправильно?

пример

<?xml version="1.0" encoding="utf-8" ?> <ContentPage x:Class="MyClass" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" > <StackLayout Orientation="Horizontal" BackgroundColor="Blue"> <RelativeLayout> <ContentView BackgroundColor="Red" RelativeLayout.XConstraint= "{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0}" RelativeLayout.WidthConstraint= "{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.707106}" RelativeLayout.YConstraint= "{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0}" RelativeLayout.HeightConstraint= "{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=1}"> </ContentView> </RelativeLayout> <RelativeLayout> <ContentView BackgroundColor="Green" RelativeLayout.XConstraint= "{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0}" RelativeLayout.WidthConstraint= "{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.5}" RelativeLayout.YConstraint= "{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0}" RelativeLayout.HeightConstraint= "{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=1}"> </ContentView> </RelativeLayout> </StackLayout> </ContentPage> 

Скриншот

Solutions Collecting From Web of "RelativeLayout в вычислении ширины StackLayout"

Два элемента RelativeLayout могут быть запутанным фактором, и тот факт, что каждый из них указан в позиции X 0 относительно родительского StackLayout , который кажется конфликтом.

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

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

Вот что я придумал:

 <?xml version="1.0" encoding="utf-8" ?> <ContentPage x:Class="App1.HomePage" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" > <StackLayout Orientation="Horizontal" BackgroundColor="Blue"> <RelativeLayout> <ContentView BackgroundColor="Red" RelativeLayout.XConstraint= "{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0}" RelativeLayout.WidthConstraint= "{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.35}" RelativeLayout.YConstraint= "{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0}" RelativeLayout.HeightConstraint= "{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=1}"> </ContentView> <!-- </RelativeLayout> <RelativeLayout> --> <ContentView BackgroundColor="Green" RelativeLayout.XConstraint= "{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.5}" RelativeLayout.WidthConstraint= "{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.25}" RelativeLayout.YConstraint= "{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0}" RelativeLayout.HeightConstraint= "{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=1}"> </ContentView> </RelativeLayout> </StackLayout> </ContentPage> 

Означает ли это нечто более близкое к ожидаемому?

Скриншот

Ничто не позиционируется и не расширяется до любого из указанных значений.

Это не совсем так. Просто заметив это, красная полоса выглядит примерно так: соотношение ширины 7: 3 к первой синей полосе. Другими словами, это первый RelativeLayout. Второй RelativeLayout частично вытолкнут с экрана, но похоже, что второй ContentView полностью находится на экране и расширен в пропорции к первым двум диапазонам – т. Е. Зеленая полоса находится примерно в соотношении 5: 7 к красной полосе ,

Другими словами, два RelativeViews получили равные распределения пространства, а два ContentViews полностью находятся на экране. Однако общая ширина двух RelativeLayouts больше ширины экрана!

Вы можете посмотреть исходный код для StackLayout здесь: https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Core/StackLayout.cs

И RelativeLayout здесь: https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Core/RelativeLayout.cs .

Я не просмотрел все подробно, но для StackLayout есть двухпроходный макет, который сначала пытается сделать «наивный» макет, надеясь, что все дети подойдут. Если нет, он проходит через сжатие. И поскольку дети RelativeLayout не имеют определенной ширины, они сначала пытаются захватить всю ширину родителя и сжиматься оттуда.

В основном, это сводится к тому, что это недостоверная система с точки зрения Xamarin.Forms. Использование StackLayout подобно этому, где нет ничего, дающего определенную ширину от родителя или дочернего элемента, может привести к неожиданным результатам. В таких ситуациях, когда вы не хотите динамического макета, другие макеты, такие как Grid, дают гораздо более предсказуемые результаты.

Редактировать:

При дальнейшем исследовании, если у вас есть StackLayout с несколькими дочерними элементами, включая один (или более) RelativeLayout без спецификации ширины, вы, вероятно, ошибаетесь. Часть этого имеет смысл, но вы также видите симптомы сомнительного (ИМО) дизайнерского решения.

RelativeLayout, по умолчанию, предполагает, что он имеет ту же ширину, что и его родитель. StackLayout имеет многоступенчатый процесс, сначала выполняет проход Measure, затем проход Layout и, наконец, pass pass (который на самом деле не вступает в игру в этой ситуации). Во время измерения RelativeLayout определяет, сколько места ему нужно, чтобы выложить своих детей. Для первого RelativeLayout это означает, что ему требуется около 70% общей ширины его родителя (т.е. 70% от общей ширины экрана – я игнорирую дробную сумму). Следующий RelativeLayout говорит, что ему требуется 50% общей ширины.

Затем идет макет. Первый RelativeLayout получает 70% запросов, поэтому он определяет своего ребенка, который будет составлять 70% (соглашаясь с вашими наблюдениями). Второй RelativeLayout получает 50% запросов и выделяет 50% его дочерью. Да, это означает, что StackLayout выделяет более 100% ширины экрана. Конечно, он отображает только первые 100%.

Поэтому способ, которым Xamarin.Forms делает макет, кажется немного странным, но я также не уверен в ограничениях, которые у вас есть на нужном вам решении.

Предполагая, что вам нужно иметь нескольких родственников RelativeLayout под StackLayout, в соответствии с этими инструкциями вы получите то, что хотите:

  1. Заполните всю ширину каждого RelativeLayout, даже если это просто пустой ContentView. Если вы этого не сделаете, описанный выше шаг измерения / макета приведет к сильным головным болям.

  2. Назначьте небольшое значение MinimumWidthRequest и HorizontalOptions, включая Expand для каждого RelativeLayout. Это позволит пропустить компресс (упомянутый выше) и дать каждому RelativeLayout такое же распределение ширины. При тестировании я использовал MinWidthRequest = "20" и HorizontalOptions = "StartAndExpand", и это сработало.

Это даст достаточные ограничения для механизма компоновки Xamarin.Forms, чтобы вести себя так, как вы ожидаете.