1

我正在使用 Monotouch.Dialog 类来填充UITableView. 我正在使用自定义单元格,您可以在 Element 中看到获取单元格的代码如下:

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

我从 Miguel De Icaza 的在线帖子中获得了这段代码,该帖子建议了为 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();
     }
}

有谁知道我如何正确地将单元格出列并且没有滚动问题?

4

2 回答 2

1

您的代码没有显示 _dataView.Update(newData) 的作用,但我认为它不会更改单元格布局上的任何内容,而只是用新数据刷新 UI 元素。在那种情况下(我一定很生气与 Miguel 相矛盾),您应该在每次访问 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;
}
于 2014-02-26T13:27:42.830 回答
0

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

这是一个工作示例 ( BubbleCell ),您可以使用它来比较您的代码。

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

于 2012-07-19T12:30:13.380 回答