2012-07-18 52 views
1

我正在使用Monotouch.Dialog类来填充UITableView。我使用的是自定义单元格,正如你可以看到在获取细胞是如下元素的代码:Monqueouch中的DequeueReusableCell在滚动时导致单元格重新排列

public override UITableViewCell GetCell (UITableView tv) 
{ 
var cell = tv.DequeueReusableCell(_key) as FoodItemCell; 

if (cell == null) 
    cell = new FoodItemCell(_foodItem, _key); 
else 
    cell.UpdateCell(_foodItem); 

return cell; 
} 

我从米格尔德伊卡萨岗位网上暗示适当的方式来创建自定义得到这个代码MonoTouch.Dialog的单元格。

数据显示正确,但是当我有一个很长的列表并且我快速上下滚动时,单元格会以随机不可预知的方式交换位置。因此,当我完成滚动时,行中的单元格可能会在第4行中结束。

当我使用下面的代码时,这个问题已经解决了,但正如你所看到的,我没有将单元出队,这可能会产生内存问题。

private FoodItemCell _currentCell; 

public override UITableViewCell GetCell (UITableView tv) 
{ 
    if(_currentCell == null) 
    { 
     _currentCell = new FoodItemCell(_foodItem, _key); 
     return _currentCell; 
    } 
    else 
    { 
     return _currentCell; 
    } 
} 

下面是完整的代码:

public class FoodItemElement: Element 
{ 
    private static NSString _key = new NSString ("foodItemCell"); 
    private FoodItem _foodItem; 
    public event EventHandler<ElementClickedEventArgs> ElementClicked; 


    public FoodItemElement(FoodItem foodItem): base(null) 
    { 
     _foodItem = foodItem; 
    } 

    public override UITableViewCell GetCell (UITableView tv) 
    { 
     var cell = tv.DequeueReusableCell(_key) as FoodItemCell; 

     if (cell == null) 
      cell = new FoodItemCell(_foodItem, _key); 
     else 
      cell.UpdateCell(_foodItem); 

     return cell; 
    } 
} 


public class FoodItemCell: UITableViewCell 
{  
    private FoodItemCellDataView _dataView; 
    private FoodItem _foodItem; 

    public FoodItemCell(FoodItem data, NSString key) : base (UITableViewCellStyle.Default, key) 
    { 
     _foodItem = (FoodItem)data; 
     _dataView = new FoodItemCellDataView(_foodItem); 

     ContentView.Add(_dataView); 
     ConstructCell(); 
    } 

    public override void LayoutSubviews() 
    { 
     base.LayoutSubviews(); 
     _dataView.Frame = ContentView.Bounds; 
     _dataView.SetNeedsDisplay(); 
    } 

    /// <summary> 
    /// Updates the cell. 
    /// </summary> 
    public void UpdateCell(FoodItem newData) 
    { 
     _dataView.Update(newData); 
     SetNeedsLayout(); 
    } 

    /// <summary> 
    /// Constructs the cell. 
    /// </summary> 
    private void ConstructCell() 
    { 
     //This prevents the default blue color when selecting the cell. 
     //this.SelectionStyle = UITableViewCellSelectionStyle.None; 
     //this.ContentView.BackgroundColor = UIColor.White; 

     var lblFoodItemName = new UILabel(); 
     lblFoodItemName.Frame = new System.Drawing.RectangleF(4,2,270,20); 
     lblFoodItemName.TextColor = UIColor.Black; 
     lblFoodItemName.Font = Fonts.H3; 
     lblFoodItemName.BackgroundColor = UIColor.Clear; 
     lblFoodItemName.Text = _foodItem.Name; 

     var lblCalories = new UILabel(); 
     lblCalories.Frame = new System.Drawing.RectangleF(15,22,75,20); 
     lblCalories.TextColor = UIColor.Black; 
     lblCalories.Font = Fonts.Small; 
     lblCalories.BackgroundColor = UIColor.Clear; 
     lblCalories.Text = "CAL - " + _foodItem.CaloriesRounded.ToString(); 

     var lblPortion = new UILabel(); 
     lblPortion.Frame = new System.Drawing.RectangleF(95,22,190,20); 
     lblPortion.TextColor = UIColor.Black; 
     lblPortion.Font = Fonts.Small; 
     lblPortion.BackgroundColor = UIColor.Clear; 
     lblPortion.Text = "Portion - " + _foodItem.Portion.ToString(); 

     this.ContentView.AddSubview(lblFoodItemName); 
     this.ContentView.AddSubview(lblCalories); 
     this.ContentView.AddSubview(lblPortion); 

     Accessory = UITableViewCellAccessory.DisclosureIndicator; 
    } 
} 


// I create a view that renders my data, as this allows me to reuse 
// the data rendering outside of a UITableViewCell context as well. 
public class FoodItemCellDataView : UIView { 

    public FoodItemCellDataView(FoodItem foodItem) 
    { 
      Update (foodItem); 
    } 

    // Public method, that allows the code to externally update 
    // what we are rendering. 
    public void Update(FoodItem foodItem) 
    { 
      SetNeedsDisplay(); 
    } 
} 

有没有人有一个想法,我怎么能正确地出列的细胞,而不必滚动问题?

+0

它看起来像重用呢不能正常工作(例如,不更新新的或重新使用的单元格)。你能向我们展示(编辑你的问题)你的'UpdateCell'代码和'_key'是如何定义的(.ctor也可以证明是有用的)。 – poupou 2012-07-18 23:05:52

回答

0

很难确定为什么没有看到更多的源代码(请参阅我的评论)。

下面是一个可用于比较代码的工作示例(BubbleCell)。

一个重要的部分是在您的UpdateCell方法中调用SetNeedsLayout。否则,在刷新完成之前,可能会出现旧的内容(在新的重用单元格中)。这可以解释你的问题。

+0

你好,谢谢你的回复。我相信我正在做你的建议。请看上面的完整代码。我更新了原始帖子。 – Apollonas 2012-07-24 19:33:41

+0

任何人有任何想法? – Apollonas 2012-10-05 16:55:10

1

你的代码没有显示_dataView.Update(newData)是做什么的,但我正在使用它并没有改变单元布局上的任何东西,而只是用新数据刷新UI元素。在这种情况下,(我一定是疯了矛盾米格尔),你应该到GetCell每次访问时被调用cell.UpdateCell(_foodItem)单元格是否出队还是新的,所以:

public override UITableViewCell GetCell (UITableView tv) 
{ 
var cell = tv.DequeueReusableCell(_key) as FoodItemCell; 

if (cell == null) 
    cell = new FoodItemCell(_foodItem, _key); 
// else <- I would remove this 
    cell.UpdateCell(_foodItem); 

return cell; 
} 
相关问题