【问题标题】:Xamarin.Forms - Image inside ViewCell flashes when updating the ItemSourceXamarin.Forms - 更新 ItemSsource 时 ViewCell 内的图像闪烁
【发布时间】:2017-03-16 17:10:03
【问题描述】:

我正在开发 Xamarin.Forms 项目中的 Accordion ListView。这意味着您可以单击 ListView 中的 Category Headings,这将展开或折叠其下方的子项。

每个类别标题中有两个图像和一个标题,所以我使用的是 ViewCell。问题在于,当点击类别并显示子项时,类别标题 ViewCell 上的图像会闪烁。

我有两个可观察的集合用于完成 Accordion 功能。一个包含每个父 (MenuItemGroup) 和子 (MenuItem) 项目,一个仅包含应显示的 MenuItem。每次点击标题时,都会触发一个事件,该事件会获取所选类别的索引并切换它的Expanded 属性(显示或隐藏它的子级)。然后调用UpdateListContent()方法刷新ListViewItemSource:

    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;
    }

这是 DateTemplate 和图像绑定:

        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
        };

更新 ListView ItemSource 时,groupIconstateIcon 图像都会闪烁。谁能提供有关如何解决此问题的任何见解?谢谢!

如果您认为有帮助,我可以发布 MenuItemGroupMenuItem 课程。

【问题讨论】:

    标签: c# listview xamarin xamarin.forms


    【解决方案1】:

    当我尝试使用图像更新列表视图时,我遇到了类似的问题。我在 Android 中看到图像闪烁。这通常是因为加载图像的延迟。

    尝试固定图像的高度和宽度。如果这不起作用,则在更新列表内容时,仅更新所需的图像和文本值,这样所有图像都不需要再次加载。

    如果你真的需要,我可以提供一个示例代码,因为你只需要洞察力。

    所以你可以这样做: 将您的 Listview.Itemsource 与 _expandedGroups 绑定,这样您就无需在每次展开/折叠时设置 ItemsSource 属性。这会刷新您的列表,从而刷新您的图像。

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

    在你的更新方法中: - 传递你的 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++);   
       }
      }
    }
    

    干杯。

    【讨论】:

    • 感谢您的回答。您能否提供任何示例代码来演示如何在不更新groupImage 的情况下更新列表视图。 groupImage 在每个菜单项组标题中都不同,因此绑定 SouceProperty 是我知道如何设置每个图像的唯一方法
    • 我已经给出了可以做什么的要点。根据需要进行修改并检查这是否可以防止闪烁。
    • 在我实现代码以仅更新将要更改的部分后,只剩下一点点闪烁。一旦我添加了图像宽度和高度,小闪烁就消失了。谢谢!
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2014-06-09
      • 1970-01-01
      • 1970-01-01
      • 2015-12-17
      • 2011-10-02
      • 2012-05-08
      • 1970-01-01
      • 2015-03-18
      • 1970-01-01
      相关资源
      最近更新 更多