2017-06-27 9 views
0

UITableViewでスクロールすると、単一のUITableViewCellのUIImageViewサブビューが他のセル間を移動します。この問題が発生するまでには時間がかかりません。リストの一番下までスクロールするだけで、応答インジケータ(UIImageView)が異なるセル間を移動します。ここでUITableViewCell UIImageViewは同じテーブルの異なるセル間を移動します

は私のカスタムテーブルビュークラスである:ここで

/// <summary> 
/// Control for interacting with comments 
/// </summary> 
public sealed class CommentView : UITableView 
{ 
    /// <summary> 
    /// Initializes with a data source 
    /// </summary> 
    /// <param name="source">Data source</param> 
    /// <param name="useSeparators">Whether separators should be used between comments</param> 
    public CommentView(UITableViewSource source, bool useSeparators) 
    { 
     AllowsSelection = true; 
     SeparatorStyle = useSeparators ? 
      UITableViewCellSeparatorStyle.SingleLine : 
      UITableViewCellSeparatorStyle.None; 
     Source = source; 
     RowHeight = AutomaticDimension; 
     EstimatedRowHeight = 100; 
    } 
} 

は私のデータソース内のgetcellをする方法である:

/// <summary> 
/// Gets the cell in the table view at the index given 
/// </summary> 
/// <param name="tableView">Table view to get cell from</param> 
/// <param name="indexPath">Index to get cell at</param> 
/// <returns>Cell at the index specified</returns> 
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath) 
{ 
    var comment = Data[indexPath.Row]; 
    var cell = tableView.DequeueReusableCell(CellId) as CommentCell; 

    // ReSharper disable once PossibleNullReferenceException 
    cell.LineCount = CommentLineCount; 
    cell.HasReplies = comment.Replies.Count > 0; 
    cell.UpdateCell(comment); 
    cell.DrawIndicator(comment); 
    if (!comment.IsReply) 
    { 
     DrawAccessories(comment, cell); 
    } 
    cell.UpdateConstraints(); 

    return cell; 
} 

そして、ここでは完全な 'CommentCell' クラスです:

using App.Common.Models; 
using App.iOS.Utilities; 
using CoreGraphics; 
using Foundation; 
using System; 
using UIKit; 
using Xamarin.Forms; 
using Xamarin.Forms.Platform.iOS; 

namespace App.iOS.Views.Controls 
{ 
    /// <summary> 
    /// Custom cell control for displaying a single comment 
    /// </summary> 
    public sealed class CommentCell : UITableViewCell 
    { 
     private const string CustomCommentCss = 
      "<style>*{{font-family:{0};font-size:{1};color:{2};}}span{{font- 
weight:600;}}</style>"; 
     private static readonly CGRect ReplyIconDimensions = new CGRect(6, 6, 12, 9); 
     private readonly UILabel _authorLabel; 
     private readonly UILabel _commentLabel; 
     private readonly UILabel _dateLabel; 
     private readonly UIFont _font; 

    private UIView _indicator; 
    private ReplyCountIndicatorView _replyCountIndicator; 

    public CommentCell(IntPtr p) : base(p) 
    { 
     SelectionStyle = UITableViewCellSelectionStyle.None; 
     SeparatorInset = UIEdgeInsets.Zero; 
     LayoutMargins = UIEdgeInsets.Zero; 

     var textColor = Globals.ColorDark; 

     _font = UIFont.FromName(Globals.FontSanFranLight, Globals.FontSizeBody); 
     _authorLabel = new UILabel 
     { 
      Font = UIFont.FromName(Globals.FontSanFranSemiBold, Globals.FontSizeBody), 
      Lines = 1, 
      LineBreakMode = UILineBreakMode.TailTruncation, 
      TextColor = textColor 
     }; 
     _commentLabel = new UILabel 
     { 
      Font = _font, 
      LineBreakMode = UILineBreakMode.TailTruncation, 
      TextColor = textColor 
     }; 
     _dateLabel = new UILabel 
     { 
      Font = UIFont.FromName(Globals.FontSanFranLight, Globals.FontSizeSmall), 
      TextColor = Globals.ColorDisabled 
     }; 

     ContentView.AddSubviews(_authorLabel, _commentLabel, _dateLabel); 
    } 

    /// <summary> 
    /// Sets whether this cell has replies associated with it 
    /// </summary> 
    public bool HasReplies { private get; set; } 

    /// <summary> 
    /// Sets the number of lines in the comment field 
    /// </summary> 
    public int LineCount { set { _commentLabel.Lines = value; } } 

    /// <summary> 
    /// Updates the constraints of the subviews 
    /// </summary> 
    public override void UpdateConstraints() 
    { 
     base.UpdateConstraints(); 
     _authorLabel.SetContentCompressionResistancePriority(1000, UILayoutConstraintAxis.Vertical); 
     _commentLabel.SetContentCompressionResistancePriority(1000, UILayoutConstraintAxis.Vertical); 
     _dateLabel.SetContentCompressionResistancePriority(1000, UILayoutConstraintAxis.Vertical); 
     _replyCountIndicator?.SetContentCompressionResistancePriority(1000, UILayoutConstraintAxis.Vertical); 

     var leftMargin = AnnotationIndicator.Size.Width + 2 * Globals.MarginGrid; 

     if (_replyCountIndicator != null && HasReplies) 
     { 
      ContentView.ConstrainLayout(() => 
       _authorLabel.Frame.Top == ContentView.Frame.Top + Globals.MarginGrid && 
       _authorLabel.Frame.Left == ContentView.Frame.Left + leftMargin && 
       _authorLabel.Frame.Right == ContentView.Frame.Right - Globals.MarginGrid && 

       _commentLabel.Frame.Top == _authorLabel.Frame.Bottom + Globals.MarginGrid/4 && 
       _commentLabel.Frame.Left == _authorLabel.Frame.Left && 
       _commentLabel.Frame.Right == _authorLabel.Frame.Right && 

       _dateLabel.Frame.Top == _commentLabel.Frame.Bottom + Globals.MarginGrid/4 && 
       _dateLabel.Frame.Left == _authorLabel.Frame.Left && 
       _dateLabel.Frame.Right == _authorLabel.Frame.Right && 

       _replyCountIndicator.Frame.Top == _dateLabel.Frame.Bottom + Globals.MarginGrid && 
       _replyCountIndicator.Frame.Left == _dateLabel.Frame.Left && 
       _replyCountIndicator.Frame.Width == Globals.SmallToolbarItemSize && 
       _replyCountIndicator.Frame.Height == Globals.SmallToolbarItemSize && 
       _replyCountIndicator.Frame.Bottom == ContentView.Frame.Bottom - Globals.MarginGrid); 
     } 
     else 
     { 
      ContentView.ConstrainLayout(() => 
       _authorLabel.Frame.Top == ContentView.Frame.Top + Globals.MarginGrid && 
       _authorLabel.Frame.Left == ContentView.Frame.Left + leftMargin && 
       _authorLabel.Frame.Right == ContentView.Frame.Right - Globals.MarginGrid && 

       _commentLabel.Frame.Top == _authorLabel.Frame.Bottom + Globals.MarginGrid/4 && 
       _commentLabel.Frame.Left == _authorLabel.Frame.Left && 
       _commentLabel.Frame.Right == _authorLabel.Frame.Right && 

       _dateLabel.Frame.Top == _commentLabel.Frame.Bottom + Globals.MarginGrid/4 && 
       _dateLabel.Frame.Left == _authorLabel.Frame.Left && 
       _dateLabel.Frame.Right == _authorLabel.Frame.Right && 
       _dateLabel.Frame.Bottom == ContentView.Frame.Bottom - Globals.MarginGrid); 
     } 
    } 

    /// <summary> 
    /// Updates the contents of the cell 
    /// </summary> 
    /// <param name="comment">Comment to update cell for</param> 
    public void UpdateCell(Comment comment) 
    { 
     // update the comment author 
     _authorLabel.Text = string.IsNullOrWhiteSpace(comment.CreatedByUser.FirstName) && 
      string.IsNullOrWhiteSpace(comment.CreatedByUser.LastName) ? 
       comment.CreatedByUser.Email : 
       $"{comment.CreatedByUser.FirstName} {comment.CreatedByUser.LastName}"; 

     // update the text 
     var attr = new NSAttributedStringDocumentAttributes { DocumentType = NSDocumentType.HTML }; 
     var nsError = new NSError(); 

     // TODO: This is where emoji rendering goes wrong 
     var text = comment.Text.Insert(0, string.Format(CustomCommentCss, 
      _font.FontDescriptor.Name, _font.PointSize, 
      ColorConverter.ConvertToHex(_commentLabel.TextColor))); 
     var mutableString = new NSMutableAttributedString(new NSAttributedString(
      text, attr, ref nsError)); 
     var mutableParagraph = new NSMutableParagraphStyle 
     { 
      Alignment = UITextAlignment.Left, 
      LineBreakMode = UILineBreakMode.TailTruncation 
     }; 
     mutableString.AddAttribute(UIStringAttributeKey.ParagraphStyle, mutableParagraph, 
      new NSRange(0, mutableString.Length)); 
     mutableString.AddAttribute(UIStringAttributeKey.StrokeColor, Globals.ColorDark, 
      new NSRange(0, mutableString.Length)); 
     _commentLabel.AttributedText = mutableString; 

     // update the timestamp 
     var localTime = TimeZone.CurrentTimeZone.ToLocalTime(
      comment.LastModifiedDateTime).ToString("g"); 
     _dateLabel.Text = comment.LastModifiedDateTime == comment.CreatedDateTime ? 
      localTime : $"Modified {localTime}"; 
    } 

    /// <summary> 
    /// Draws the appropriate type of indicator next to the author's name 
    /// </summary> 
    /// <param name="comment">Comment to draw indicator for</param> 
    public void DrawIndicator(Comment comment) 
    { 
     // if we've already drawn the indicator and 
     // the comment has no annotation associated with it 
     _indicator?.RemoveFromSuperview(); 

     // if the comment havs an annotation associated with it, 
     // draw the annotation indicator 
     if (comment.Annotation != null) 
     { 
      _indicator = new AnnotationIndicator 
      { 
       Location = new CGPoint(Globals.MarginGrid, Globals.MarginGrid), 
       Number = comment.Annotation.AnnotationNumber, 
       FillColor = Color.FromHex(comment.Annotation.FillColorValue).ToUIColor(), 
       TextColor = Color.FromHex(comment.Annotation.TextColorValue).ToUIColor() 
      }; 
      ContentView.AddSubview(_indicator); 
     } 

     // otherwise, draw the general comment indicator 
     else 
     { 
      var dim = comment.IsReply ? ReplyIconDimensions : 
       new CGRect(0, 0, AnnotationIndicator.Size.Width, AnnotationIndicator.Size.Height); 
      _indicator = new UIImageView 
      { 
       ContentMode = UIViewContentMode.ScaleAspectFit, 
       Frame = new CGRect(Globals.MarginGrid + dim.X, Globals.MarginGrid + dim.Y, dim.Width, dim.Height), 
       Image = comment.IsReply ? UIImage.FromFile("reply.png") : 
        UIImage.FromFile("general_annotation_indicator.png") 
      }; 
      ContentView.AddSubview(_indicator); 
     } 
    } 

    /// <summary> 
    /// Draws the reply count indicator 
    /// </summary> 
    /// <param name="comment">Comment to draw indicator for</param> 
    public void DrawReplyCountIndicator(Comment comment) 
    { 
     if (_replyCountIndicator != null) 
     { 
      _replyCountIndicator.RemoveFromSuperview(); 
      _replyCountIndicator = null; 
     } 
     _replyCountIndicator = new ReplyCountIndicatorView(comment.Replies.Count); 
     ContentView.AddSubview(_replyCountIndicator); 
    } 
} 
} 

ここにいくつかのスクリーンショットがあります: Normal The reply indicator has now moved to another cell

答えて

0

DequeueReusableCellは、キャッシュから既に存在するバージョンのセルを返します。以前の使用によるデータがすでに格納されている可能性があります。したがって、現在のセルの状態を反映するために、データフィールドなどが適切にリセットされていることを確認する責任があります。

+0

すべてが_replyCountIndicatorを除いて正しくリセットされるように見えます。 CommentCellクラスのDrawReplyCountIndicatorメソッドに問題はありますか?インジケータの具体的除去: – kformeck

+0

(!_replyCountIndicator = NULL)であれば{ _replyCountIndicator.RemoveFromSuperview()。 _replyCountIndicator = null;} – kformeck

+0

あなたは実際にデバッガでそれを実行して、期待していることを確認する必要があります – Jason

関連する問題