菜鸟教程小白 发表于 2022-12-12 14:59:49

iOS : Expandable list view not drawing newly added control


                                            <p><p>我正在尝试使用带有 MvvmCross 的 Xamarin 在 iOS 中创建一个可扩展的 ListView 。</p>

<p>场景是我有一个 ListView ,当 ListView 中的一行被选中时,它会展开(动画)以显示一个 Collection View ,通过延迟加载加载。</p>

<p>这是我目前的代码:</p>

<p><strong>适配器:</strong> </p>

<pre><code>public class MercatoAnimatedExpandableTableSource : MvxTableViewSource
{
    private readonly string _key;
    private readonly List&lt;object&gt; items;
    private Dictionary&lt;object, bool&gt; expandableState = new Dictionary&lt;object, bool&gt;();

    public MercatoAnimatedExpandableTableSource(UITableView tableView, IEnumerable&lt;object&gt; items, UINib nib, string key)
      : base(tableView)
    {
      _key = key;
      this.items = items.ToList();
      this.items.ForEach(x =&gt; expandableState = true);
      tableView.RegisterNibForCellReuse(nib, key);
    }

    protected override UITableViewCell GetOrCreateCellFor(UITableView tableView, NSIndexPath indexPath, object item)
    {
      var cell = tableView.DequeueReusableCell(_key);

      cell.Frame = new RectangleF(cell.Frame.X, cell.Frame.Y, cell.Frame.Width, GetHeightForRow(tableView, indexPath));

      return cell;
    }

    public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
    {
      base.RowSelected(tableView, indexPath);

      var isExpanded = expandableState];

      expandableState] = !isExpanded;

      var row = this.GetCell(tableView, indexPath);

      (row as FamilysubgroupViewCell).ExpandCells();

      tableView.ReloadRows(new[] { indexPath }, UITableViewRowAnimation.Automatic);
    }

    public override float GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
    {
      var isExpanded = expandableState];
      if (isExpanded)
      {
            return 25;
      }

      return 400;
    }

    protected override object GetItemAt(NSIndexPath indexPath)
    {
      return items;
    }
}
</code></pre>

<p><strong>单元格:</strong> </p>

<pre><code>    public FamilySubgroupViewCell (IntPtr handle) : base (handle)
    {
      this.DelayBind(() =&gt;
      {
            this.FamilyCollectionViewContainer.BackgroundColor = UIColor.Blue;
            var bindingset = this.CreateBindingSet&lt;FamilySubgroupViewCell, FamilySubTypeViewModel&gt;();
            bindingset.Bind(this.FamilyGroupTitleLabel).To(x =&gt; x.FamilySubType.FamilySubGroupDescription);
            bindingset.Bind(this.FamilyGroupDescLabel).To(x =&gt; x.FamilySubType.FamilySubGroupDetail);
            bindingset.Apply();
      });

    }

    public void ExpandCells(Action onUpdate)
    {
      var context = this.DataContext as FamilySubTypeViewModel;
      context.PopulateAndRun(() =&gt;
      {
            Debug.WriteLine(&#34;Populating Models complete : now showing cells&#34;);
            var collection = new FamilySubGroupModelsCollection();
            collection.ViewModel = context;
            Debug.WriteLine(&#34;FamilySubGroupCell : Showing {0} Items&#34;, context.FamilyModels.Count);

            this.FamilyCollectionViewContainer.Add(collection.View);

            if (onUpdate != null) onUpdate();
      });
    }
</code></pre>

<p><strong>问题</strong></p>

<p>因此,当一个单元格被选中时,它会翻转 'isExpanded' 属性,赋予它一个新的高度 - 效果很好。然后向该单元格发送一条消息以“扩展”该单元格,然后加载一个新集合并将其添加到 View 中(通过 View 导出)。</p>

<p>但是,集合永远不会在 View 上重新呈现。它填充得很好,添加到 View 中,但它在新扩展的单元格上实际上是不可见的。如果我在 DelayBind() 方法中最初创建单元格时加载它(即 - 没有延迟加载),那么它可以正常工作。</p>

<p>尝试过重绘单元格之类的方法</p>

<pre><code>this.Draw(this.Bounds);
</code></pre>

<p>将集合添加到 View 后,但无济于事。</p>

<p>我做错了什么?</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>感觉这段代码可能会混淆你的显示:</p>

<pre><code>    var row = this.GetCell(tableView, indexPath);
    (row as FamilysubgroupViewCell).ExpandCells();
    tableView.ReloadRows(new[] { indexPath }, UITableViewRowAnimation.Automatic);
</code></pre>

<p>这是做什么的:</p>

<ul>
<li>获取当前单元格并告诉它展开</li>
<li>然后要求表格重新加载行(此时可能会使用不同的单元格实例)。</li>
</ul>

<p>我也担心这行:</p>

<pre><code>    var context = this.DataContext as FamilySubTypeViewModel;
</code></pre>

<p>会将您的单元格子显示链接到当前 View 模型 - 如果单元格被重复使用(给定新的 View 模型),这不会更新。</p>

<p>解决这两个问题的一种快速(而且只是稍微有点脏)的方法是将 <code>GetOrCreateCellFor</code> 的覆盖更改为:</p>

<pre><code>protected override UITableViewCell GetOrCreateCellFor(UITableView tableView, NSIndexPath indexPath, object item)
{
    var cell = tableView.DequeueReusableCell(_key);

    cell.Frame = new RectangleF(cell.Frame.X, cell.Frame.Y, cell.Frame.Width, GetHeightForRow(tableView, indexPath));

    ((MyCellType)cell).ShowExpandedState(expandableState]);

    return cell;
}
</code></pre>

<p><code>ShowExpandedState(bool)</code> 可以在重用后重置单元格的展开区域。</p>

<hr/>

<p>其他选项:</p>

<ul>
<li>除此之外,您可以简单地为展开行和非展开行返回不同的单元格类型? </li>
<li>或者您可以将展开/未展开的信息放在 Cell 的 ViewModel 中,以便它可以数据绑定(bind)到该展开状态并更新它自己的布局? (不过,您仍然需要一些机制来告诉表格大小变化)</li>
</ul>

<hr/>

<p>开启:</p>

<pre><code>this.Draw(this.Bounds);
</code></pre>

<p>我并不感到惊讶这不起作用 - 通常你必须鼓励系统重绘 View- 使用诸如 <code>SetNeedsDisplay</code> 之类的东西(有时在子更改后 <code>SetNeedsLayout</code> 也是)</p></p>
                                   
                                                <p style="font-size: 20px;">关于iOS : Expandable list view not drawing newly added control,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/19091776/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/19091776/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: iOS : Expandable list view not drawing newly added control