当我上下滚动 UICollectionView 时,视图高度限制设置不正确
View height constraints are not set correctly as I scroll UICollectionView up and down
我正在尝试根据模型 属性 确定视图高度,但是随着 UICollectionView
上下滚动,为可见单元格指定的高度不正确。似乎在 GetCell
中设置 HeightAnchor
(即 cellForItemAtIndexPath
)不起作用。我怎样才能使这项工作?
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; }
}
}
如果您这样做,打印消息会提示您重复约束。
您设置了left, right, bottom, top
的约束,更新时添加了height
约束。前四个约束已经确定了最终的高度,这里的新高度不起作用,会打印警告信息。
如果真的要更新高度,应该从头开始设置left, right, top, height
约束,保存height
约束,更新时用到
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
}
这是 Xamarin support 推荐的解决方法:
NSLayoutConstraint heightConstraint;
public void UpdateHeight(int height)
{
if (heightConstraint == null)
{
heightConstraint = _uiView.HeightAnchor.ConstraintEqualTo(height);
heightConstraint.Active = true;
}
else
{
heightConstraint.Constant = height;
}
}
我正在尝试根据模型 属性 确定视图高度,但是随着 UICollectionView
上下滚动,为可见单元格指定的高度不正确。似乎在 GetCell
中设置 HeightAnchor
(即 cellForItemAtIndexPath
)不起作用。我怎样才能使这项工作?
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; }
}
}
如果您这样做,打印消息会提示您重复约束。
您设置了left, right, bottom, top
的约束,更新时添加了height
约束。前四个约束已经确定了最终的高度,这里的新高度不起作用,会打印警告信息。
如果真的要更新高度,应该从头开始设置left, right, top, height
约束,保存height
约束,更新时用到
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
}
这是 Xamarin support 推荐的解决方法:
NSLayoutConstraint heightConstraint;
public void UpdateHeight(int height)
{
if (heightConstraint == null)
{
heightConstraint = _uiView.HeightAnchor.ConstraintEqualTo(height);
heightConstraint.Active = true;
}
else
{
heightConstraint.Constant = height;
}
}