У меня довольно много других проблем с макетом, которые требуют большого количества дополнительных вызовов InvalidateLayout(), поэтому я начинаю сомневаться, понимаю ли я, как работает RelativeLayout.
Вот очень простой пример пользовательского интерфейса, которому нужна метка, выровненная по правому краю:
public class MainPage : ContentPage {
public MainPage() {
var layout = new RelativeLayout();
var label = new Label() {
Text = "I want to be right-aligned."
};
layout.Children.Add(label,
Constraint.RelativeToParent((rl) => rl.Width - label.Width),
Constraint.Constant(10));
var button = new Button() {
Text = "Invalidate"
};
button.Clicked += (object sender, EventArgs e) => layout.ForceLayout();
layout.Children.Add(button,
Constraint.Constant(10),
Constraint.Constant(10));
Content = layout;
}
}
Я ожидаю, что это начнется с правильного выравнивания метки, но оно не выравнивает метку правильно, пока не будет принудительно выполнен другой проход макета. Переопределяя такие методы, как OnSizeRequest() в моем пользовательском элементе управления, я определил, что это связано с тем, что вызовы OnSizeRequest() не происходят до тех пор, пока не будут вызваны лямбда-выражения ограничения RelativeLayout. Итак, когда страница выложена, ширина метки равна -1. Когда ForceLayout() вызывается позже, метка имеет возможность выполнить свою логику компоновки и правильно установить свойство Width, поэтому она размещается правильно.
В более широком контексте я пытаюсь сделать кнопку, которая при нажатии исчезает, а метка перемещается на то место, где она была. Он должен быть выровнен по нижнему правому углу моего макета, но я обнаружил, что изменение Opacity или IsVisible только непоследовательно обновляет макет. Единственным последовательным поведением является то, что RelativeLayout действительно любит запрашивать размер элемента управления, прежде чем он получит возможность изменить свой размер.
Я неправильно интерпретирую, как использовать RelativeLayout, или это ошибка в его логике?