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

MonoTouch.Dialog のカスタム セルを作成する適切な方法を提案するオンラインの Miguel De Icaza 投稿からこのコードを取得しました。

データは適切に表示されますが、長いリストがあり、すばやく上下にスクロールすると、セルが予測できないランダムな方法で場所が入れ替わります。そのため、スクロールが終了すると、行のセルが行 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重要な部分の 1 つは、UpdateCellメソッドを呼び出すことです。そうしないと、更新が完了する前に古いコンテンツが (新しく再利用されたセルに) 表示される可能性があります。それはあなたの問題を説明するかもしれません。

于 2012-07-19T12:30:13.380 に答える