Xamarin Android Custom MasterDetailPage не вызывает OnLayout, когда страница перетаскивается на страницу сведений, которая называется NavigaionPage

Я взял источник, который нашел здесь: https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/MasterDetailRenderer.cs

И создал пользовательский рендерер в проекте Android Xamarin Forms. Я получил проект для сборки и меню, чтобы открыть / закрыть, как ожидалось, а также отобразить начальную страницу сведений.

Страница сведений - это "NavigaionPage" в Xamarin.Forms, которая на самом деле является просто ViewGroup с кучей кода для работы с функциями Push / Pop.

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

После некоторых исследований в коде я понял, что OnMeasure и OnLayout не вызывались на странице, которая перемещалась на страницу NavigationPage / detail (размер толкаемой страницы оставался равным 0x0 до изменения ориентации).

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

public class MasterDetailContentNavigationPageRenderer : NavigationPageRenderer 
{

  protected override void OnElementChanged(ElementChangedEventArgs<NavigationPage> e)
  {
    base.OnElementChanged(e);

    if(e.OldElement != null)
    {
      e.OldElement.Pushed -= handleOnPushed;
    }

    if(e.NewElement != null)
    {
      e.NewElement.Pushed += handleOnPushed;
    }
  }

  private void handleOnPushed(object sender, EventArgs e)
  {
    var w = MeasureSpec.MakeMeasureSpec(MeasuredWidth, MeasureSpecMode.Exactly);
    var h = MeasureSpec.MakeMeasureSpec(MeasuredHeight, MeasureSpecMode.Exactly);
    Measure(w, h);
    Layout(Left, Top, Right, Bottom);
  }
}

Этот пользовательский рендерер для страницы сведений / NavigaionPage работал для 2 из 3 моих страниц, помещенных в пуш.

Главная / самая важная страница не полностью добавила все элементы пользовательского интерфейса.

Страница, которая была нажата и отсутствует пользовательский интерфейс, имеет НЕКОТОРЫЙ интерфейс. Ниже приведен список того, как страница отображается:

--- SongViewerLayout: RelativeLayout

------ RelativeLayout

--------- ViewerTopBar (рисует все кнопки, кроме одной)

--------- DocumentView (пустое белое пятно между верхней панелью и нумерацией страниц)

--------- ViewerPagination (рисует цвет фона, но не кнопки страницы)

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

Если я вернусь к использованию Xamarin.Forms при условии MasterDetailPage, пользовательский интерфейс загружается как положено.

Я изучил код в репозитории Xamarin.Forms, но на самом деле ничего из этого не относится к внутренней работе добавляемых элементов. Другими словами, страница сведений (которая в моем случае - NavigationPage) добавляется в SetElement (...) и назначаются некоторые обработчики... но я ничего не могу сказать, что ищет страницы, которые нажимают и затем отвечают. Я бы предположил / ожидал, что NavigationPage будет работать так, как ожидалось, теперь, когда это подпредставление MasterDetailPage / DrawerLayout.

Примечание. Представления, которые, по-видимому, имеют наибольшее количество проблем, добавляются программно и получают "LayoutParamaters". Представления, найденные в AXML, похоже, просто появляются.

  • Что-то мне не хватает, чтобы "инициализировать" макет в Android? Я сделал нативные приложения в Android и не должен был делать ничего особенного.

  • Почему пользовательский интерфейс над NavigationPage заставляет NavigationPage не выполнять стандартную инициализацию?

  • Что мне не хватает???

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

Я создал рабочий пример этой проблемы в моей учетной записи GitHub, которую вы можете клонировать здесь: https://github.com/XamarinMonkey/CustomMasterDetail

  1. Создайте и запустите CustomMasterDetail.Droid (обратите внимание, что интерфейс является MasterDetailPage)

  2. Нажмите на любой предмет

  3. Нижняя синяя полоса не имеет номеров страниц.

  4. Поверните ориентацию отображения номера страницы.

  5. Остановить сборку

  6. Закомментируйте весь класс "MainMasterDetailPageRenderer.cs"

  7. Перестройте / запустите приложение

  8. Нажмите на любой предмет

  9. Номера страниц отображаются сразу, как и ожидалось, просто потому, что теперь используется стандартная MasterDetailPage!

  10. Дайте предложения, пожалуйста!

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

Благодаря некоторой обратной связи, это не кажется проблемой в устройствах 6.0. Мое тестирующее устройство - "Samsung Galaxy Tab Pro" с версией 5.1. И, к сожалению, мне нужно это приложение, чтобы вернуться к 4!

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

Проблема заключается в программном добавлении представления в Android 5.1.1 к собственному RelativeLayout (которое помещается на страницу сведений NavigationPage) после его надувания в Xamarin.Forms. Вызов Measure / Layout вручную, кажется, решает проблему. Но мне нужно более автоматизированное решение.

1 ответ

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

В основном я прочитал об Android и нашел способ прослушать изменения макета, используя событие ViewTreeObserver.GlobalLayout в сочетании с вызовом Measure / Layout для detail и master ViewGroups.

public void MeasureAndLayoutNative()
{
    if(_childView != null)
    {
        IVisualElementRenderer renderer = Platform.GetRenderer(_childView);
        if(renderer.ViewGroup != null)
        {
            var nativeView = renderer.ViewGroup;

            var w = MeasureSpec.MakeMeasureSpec(nativeView.MeasuredWidth, MeasureSpecMode.Exactly);
            var h = MeasureSpec.MakeMeasureSpec(nativeView.MeasuredHeight, MeasureSpecMode.Exactly);
            nativeView.Measure(w, h);
            nativeView.Layout(nativeView.Left, nativeView.Top, nativeView.Right, nativeView.Bottom);
        }
    }
}

Я обновил мой пример кода выше с рабочими изменениями!

Другие вопросы по тегам