ScrollTo в ListView работает не сразу после настройки видимости - PullRequest
0 голосов
/ 17 мая 2018

В настоящее время я пытаюсь скопировать средство выбора даты для Android с формами xamarin в качестве пользовательского элемента управления в форме диалога, как для практических целей, так как я искренне ненавижу средство выбора даты iPhone ... В любом случае, пока все работает нормально,Я могу выбрать день, переключаться между месяцами, выбирать год и т. Д.

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

2017 - ср., 22 февраля.

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

Итак, скажем, пользователь нажимает на «2017», ему теперь представлен вид списка, и он не прокручивается и показывает самый первый элемент сверху.Теперь он снова нажимает на «2017» и, наконец, listView прокручивает в позицию, так что элемент с «2017» отображается в центре для пользователя.Может быть, изображение ниже объясняет это немного лучше (Пуск -> Первое нажатие на 2017 -> Второе нажатие на 2017) image First tap on 2017 -> Second tap on 2017">

Я делаю что-то не так, что-то не получаетсявидеть?Может ли быть так, что высота ответственна за такое поведение, если сам список не виден?

Примечание: я уже пытался вызвать scrollTo с настройкой SelectedDate или при создании фактического представления (т.е. в конструкторе или OnBindingContextChanged).

Примечание 2: проверка if(sender == YearLabel) верна в первый раз, а selection не равна нулю, но то же значение, что и во второй раз

важная часть XAML

<StackLayout BackgroundColor="{DynamicResource AccentColor}" Spacing="5" Padding="15" Grid.Row="0">
        <Label Text="{Binding SelectedDate, StringFormat='{0:yyyy}', Source={x:Reference this}}" FontSize="Medium" TextColor="LightGray" x:Name="YearLabel">
            <Label.GestureRecognizers>
                <TapGestureRecognizer Tapped="OnDateLabelTapped"/>
            </Label.GestureRecognizers>
        </Label>
        <Label Text="{Binding SelectedDate, StringFormat='{0:ddd, d. MMMM}', Source={x:Reference this}" FontSize="Large" TextColor="White" x:Name="DayLabel">
            <Label.GestureRecognizers>
                <TapGestureRecognizer Tapped="OnDateLabelTapped"/>
            </Label.GestureRecognizers>
        </Label>
    </StackLayout>
    <StackLayout Grid.Row="1">
        <StackLayout x:Name="YearPicker" IsVisible="False" HorizontalOptions="FillAndExpand" Spacing="0">
            <ListView ItemSelected="OnYearSelected" x:Name="YearList" ItemTemplate="{StaticResource dateDataTemplateSelector}" SeparatorVisibility="None" />
            <BoxView HeightRequest="1" HorizontalOptions="FillAndExpand" Color="#efefef" />
        </StackLayout>
    ... other stuff

в коде позади

public ObservableCollection<YearViewModel> Years { get; set; }

public DateTime SelectedDate
{
    get { return (DateTime)GetValue(SelectedDateProperty); }
    set { SetValue(SelectedDateProperty, value); }
}

private void OnDateLabelTapped(object sender, EventArgs args)
    {
        if(sender == YearLabel)
        {
            YearLabel.TextColor = Color.White;
            DayLabel.TextColor = Color.LightGray;
            YearPicker.IsVisible = true;
            DayPicker.IsVisible = false;

            var selection = Years.FirstOrDefault(y => y.Date.Year == SelectedDate.Year);
            YearList.ScrollTo(selection, ScrollToPosition.Center, true);
        }
        else if(sender == DayLabel)
        {
            DayLabel.TextColor = Color.White;
            YearLabel.TextColor = Color.LightGray;
            DayPicker.IsVisible = true;
            YearPicker.IsVisible = false;
        }
    }

Если вы считаете, что больше кода может быть полезным, пожалуйста, дайте мне знать!

1 Ответ

0 голосов
/ 18 мая 2018

Так что, поскольку я снова и снова отлаживал это, мое предположение, что это может быть из-за отсутствия высоты listView непосредственно после установки YearPicker.IsVisible = true;, было правильным. Я немного раздражен тем, что раньше этого не видел, но хорошо.

Мое текущее решение -

private void OnDateLabelTapped(object sender, EventArgs args)
    {
        if(sender == YearLabel)
        {
            YearLabel.TextColor = Color.White;
            DayLabel.TextColor = Color.LightGray;
            YearPicker.IsVisible = true;
            DayPicker.IsVisible = false;

            Device.StartTimer(TimeSpan.FromMilliseconds(20), () =>
            {
                var selection = Years.FirstOrDefault(y => y.Date.Year == SelectedDate.Year);
                YearList.ScrollTo(selection, ScrollToPosition.Center, true);
                return false;
            });
        }
        else if(sender == DayLabel)
        {
            DayLabel.TextColor = Color.White;
            YearLabel.TextColor = Color.LightGray;
            DayPicker.IsVisible = true;
            YearPicker.IsVisible = false;
        }
    }

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

Так как это очень как хак, я был бы признателен за любое другое / лучшее решение для этого. Я уже пытался прослушать sizeChanged событие listView, но безрезультатно

YearList.SizeChanged += (s, e) =>
        {
            var selection = Years.FirstOrDefault(y => y.Date.Year == SelectedDate.Year);
            YearList.ScrollTo(selection, ScrollToPosition.Center, true);

        };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...