我第一次使用UICollectionView时不确定如何操作。我正在尝试为tvOS创建一个应用程序,并希望显示像airbnb tvos app这样的菜单。我以某种方式试图实现特定格式didUpdateFocusInContext
,但问题是关于第一次出现,因为第一次出现发生在默认点上,即收集视图的0,0导致混乱。
继承了我迄今为止所做的工作。
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as? ShowCell {
menuData = dataArray[indexPath.row] as! NSDictionary
cell.configureCell(menuData.objectForKey("name") as! String)
return cell
}
else {
return ShowCell()
}
}
override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
if let previousItem = context.previouslyFocusedView as? ShowCell {
UIView.animateWithDuration(0.2, animations: { () -> Void in
previousItem.showImg.frame.size = self.originalCellSize
})
}
if let nextItem = context.nextFocusedView as? ShowCell {
UIView.animateWithDuration(0.2, animations: { () -> Void in
nextItem.showImg.frame = CGRectMake(
self.view.frame.width/2 - self.focusCellSize.width/2,
169.0,
self.focusCellSize.width,
self.focusCellSize.height)
})
}
}
这是我想要实现的视图,我已经实现了它,但对于后来的索引意味着1,2 之后的索引
这就是我真正想要的,但我正在努力将我的专注细胞放到屏幕的中间,同样地,我的前一个和下一个在两侧。我知道我明确给出了帧坐标这是不正确的这只是我正在运行的测试用例而没有其他但我找不到这样做的方法
答案 0 :(得分:3)
我将分别控制焦点和集合内容偏移(滚动位置)。
对于内容偏移,您应设置截面边距和项目间距,以便让一个单元格居中,并且边缘处可见相邻单元格。您可以在不显示任何焦点的情况下进行此设置和测试。
当你滚动(焦点改变)时,可能难以让物品准确地移动到中心。要解决此问题,请实施- scrollViewWillEndDragging:withVelocity:targetContentOffset:
以查找targetContentOffset
处的项目并获取其中心点(来自布局属性)。有了它,你可以修改targetContentOffset
,使滚动结束与项目居中完全结束。
现在,焦点应该由单元本身管理,而不是集合视图。下面是一个(稍大)细胞焦点变化动画的例子。它使用制图来更改图像视图约束并将变换应用于标签。您可以执行类似的操作,具体取决于您希望图像和标签彼此交互的方式。
请注意,当UIImageView
具有焦点且设置为adjustsImageWhenAncestorFocused
时,以下代码也会应用类似于apple提供的股票的动态效果转换。如果你不想要,你可以简化和缩短代码。
override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
super.didUpdateFocusInContext(context, withAnimationCoordinator: coordinator)
if (context.nextFocusedView == self) {
UIView.animateWithDuration(0.1,
animations: { () -> Void in
self.imageConstraints = constrain(self.itemImageView, replace: self.imageConstraints!) {
$0.top == $0.superview!.top
$0.bottom == $0.superview!.bottom
$0.leading == $0.superview!.leading
$0.trailing == $0.superview!.trailing
}
self.itemLabel.transform = CGAffineTransformMakeTranslation(0, 60)
self.itemLabel.layer.backgroundColor = UIColor.darkGrayColor().colorWithAlphaComponent(0).CGColor
self.layer.shadowOpacity = 1
self.layoutIfNeeded()
}, completion: nil)
let minMaxAngle = 10.0
let m34 = CGFloat(1.0 / -1250)
let angle = CGFloat(minMaxAngle * M_PI / 180.0)
var baseTransform = CATransform3DIdentity
baseTransform.m34 = m34
let rotateXmin = CATransform3DRotate(baseTransform, -1 * angle, 1.0, 0.0, 0.0);
let rotateXmax = CATransform3DRotate(baseTransform, angle, 1.0, 0.0, 0.0);
let rotateYmin = CATransform3DRotate(baseTransform, angle, 0.0, 1.0, 0.0);
let rotateYmax = CATransform3DRotate(baseTransform, -1 * angle, 0.0, 1.0, 0.0);
let verticalMotionEffect = UIInterpolatingMotionEffect(keyPath: "layer.transform",
type: .TiltAlongVerticalAxis)
verticalMotionEffect.minimumRelativeValue = NSValue(CATransform3D: rotateXmin)
verticalMotionEffect.maximumRelativeValue = NSValue(CATransform3D: rotateXmax)
let horizontalMotionEffect = UIInterpolatingMotionEffect(keyPath: "layer.transform",
type: .TiltAlongHorizontalAxis)
horizontalMotionEffect.minimumRelativeValue = NSValue(CATransform3D: rotateYmin)
horizontalMotionEffect.maximumRelativeValue = NSValue(CATransform3D: rotateYmax)
let group = UIMotionEffectGroup()
group.motionEffects = [horizontalMotionEffect, verticalMotionEffect]
self.addMotionEffect(group)
}
else {
UIView.animateWithDuration(0.3,
animations: { () -> Void in
self.imageConstraints = constrain(self.itemImageView, replace: self.imageConstraints!) {
$0.top == $0.superview!.top + 20
$0.bottom == $0.superview!.bottom - 20
$0.leading == $0.superview!.leading + 20
$0.trailing == $0.superview!.trailing - 20
}
self.itemLabel.transform = CGAffineTransformIdentity
self.itemLabel.layer.backgroundColor = UIColor.darkGrayColor().colorWithAlphaComponent(0.75).CGColor
self.layer.shadowOpacity = 0
self.layoutIfNeeded()
}, completion: nil)
for effect in self.motionEffects {
self.removeMotionEffect(effect)
}
}
}
答案 1 :(得分:0)
@Wain已经提出了实现上述风格的指导方针,这是我对此的准确答案:
override func didUpdateFocusInContext(context: UIFocusUpdateContext,
withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
if let focusedView = context.nextFocusedView as? ShowCell {
collectionView.scrollEnabled = false
let indexPath = collectionView.indexPathForCell(focusedView)!
focusedView.showImg.frame.size = self.focusImageSize
focusedView.showLbl.frame.size = self.focusLabelSize
focusedView.showLbl.font = UIFont.systemFontOfSize(75)
collectionView.scrollToItemAtIndexPath(indexPath, atScrollPosition: .CenteredHorizontally, animated: true)
self.collectionView.layoutIfNeeded()
}
else if let lastFocuedView = context.previouslyFocusedView as? ShowCell{
collectionView.scrollEnabled = true
// let indexPath = collectionView.indexPathForCell(lastFocuedView)!
lastFocuedView.showImg.frame.size = self.originalImageSize
lastFocuedView.showLbl.frame.size = self.originalLabelSize
lastFocuedView.showLbl.font = UIFont.systemFontOfSize(70)
self.collectionView.layoutIfNeeded()
}
并为第一个和最后一个单元格提供UIEdgeInsets(它是流程布局的委托方法)
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets{
return UIEdgeInsets(top: 0.0, left: self.collectionView.frame.width/2 , bottom: 0.0, right: self.collectionView.frame.width/2)
}
真诚地感谢Wain为这个问题提供了准确的指导。 干杯!
答案 2 :(得分:0)
解决方案是覆盖此处的滚动视图委托方法scrollViewWillEndDragging
https://stackoverflow.com/a/42117107/1587729(Swift 3)