Xamarin Forms ListView: проблемы с программным выбором и пользовательским средством визуализации - PullRequest
0 голосов
/ 10 октября 2019

У меня проблемы с просмотром списка XF и пользовательским рендерером. Мне нужно:

  • Изменить цвет фона выбранного элемента
  • Предварительно выбрать элемент при запуске программным способом.

Я смог изменитьцвет фона выбранного элемента, и все работает, если я предварительно не выбрал элемент.

Для пользовательских элементов управления и средств визуализации я использовал «стандартный» код, который можно найти во многих примерах:

Пользовательский элемент управления:

    public class RRViewCell : ViewCell
{
    public static readonly BindableProperty SelectedItemBackgroundColorProperty = BindableProperty.Create("SelectedItemBackgroundColor", typeof(Color), typeof(RRViewCell), Color.Default);

    public Color SelectedItemBackgroundColor
    {
        get { return (Color)GetValue(SelectedItemBackgroundColorProperty); }
        set { SetValue(SelectedItemBackgroundColorProperty, value); }
    }
}

Средство визуализации Android:

public class RRViewCellRendererAndroid : ViewCellRenderer
{

    private Android.Views.View _cellCore;
    private Drawable _unselectedBackground;
    private bool _selected;

    protected override Android.Views.View GetCellCore(Cell item, Android.Views.View convertView, ViewGroup parent, Context context)
    {
        _cellCore = base.GetCellCore(item, convertView, parent, context);

        _selected = false;
        _unselectedBackground = _cellCore.Background;

        return _cellCore;
    }

    protected override void OnCellPropertyChanged(object sender, PropertyChangedEventArgs args)
    {
        base.OnCellPropertyChanged(sender, args);

        if (args.PropertyName == "IsSelected")
        {
            _selected = !_selected;

            if (_selected)
            {
                var extendedViewCell = sender as RRViewCell;
                _cellCore.SetBackgroundColor(extendedViewCell.SelectedItemBackgroundColor.ToAndroid());
            }
            else
            {
                _cellCore.SetBackground(_unselectedBackground);
            }
        }
    }
}

XAML:

<ctrl:RRViewCell SelectedItemBackgroundColor="{StaticResource NavigationPrimary}">

(NavigationPrimary настроен на оттенок синего).

Как я уже сказал, все работает, если никакие элементы не выбираются программно, но если я делаю:

MyList.SelectedItem = loc[0];

, это результат:

enter image description here

(разумные данные замаскированы!)

В этом случае вместо пользовательского используется цвет фона по умолчанию.

Более того, если я коснусь другого элемента, это произойдет:

enter image description here

Обратите внимание:

  • ЕслиЯ повторилy коснитесь разных элементов (кроме первого):
    • Первый элемент остается синим
    • Последний нажатый элемент имеет синий цвет, предыдущий - белый, так что я всегдау первого элемента и последнего постучанного синего цвета.
  • Если я коснусь первого элемента, он станет оранжевым и останется оранжевым при последующих нажатиях.
  • Нажатие другого элемента послеЯ нажал на первый превращает первый элемент из оранжевого в синий.

Ответы [ 2 ]

0 голосов
/ 11 октября 2019

В Android проще всего редактировать под Resources\values:

, добавить эту строку внутри styles.xml:

<style name="MainTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
     ...
   <item name="android:colorActivatedHighlight">@color/ListViewSelected</item>
    ...
</style>

, затем добавить color/ListViewSelected внутри colors.xml:

<color name="ListViewSelected">#96BCE3</color>

Недостатком является то, что после установки все списки включат этот эффект

0 голосов
/ 10 октября 2019

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

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

Я установил ListView.SelectionMode на Нет и вместо этого ListView.ItemTapped активировал мойкод выбора. Каждый из моих исходных элементов ListView имеет свойство IsSelected, которое устанавливается всякий раз, когда элемент выбирается для просмотра. Я не изменяю цвет фона ListView.Item, но вместо этого я использую BoxView с фиксированным фоновым цветом с привязкой IsVisible к IsSelected, например:

        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <Grid  RowSpacing="0" >
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="1"/>
                            <ColumnDefinition Width="60"/>
                            <ColumnDefinition Width="120"/>
                            <ColumnDefinition Width="100*"/>
                            <ColumnDefinition Width="40"/>
                            <ColumnDefinition Width="1" />
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="30*"/>
                        </Grid.RowDefinitions>
                        <BoxView Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="6" BackgroundColor="{StaticResource Primary}" IsVisible="{Binding IsSelected}" />
                        <Label   Grid.Column="1" Grid.Row="0" HorizontalTextAlignment="Center" VerticalOptions="Center" Text="{Binding Destination}"/>
                        <Label   Grid.Column="2" Grid.Row="0" HorizontalTextAlignment="Start" VerticalOptions="Center" Text="{Binding Description}"/>
                        <Label   Grid.Column="3" Grid.Row="0" HorizontalTextAlignment="End"  HorizontalOptions="End" VerticalOptions="Center" Text="{Binding ScaledValue}" FontAttributes="Bold" FontSize="Medium" BackgroundColor="{Binding StoredValueDiffers, Converter={x:StaticResource StoredDiffersConverter}}"/>
                        <Label   Grid.Column="4" Grid.Row="0" HorizontalTextAlignment="Start" VerticalOptions="Center" Text="{Binding Units}"/>
                    </Grid>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>

Поскольку BoxView объявлен первым, он находится всамый нижний слой и другие компоненты отображаются поверх него.

Я полагаю, что в вашем случае вы могли бы использовать не-логическое значение, чтобы показать, был ли выбран элемент вручную (при нажатии), программно или нет привсе, а затем конвертер выберет ваш цвет фона.

Я надеюсь, что это дает вам некоторые идеи.

...