2017-03-16 47 views
2

我正在使用Xamarin.Forms項目中的Accordion ListView。這意味着您可以單擊ListView中的類別標題,該類別標題將展開或摺疊它下面的子項。Xamarin.Forms - 更新ItemSource時,ViewCell中的圖像閃爍

有兩個圖像,並在每個類別標題標題所以我用一個ViewCell。問題是當輕擊類別並顯示子項時,類別標題ViewCell上的圖像會閃爍。

我有我使用來完成手風琴功能的兩個觀察集合。一個包含每個父項(MenuItemGroup)和子項(MenuItem)的項目,以及僅包含應顯示的MenuItem的項目。每次點擊標題時,會觸發一個事件,獲取所選類別的索引並切換其屬性(顯示或隱藏其子項)。然後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; 
    } 

這裏是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 
     }; 

無論是groupIconstateIcon圖像閃光燈時ListView控件的ItemSource被更新。任何人都可以提供任何見解如何解決這個問題?謝謝!

,如果你認爲這將有助於我可以張貼MenuItemGroupMenuItem類。

回答

0

我試圖用圖像更新我的列表視圖時遇到了類似的問題。我在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++); 
    } 
    } 
} 

乾杯。

+0

感謝您的回答。你能否提供任何演示如何在不更新'groupImage'的情況下更新列表視圖的示例代碼。每個Menu Item Group Header中的'groupImage'是不同的,所以綁定SouceProperty是我知道如何設置每個圖像的唯一方法。 – cfly24

+0

我已經給出了可以做什麼的一個要點。根據需要進行修改,並檢查這是否可以防止閃爍。 –

+0

一旦我實現代碼只更新將改變的部分,只剩下一個小閃爍。一旦我添加了圖像的寬度和高度,小閃爍消失了。謝謝! – cfly24

0

面對同樣的問題..令人驚訝的我已經把那個被通知需要的Device.BeginInvokeOnMainThread內部的更新該控件的代碼之後完全disapeared閃爍。