简体   繁体   English

Xamarin.Forms - 更新ItemSource时,ViewCell内的图像闪烁

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

I am working on an Accordion ListView in a Xamarin.Forms project. 我正在使用Xamarin.Forms项目中的Accordion ListView。 This means that you can click on Category Headings in a ListView, which will expand or collapse the children beneath it. 这意味着您可以单击ListView中的“类别标题”,这将扩展或折叠其下的子项。

There are two images and a title in each Category Heading so I am using a ViewCell. 每个类别标题中有两个图像和一个标题,因此我使用的是ViewCell。 The issue is that when a Category is tapped and the children are shown, the images on the Category Heading ViewCell flash. 问题是,当点击类别并显示子项时,类别标题ViewCell上的图像会闪烁。

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. 包含每个父项( MenuItemGroup )和子项( MenuItem )项的项,以及仅包含应显示的MenuItem项的项。 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). 每次点击标题时,都会触发一个事件,该事件将获取所选类别的索引,并切换它的Expanded属性(显示或隐藏它的子项)。 Then the UpdateListContent() method is called to refresh the ListView ItemSource: 然后调用UpdateListContent()方法来刷新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: 这是DateTemplate和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. 无论是groupIconstateIcon当ListView控件的ItemSource被更新的图像闪烁。 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. 如果您认为它有用,我可以发布MenuItemGroupMenuItem类。

I faced a similar problem when I tried to update my listview with images. 当我尝试使用图像更新listview时,我遇到了类似的问题。 I saw image flicker in Android. 我在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. 这就是你可以做的事情:将Listview.Itemsource绑定到_expandedGroups,这样每次展开/折叠时都不需要设置ItemsSource属性。 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 在您的更新方法中: - 传递您的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中需要更新之后,闪烁完全消失了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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