View height constraints are not set correctly as I scroll UICollectionView up and down

懵懂的女人 提交于 2019-12-20 05:49:13

问题


I'm trying to decide view heights based on a model property, but as UICollectionView is scrolled up and down, incorrect heights are assigned to visible cells. It seems that setting a HeightAnchor in GetCell (i.e. cellForItemAtIndexPath) does not work. How can I make this work?

using CoreGraphics;
using Foundation;
using System;
using System.Collections.Generic;
using UIKit;

namespace App2
{
    public partial class ViewController : UIViewController
    {
        private UICollectionView _collectionView;

        public ViewController (IntPtr handle) : base (handle)
        {
        }

        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();

            InitializeCollectionView();
        }

        private void InitializeCollectionView()
        {
            _collectionView = new UICollectionView(View.Frame, new UICollectionViewCompositionalLayout(GetSection()))
            {
                DataSource = new CustomUICollectionViewDataSource(),
                TranslatesAutoresizingMaskIntoConstraints = false
            };

            _collectionView.RegisterClassForCell(typeof(CustomUICollectionViewCell), "CustomUICollectionViewCell");

            View.AddSubview(_collectionView);

            NSLayoutConstraint.ActivateConstraints(new[]
            {
                _collectionView.TopAnchor.ConstraintEqualTo(View.SafeAreaLayoutGuide.TopAnchor),
                _collectionView.BottomAnchor.ConstraintEqualTo(View.SafeAreaLayoutGuide.BottomAnchor),
                _collectionView.LeftAnchor.ConstraintEqualTo(View.SafeAreaLayoutGuide.LeftAnchor),
                _collectionView.RightAnchor.ConstraintEqualTo(View.SafeAreaLayoutGuide.RightAnchor)
            });
        }

        private static NSCollectionLayoutSection GetSection()
        {
            var size = NSCollectionLayoutSize.Create(NSCollectionLayoutDimension.CreateFractionalWidth(1), NSCollectionLayoutDimension.CreateEstimated(50));
            var item = NSCollectionLayoutItem.Create(size);
            var group = NSCollectionLayoutGroup.CreateHorizontal(layoutSize: size, subitem: item, count: 1);
            var section = NSCollectionLayoutSection.Create(group);

            section.InterGroupSpacing = 5;

            return section;
        }
    }

    public class CustomUICollectionViewDataSource : UICollectionViewDataSource
    {
        private readonly List<Model> _models = new List<Model>
        {
            new Model {Height = 250},
            new Model {Height = 100},
            new Model {Height = 300},
            new Model {Height = 400},
            new Model {Height = 500},
            new Model {Height = 50},
            new Model {Height = 230},
            new Model {Height = 100},
            new Model {Height = 600},
            new Model {Height = 310},
            new Model {Height = 150},
            new Model {Height = 220}
        };

        public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath)
        {
            var model = _models[(int)indexPath.Item];

            var cell = collectionView.DequeueReusableCell("CustomUICollectionViewCell", indexPath) as CustomUICollectionViewCell;

            cell.UpdateHeight(model.Height);

            return cell;
        }

        public override nint GetItemsCount(UICollectionView collectionView, nint section)
        {
            return _models.Count;
        }
    }

    public sealed class CustomUICollectionViewCell : UICollectionViewCell
    {
        private readonly UIView _uiView;

        [Export("initWithFrame:")]
        public CustomUICollectionViewCell(CGRect frame) : base(frame)
        {
            _uiView = new UIView
            {
                BackgroundColor = UIColor.Brown,
                TranslatesAutoresizingMaskIntoConstraints = false
            };

            ContentView.AddSubview(_uiView);

            NSLayoutConstraint.ActivateConstraints(new[]
            {
                _uiView.TopAnchor.ConstraintEqualTo(ContentView.SafeAreaLayoutGuide.TopAnchor),
                _uiView.BottomAnchor.ConstraintEqualTo(ContentView.SafeAreaLayoutGuide.BottomAnchor),
                _uiView.LeftAnchor.ConstraintEqualTo(ContentView.SafeAreaLayoutGuide.LeftAnchor),
                _uiView.RightAnchor.ConstraintEqualTo(ContentView.SafeAreaLayoutGuide.RightAnchor)
            });
        }

        public void UpdateHeight(int height)
        {
            _uiView.HeightAnchor.ConstraintEqualTo(height).Active = true;
        }
    }

    public class Model
    {
        public int Height { get; set; }
    }
}

回答1:


If you do this, the print message should prompt you to repeat the constraint.

You set the constraints of left, right, bottom, top, and added a height constraint when updating. The first four constraints have already determined the final height, the new height here will not work, and a warning message will be printed.

If you really want to update the height, you should set the left, right, top, height constraints from the beginning, and save the height constraint, which is used when updating.

var heightConstraint: NSLayoutConstraint?

heightConstraint = _uiView.heightAnchor.constraint(equalToConstant: 50)//Defaults
NSLayoutConstraint.activate([

(_uiView.topAnchor.constraint(equalTo:ContentView.SafeAreaLayoutGuide.topAnchor))!,                
(_uiView.leftAnchor.constraint(equalTo:ContentView.SafeAreaLayoutGuide.leftAnchor))!
(_uiView.rightAnchor.constraint(equalTo:ContentView.SafeAreaLayoutGuide.rightAnchor))!,
(heightConstraint)!
]);

public void UpdateHeight(int height){
    heightConstraint?.isActive = false
    heightConstraint = _uiView.heightAnchor.constraint(equalToConstant: height)
    heightConstraint?.isActive = true
}



回答2:


Here's the fix for this as recommended by Xamarin support:

NSLayoutConstraint heightConstraint;
public void UpdateHeight(int height)
{
    if (heightConstraint == null)
    {
        heightConstraint = _uiView.HeightAnchor.ConstraintEqualTo(height);
        heightConstraint.Active = true;
    }
    else
    {
        heightConstraint.Constant = height;
    }
}


来源:https://stackoverflow.com/questions/58580490/view-height-constraints-are-not-set-correctly-as-i-scroll-uicollectionview-up-an

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!