我在启用分页的情况下遇到 UICollectionView 问题。每个单元格将覆盖整个屏幕,因此一次只能看到 1 个单元格 在主视图中,我有 UICollectionView,当用户滑动到其他单元格时,导航标题将根据新单元格而变化,当用户正确滑动时,这非常有效,这意味着当滑动时,UICollectionView 将整个新单元格推送到屏幕 但是,当用户稍微滑动以显示下一个单元格,然后移回到当前显示的单元格时,导航标题会发生变化,但内容仍然是当前的 有谁知道如何解决这个问题? 我在这里附上图片作为说明
这是我的代码:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
SingleLabViewCollectionScrollCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:collectionCellID forIndexPath:indexPath];
if (cell == nil){
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"SingleLabViewCollectionScrollCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
// hide
[cell.viewMain2 setHidden:YES];
[cell.viewMain3 setHidden:YES];
[cell.viewBubble2 setHidden:YES];
[cell.viewBubble3 setHidden:YES];
// set text view
[cell.lblLabText setFont:FONT_AVANT_BOOK(cell.lblLabText.font.pointSize)];
[cell.textview setScrollEnabled:YES];
[cell.textview setUserInteractionEnabled:YES];
NSDictionary *thisDict = [dictLabContentPlist valueForKey:self.titleName];
if(thisDict != nil){
NSDictionary *thisDictContent = [thisDict objectForKey:@"Text"];
NSString *content = [thisDictContent valueForKey:@"Content"];
NSAttributedString *ctAttri = [self attributedMessageFromMessage:content];
UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(messageTapped:)];
[cell.textview addGestureRecognizer:gesture];
cell.textview.attributedText = ctAttri;
cell.lblLabText.text = [thisDictContent valueForKey:@"Title"];
}
// expand textview according to text
[cell.textview sizeToFit];
[cell.textview layoutIfNeeded];
cell.textview.backgroundColor = [UIColor clearColor];
CGRect rect = cell.viewDescription.frame;
rect.size.height = cell.textview.contentSize.height + 40;
cell.viewDescription.frame = rect;
[cell.viewMain.layer setCornerRadius:5];
[cell.viewMain2.layer setCornerRadius:5];
[cell.viewMain3.layer setCornerRadius:5];
[cell.viewDescription.layer setCornerRadius:5];
// set scrollview contentsize
rect.size.height += 400;
cell.cellScrollView.contentSize = rect.size;
[cell.cellScrollView setScrollEnabled:YES];
[cell.cellScrollView scrollsToTop];
// set bubble view
[cell.btnSeeMore addTarget:self action:@selector(expand:) forControlEvents:UIControlEventTouchUpInside];
// get data for this testID
for(int i = 0; i < self.arrayTestIDs.count; i++){
if([self.arrayTestIDs[i] isEqualToString:currentID]){
currentIndex = i;
break;
}
}
// load 1st time
if(firstTimeOpenThisView){
cell.lblTestName.text = self.arrayTestNames[currentIndex];
self.titleName = self.arrayTestNames[currentIndex];
currentID = self.arrayTestIDs[currentIndex];
}else{
currentIndex ++;
// set title name
cell.lblTestName.text = self.arrayTestNames[indexPath.row];
self.titleName = self.arrayTestNames[indexPath.row];
currentID = self.arrayTestIDs[indexPath.row];
}
NSMutableDictionary *postData = [[NSMutableDictionary alloc] init];
[postData setValue:singleton.ACCESS_TOKEN forKey:@"token"];
[postData setValue:currentID forKey:@"testId"];
// this is new block that check db when click next
NSArray *fetchObjects = [singleton loadDataFromTable:@"TestData"];
// first load data from DB
isDataExist = false;
for(NSManagedObject *item in fetchObjects){
if ([[item valueForKey:@"testID"] isEqualToString:[NSString stringWithFormat:@"%@",currentID]]) {
dataResponseDict = [item valueForKey:@"data"];
NSDictionary *commonDict = [dataResponseDict objectForKey:@"Common"];
cell.lblLeftValue.text = [commonDict valueForKey:@"min"];
cell.lblLeftLevel.text = [commonDict valueForKey:@"statusBegin"];
cell.lblUnit.text = [commonDict valueForKey:@"avg"];
cell.lblRightLevel.text = [commonDict valueForKey:@"statusEnd"];
cell.lblRightValue.text = [commonDict valueForKey:@"max"];
dataResponseArray = [dataResponseDict objectForKey:@"LabReport"];
//kenvu
NSDictionary *testDict = [dataResponseArray[0] objectForKey:@"Test"];
NSString *resultStr = [testDict valueForKey:@"result"];
if([resultStr isKindOfClass:[NSNull class]])
numberOfRows = 1;
else
numberOfRows = 2;
[self loadDataIntoCell:cell indexPath:indexPath];
isDataExist=true;
}
}
if(!isDataExist){ // even data exist, still needs to download from server for latest labs data
clvMain.hidden = YES;
[self showHud];
[ws downloadDataWithMethod:@"viewlab" requestMethod:@"POST" data:postData completionBlock:^(NSDictionary *resultDict){
NSDictionary *tmpDict = [resultDict valueForKey:WS_RESULT_DATA];
dataResponseDict = [resultDict valueForKey:WS_RESULT_DATA];
if(dataResponseDict != NULL && ![dataResponseDict isKindOfClass:[NSNull class]] && dataResponseDict.count > 0){
// remove existing data for this category id
for(NSManagedObject *item in fetchObjects){
if ([[item valueForKey:@"testID"] isEqualToString:[NSString stringWithFormat:@"%@",currentID]]) {
[singleton deleteObjectFromDB:item];
}
}
// save data to db
NSMutableDictionary *dataToSave = [[NSMutableDictionary alloc]init];
[dataToSave setObject:[NSString stringWithFormat:@"%@",currentID] forKey:@"testID"];
[dataToSave setObject:tmpDict forKey:@"data"];
[singleton saveNewData:dataToSave forTable:@"TestData"];
// only reload data if no data in DB
if(!isDataExist){
NSDictionary *commonDict = [dataResponseDict objectForKey:@"Common"];
cell.lblLeftValue.text = [commonDict valueForKey:@"min"];
cell.lblLeftLevel.text = [commonDict valueForKey:@"statusBegin"];
cell.lblUnit.text = [commonDict valueForKey:@"avg"];
cell.lblRightLevel.text = [commonDict valueForKey:@"statusEnd"];
cell.lblRightValue.text = [commonDict valueForKey:@"max"];
dataResponseArray = [dataResponseDict objectForKey:@"LabReport"];
//kenvu
NSDictionary *testDict = [dataResponseArray[0] objectForKey:@"Test"];
NSString *resultStr = [testDict valueForKey:@"result"];
if([resultStr isKindOfClass:[NSNull class]])
numberOfRows = 1;
else
numberOfRows = 2;
[self loadDataIntoCell:cell indexPath:indexPath];
}
}else{ // if data == nil, still show static info
numberOfRows = 1;
cell.lblLeftValue.text = cell.lblLeftLevel.text = cell.lblUnit.text = cell.lblRightLevel.text = cell.lblRightValue.text = @"";
[self loadDataIntoCell:cell indexPath:indexPath];
}
[self hideHud];
clvMain.hidden = NO;
}];
}
firstTimeOpenThisView = false;
return cell;
}
-(void)loadDataIntoCell:(SingleLabViewCollectionScrollCell *)cell indexPath:(NSIndexPath*)indexPath{
if(indexPath.row == self.arrayTestIDs.count - 1){
btnNext.hidden = YES;
}else{
btnNext.hidden = NO;
}
if(indexPath.row == 0){
btnPrevious.hidden = YES;
}else{
btnPrevious.hidden = NO;
}
// set navigation title
titleView.lblTestName.text = self.titleName;
[titleView.lblTestName setFont:FONT_AVANT_BOOK(cell.lblTestName.font.pointSize)];
.....
}
我找到了解决方案。 通过使用scrollViewDidEndDecelerating,我只需在获取UICollectionView的visibleCells之前添加0.1秒的延迟,并且它总是返回正确的可见单元格
UICollectionView
继承自UIScrollView
,这意味着您可以随时访问集合视图的contentOffset
属性。 如果将 contentOffset
除以集合视图单元格的宽度,您将得出所显示单元格的索引,以便您可以找出当前可见的单元格。
您还可以利用
UIScrollViewDelegate
的 scrollViewDidScroll
方法 - 覆盖此方法,然后使用 contentOffset
计算出可见单元格移动了多远并触发导航栏文本的更改。因此,您可以等到当前单元格滚动超过其宽度的 50% 到下一个单元格后再进行更改 - 这样,如果用户触摸并让单元格“弹回”,导航栏标题将不会更改.
好吧,浏览一下 Apple 的开发人员文档就会发现,确实没有任何委托方法可以告诉您单元格何时在屏幕上可见。我关于在
cellForItemAtIndexPath
检查这一点的第一个评论在技术上也不准确。该方法不应该知道单元格在屏幕上的“位置”。只是如何显示它。
所以我的建议是尝试这个:
从
loadDataIntoCell
中删除对
cellForItemAtIndexPath
的方法调用。 接下来,由于
UICollectionView
继承自
UIScrollView
,您可以使用这些委托方法来确定滚动时要执行的操作。这是一个粗略的例子:方法
[collectionView visibleCells]
将为您提供数组中的所有可见单元格。您可以使用它来更改您的标题:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
for (UICollectionViewCell *cell in [collectionView visibleCells]) {
NSIndexPath *indexPath = [collectionView indexPathForCell:cell];
NSLog(@"%@",indexPath);
//Set the navigation title here
}
}
您只需要管理数组并确保其中的对象是正确的。但这应该会让你朝着正确的方向前进。