简体   繁体   中英

Xamarin.Forms - Image inside ViewCell flashes when updating the ItemSource

I am working on an Accordion ListView in a Xamarin.Forms project. This means that you can click on Category Headings in a ListView, which will expand or collapse the children beneath it.

There are two images and a title in each Category Heading so I am using a ViewCell. The issue is that when a Category is tapped and the children are shown, the images on the Category Heading ViewCell flash.

I have two observable collections that I am using to accomplish the Accordion Functionality. One that contains every parent ( MenuItemGroup ) and child ( MenuItem ) item, and one that only includes the MenuItem 's that should be shown. Every time a header is tapped, an event fires that gets the selected Index of the Category and toggles it's Expanded property (showing or hiding it's children). Then the UpdateListContent() method is called to refresh the ListView ItemSource:

    private ObservableCollection<MenuItemGroup> _allGroups;
    private ObservableCollection<MenuItemGroup> _expandedGroups;

    private void OnHeaderTapped(object sender, EventArgs e)
    {
        var selectedIndex = _expandedGroups.IndexOf(
            ((MenuItemGroup)((StackLayout)sender).Parent.BindingContext));

        _allGroups[selectedIndex].Expanded = !_allGroups[selectedIndex].Expanded;

        UpdateListContent();
    }

    private void UpdateListContent()
    {
        _expandedGroups = new ObservableCollection<MenuItemGroup>();

        foreach (var group in _allGroups)
        {
            var newGroup = new MenuItemGroup(group.Title, group.CategoryIcon, group.Expanded);

            if (group.Count == 0)
            {
                newGroup.Expanded = null;
            }

            if (group.Expanded == true)
            {
                foreach (var menuItem in group)
                {
                    newGroup.Add(menuItem);
                }
            }
            _expandedGroups.Add(newGroup);
        }

        _menuItemListView.ItemsSource = _expandedGroups;
    }

Here is the DateTemplate and Image Binding:

        var menuItemGroupTemplate = new DataTemplate(() =>
        {
            var groupImage = new Image();
            groupImage.SetBinding<MenuItemGroup>(Image.SourceProperty, i => i.CategoryIcon);

            var titleLabel = new Label
            {
                TextColor = Color.White,
                VerticalTextAlignment = TextAlignment.Center,
                VerticalOptions = LayoutOptions.Center,
                FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label))
            };
            titleLabel.SetBinding<MenuItemGroup>(Label.TextProperty, t => t.Title);

            var stateIconImage = new Image
            {
                HorizontalOptions = LayoutOptions.EndAndExpand
            };
            stateIconImage.SetBinding<MenuItemGroup>(Image.SourceProperty, i => i.IconState);

            var menuItemGroupStackLayout = new StackLayout
            {
                BackgroundColor = Color.FromHex("40474d"),
                HorizontalOptions = LayoutOptions.FillAndExpand,
                VerticalOptions = LayoutOptions.FillAndExpand,
                Orientation = StackOrientation.Horizontal,
                Padding = new Thickness(10 ,0, 20, 0),
                Children = { groupImage, titleLabel, stateIconImage }
            };

            var tapGestureRecognizer = new TapGestureRecognizer();

            tapGestureRecognizer.Tapped += OnHeaderTapped;
            tapGestureRecognizer.CommandParameter = menuItemGroupStackLayout.BindingContext;
            menuItemGroupStackLayout.GestureRecognizers.Add(tapGestureRecognizer);

            var menuItemGroupViewCell = new ViewCell
            {
                View = menuItemGroupStackLayout,
                Height = 63.0
            };

            return menuItemGroupViewCell;
        });

        _menuItemListView = new ListView
        {
            RowHeight = 55,
            IsGroupingEnabled = true,
            ItemTemplate = menuItemTemplate,
            GroupHeaderTemplate = menuItemGroupTemplate,
            SeparatorColor = Color.FromHex("40474d"),
            HasUnevenRows = true
        };

Both the groupIcon and stateIcon images flash when the ListView ItemSource is updated. Can anyone offer any insight into how to fix this issue? Thanks!

I can post the MenuItemGroup and MenuItem classes if you think it would be helpful.

I faced a similar problem when I tried to update my listview with images. I saw image flicker in Android. It is usually because of the delay in loading image.

Try fixing the image height and width. If that doesn't work, while updating the list content, update only the required images and textual values, so that all images need not load again.

I can provide a sample code if you really need it, since you only needed an insight.

So here's what you can do : Bind your Listview.Itemsource with _expandedGroups, so that you need not set the ItemsSource property everytime you expand/collapse. This refreshes your list and hence your images.

private ObservableCollection<MenuItemGroup> _expandedGroups;
public ObservableCollection<MenuItemGroup> ExpandedGroups
{
 get
 {
  return _expandedGroups;
 }
 set
 {
  if(value!=null) _expandedGroups = value;
  OnPropertyChanged("ExpandedGroups");
 }
}

And in your updation method : - Pass your allListSelection

UpdateListContent(_allGroups[SelectedIndex], SelectedIndex);
private void UpdateListContent(MenuItemGroup group, int index)
{
 if(group.Expanded)
 {
  foreach (var menuItem in group)
   {
     ExpandedGroup.Insert(index++, menuItem);
   }
 }
 else
 {
  foreach (var menuItem in group)
   {
     ExpandedGroup.Remove(menuItem); //Can also use ExpandedGroup.RemoveAt(index++);   
   }
  }
}

Cheers.

面对同样的问题..令人惊讶的是,在我将通知控件的代码放在Device.BeginInvokeOnMainThread中需要更新之后,闪烁完全消失了。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM