问题
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