I have used GMGridView inside my app. When I change the orientation all is fine, but if I change it again and enter edit mode all the cells are shacking except the visible one in the lower-right corner.
The GmGridView is added as a subview to a controller and it also doesn't occupy the whole screen. I've tried destroying it and recreating it when a rotation notification occurs ... same behaviour. Also I have made a custom view with multiple buttons and labels that I have set as the the GMGridViewCell's contentView.
here's the code for the cellForItemAtIndex
- (GMGridViewCell *)GMGridView:(GMGridView *)gridView cellForItemAtIndex:(NSInteger)index {
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
GMGridViewCell *cell = [gmGridView dequeueReusableCell];
if (!cell) {
CGSize cellSize = [self GMGridView:gmGridView sizeForItemsInInterfaceOrientation:orientation];
cell = [[GMGridViewCell alloc] initWithFrame:CGRectMake(0, 0, cellSize.width, cellSize.height)];
cell.deleteButtonIcon = [UIImage imageNamed:#"delete_button"];
cell.deleteButtonOffset = CGPointMake(0, 0);
}
CustomGridViewCell *gridViewContent = [CustomGridViewCell getNewGridViewCellForOrientation:orientation];
ContentData *data = [wishlistContentArray objectAtIndex:index];
[gridViewContent setuprWithContent:data];
cell.contentView = gridViewContent;
if (!gridViewContent.delegate)
gridViewContent.delegate = self;
return cell;
}
There is a bug on GMGridView when it computes the number of visible cells.
In loadRequiredItems there are these two lines of code
NSRange rangeOfPositions = [self.layoutStrategy rangeOfPositionsInBoundsFromOffset: self.contentOffset];
NSRange loadedPositionsRange = NSMakeRange(self.firstPositionLoaded, self.lastPositionLoaded - self.firstPositionLoaded);
You have to change the range so it will return the smallest number that is a multiple of the number of items on your cell.
For example if you have 2 cells on a row, right now the code will return a range of {0,5} but it should be {0,6}.
Related
I'm building an app whereas I've got a UICollectionView with a custom layout. I have a problem whereas I cannot tap some rows. Here's an overview over what happens
1) App starts and presents a UICollectionView
2) 3 test items are displayed, using the visual debugger in Xcode, you can see that there is something not right with the hierarchy
The red row can't be tapped now, but the yellow and green rows can.
3) User taps the yellow item, and segues to another page
4) User pops the shown UIViewController and returns to the UICollectionView whereas the viewWillAppear method reloads the UICollectionView like so:
[self.collectionView reloadData];
5) Re-entering the visual debugger shows that the hierarchy seems shifted, and the yellow row is now untappable, but the red and green rows can be tapped.
What could be the reason for this? I'll post any relevant code, ask for what parts you'd like to see.
Update
The UIViewController displaying the UICollectionView
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
ShareViewCell *view = [collectionView dequeueReusableCellWithReuseIdentifier:#"share" forIndexPath:indexPath];
view.share = [self.sharesController shareAtIndex:indexPath.item];
return view;
}
Custom cell:
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
self.leftBorderView = [UIView new];
[self.contentView addSubview:self.leftBorderView];
self.label = [UILabel new];
self.label.font = [UIFont boldSystemFontOfSize:10];
self.label.numberOfLines = 0;
self.label.lineBreakMode = NSLineBreakByWordWrapping;
[self.contentView addSubview:self.label];
}
return self;
}
- (void)layoutSubviews
{
[super layoutSubviews];
self.leftBorderView.frame = CGRectMake(0, 0, 1.5, self.bounds.size.height);
CGSize labelSize = [self.label sizeThatFits:CGSizeMake(self.bounds.size.width - 10.0f, MAXFLOAT)];
NSTimeInterval durationOfShare = [self.share.endSpan timeIntervalSinceDate:self.share.startSpan] / 3600;
CGFloat middleOfCell = self.bounds.size.height / 2;
CGFloat yPositionToUse = middleOfCell - (labelSize.height / 2);
if (durationOfShare < 0.25)
{
[self.label setHidden:YES];// to small to be shown
} else if (durationOfShare > 0.5)
{
yPositionToUse = 8; // show it at the top
}
self.label.frame = CGRectMake(8, yPositionToUse, labelSize.width, labelSize.height);
}
Update 2
Is the UICollectionReusableView blocking tap of the UICollectionViewCell?
Ok,
First, you should be more precise in your question : you're using some code found on some question on StackOverflow.
The code seems to be this Calendar UI made with UICollectionView.
This is a sample code, quickly built for the sake of a StackOverflow answer (with a bounty). It's not finished, has no contributors, and you should try to read it and improve over it !
From your debugger's captures, it seems you have some view which overlays on top of your collectionView's cells.
From reading this code, I see it uses some supplementary view to present 'hour' blocks. This supplementary view class is HourReusableView. And it's the view coming on top on your debugger's captures
CalendarViewLayout is responsible to compute these supplementary views frame, as it does for colored event blocks (see method - (void)prepareLayout)
I might bet that these supplementary views's Z-order isn't predictable - all views have a default zIndex of 0. One way to fix it ? After line 67 of this file, set a negative zIndex on the UICollectionViewLayoutAttributes of the hour block. This way, you make sure hour supplementary views are always behind your cells, and don't intercept the cell's touch
I have an app that uses a UIPickerView to set various parameters having to do with line style for a graph series (line width, colour, and line style). This picker is used in a table view row. I have defined the frame for the picker so that its width fills the width of the cell's contentView member. Up until iOS 9, this appeared to work. With iOS 9, there appears to be some sort of maximum cap on the width of a UIPickerView. Has anyone encountered anything similar to this?
The picker view is being created like this:
self.picker = [[[UIPickerView alloc] init] autorelease];
[self.contentView addSubview:self.picker];
self.picker.dataSource = self;
self.picker.delegate = self;
self.picker.backgroundColor = [UIColor grouped_table_view_background_colour];
The cell is layed out as follows:
-(void) layoutSubviews
{
// we need to allow the base class to perform its layout.
static CGFloat left_margin = 40;
static CGFloat right_margin = 40;
CGSize my_size;
[super layoutSubviews];
my_size = self.contentView.bounds.size;
my_size.width -= left_margin + right_margin;
// we now need to lay out the views.
CGRect picker_rect = CGRectMake(left_margin, 5, my_size.width, my_size.height);
self.picker.frame = picker_rect;
// we want to look at the bounds of the picker
CGRect picker_bounds = self.picker.bounds;
NSLog(#"picker bounds x=%g, y=%g, w=%g, h=%g", picker_bounds.origin.x, picker_bounds.origin.y, picker_bounds.size.width, picker_bounds.size.height);
}
I am also overloading the widthForComponent method as follows:
-(CGFloat) pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component
{
// we want to look at the bounds of the picker
CGRect picker_bounds = self.picker.bounds;
NSLog(#"picker bounds x=%g, y=%g, w=%g, h=%g", picker_bounds.origin.x, picker_bounds.origin.y, picker_bounds.size.width, picker_bounds.size.height);
return picker_bounds.size.width / 3;
}
I can see that the bounds of the view appear correctly both in the values that are logged as well as the background colour of the view. Despite this, the picker appears to fill less than half the width that is available (688 points on my iPad)
After [[UIPickerView alloc] init] the Picker has a size of {320,216} and this size will be used in pickerView:widthForComponent:. If you just resize the picker afterwards, the function pickerView:widthForComponent: won't be called again, so the components are stuck at their width.
Try to initialise the picker with the correct size like..
picker=[[UIDatePicker new] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(self.view.bounds), 216.0)];
or call [self.picker setNeedsLayout] after you change the picker frame to force pickerView:widthForComponent: to be called again.
I am trying to create a view similar to the attached image below. there is a variable sized width. I have marked text as black as there is a copyright issue.
Can anyone please look into the same and put some code so that it can help me somewhere.
Do I need to implement Custom Collection View Layout?
Please help me.
This is response to your comment you need to add 3 extra lines of code in SGSStaggeredFlowLayout
NSArray* arr = [super layoutAttributesForElementsInRect:rect];
// THIS CODE SEPARATES INTO ROWS
NSMutableArray* rows = [NSMutableArray array];
NSMutableArray* currentRow = nil;
NSInteger currentIndex = 0;
BOOL nextIsNewRow = YES;
for (UICollectionViewLayoutAttributes* atts in arr) {
if (nextIsNewRow) {
nextIsNewRow = NO;
if (currentRow) {
[rows addObject:currentRow];
}
currentRow = [NSMutableArray array];
}
if (arr.count > currentIndex+1) {
UICollectionViewLayoutAttributes* nextAtts = arr[currentIndex+1];
if (nextAtts.frame.origin.y > atts.frame.origin.y) {
nextIsNewRow = YES;
}
}
[currentRow addObject:atts];
currentIndex++;
}
if (![rows containsObject:currentRow]) {
[rows addObject:currentRow];
}
It works like charm :)
You can set size for every item by impelmenting
UICollectionViewDelegateFlowLayout protocol, and calculate item width using even/odd formula.
-(CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewFlowLayout *flowLayout = (UICollectionViewFlowLayout *)collectionView.collectionViewLayout;
NSInteger itemsPerRow = 0;
NSInteger contentSizeWidth = 0;
NSInteger num = indexPath.row;
if (num % 2)
{// odd
itemsPerRow = 2;
}
else {
// even
itemsPerRow = 3;
}
contentSizeWidth = collectionView.frame.size.width- (flowLayout.minimumInteritemSpacing*(itemsPerRow-1))-flowLayout.sectionInset.left-flowLayout.sectionInset.right;
return CGSizeMake(contentSizeWidth/itemsPerRow, 100);
}
if you are trying to do this without any framework, you need to develop your own algroithm to calculate the width of each cell.
first, you need to calculate the width of text plus margin maybe border as well.
Second, calculate how many items are gonna be placed in given row. try to add 3 togther , if the total width excess the uicollection width, it means the third text should go to the next cell. if it is less than the collection width,it means you can add try to the 4th text.
third, caculate the width of each cell in each line base on how many cells are gonna placed on that line and their own width.
changing the uicollectionview width should not be diffculty since collectionviewcells are darw from left to right then top to bottom.
I am new to IOS.
I have used collection view. I am using Prototype cell in it. I have not used Auto-Layout in my app.
I need to change frame of buttons and view in cellForItemAtIndexPath. But when I first scroll to move to next cell it not reflecting first time. I can only see blank with out any buttons or view. I have checked all the frames are correctly updating. Still I can not see any thing.
Though if I again go to previous call and come back it will seen properly.
Please find below code of cellForItemAtIndexPath
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
Feed *feed;
NSMutableAttributedString * string;
feed = [arrTop objectAtIndex:indexPath.row];
ShuffleCell *myCell = [collectionView
dequeueReusableCellWithReuseIdentifier:#"ShuffleCell"
forIndexPath:indexPath];
myCell.index = indexPath;
myCell.delegate = self;
// Below frame changes are not working
myCell.vwBack.frame = collect.frame;
myCell.imgShare.frame = CGRectMake(myCell.imgShare.frame.origin.x, myCell.imgShare.frame.origin.y, self.view.frame.size.width,self.view.frame.size.width );
myCell.lblText.center = CGPointMake(myCell.imgShare.frame.size.width / 2, myCell.imgShare.frame.size.height / 2);
myCell.lblText.frame = CGRectMake(20
, myCell.imgShare.frame.origin.y + 20, self.view.frame.size.width - 20,self.view.frame.size.width -20);
int totHeight = (collect.frame.size.height - self.view.frame.size.width);
myCell.vwBtn.frame = CGRectMake(myCell.vwBtn.frame.origin.x, collect.frame.size.height -totHeight, myCell.vwBtn.frame.size.width, totHeight);
[myCell.vwBtn setFrame:CGRectMake(myCell.vwBtn.frame.origin.x, collect.frame.size.height -totHeight, myCell.vwBtn.frame.size.width, totHeight)];
myCell.btnFavoriteBack.frame = CGRectMake(myCell.btnFavoriteBack.frame.origin.x, 0, myCell.btnFavoriteBack.frame.size.width, totHeight/3);
[myCell.btnFavoriteBack setFrame:CGRectMake(myCell.btnFavoriteBack.frame.origin.x, 0, myCell.btnFavoriteBack.frame.size.width, totHeight/3)];
myCell.btnShare.frame = CGRectMake(myCell.btnShare.frame.origin.x, (totHeight/3), myCell.btnShare.frame.size.width, totHeight/3);
myCell.btnReport.frame = CGRectMake(myCell.btnReport.frame.origin.x, (totHeight/3)*2, myCell.btnReport.frame.size.width, totHeight/3);
myCell.vwLikeBtn.frame = CGRectMake(self.view.frame.size.width - 82, (totHeight/3 - 32)/2, 82,32);
NSLog(#"Y :- %f",myCell.vwBtn.frame.size.height);
return myCell;
I have also attached screen shot of same.
Thanks for Help.
Adding this line should fix the problem. Let the subviews of cell translate their frames to constraints.
cell.label.translatesAutoresizingMaskIntoConstraints = YES;
I am working on an app since a while, it is going well. However, this weekend I updated to Xcode 6 and now my app is behaving differently as opposed to before the update to Xcode 6.
I have a UITableView in my app which I rotate in viewDidLoad:
//Rotate playerCardsTable.
CGAffineTransform rotateTable = CGAffineTransformMakeRotation(-M_PI_2);
_playerCardsTable.transform = rotateTable;
_playerCardsTable.frame = CGRectMake(0, 0, _playerCardsTable.frame.size.width, _playerCardsTable.frame.size.height);
In Xcode before the update (Xcode 5) I had this view:
But now, after updating to Xcode 6, I have this view:
The tableview is rotated, ergo I have horizontal scrolling, but it seems like the frame is not changed correctly after rotation. It is 320 pixels high and 80 pixels wide and it should be the other way round. I don't know why, but it seems I cannot change the frame afterwards in code, in other words, I don't see any change after changing the width and height.
The tableview is added via the interface builder and holds custom cells:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSString *cardName = [[[[[Game game] localPlayer] playerCards] objectAtIndex:indexPath.row] fileNameCard];
cell.cardImage.image = [UIImage imageNamed:cardName];
Card *card;
card = [[[[Game game] localPlayer] playerCards] objectAtIndex:indexPath.row];
if(card.playable == IsPlayable){
cell.backgroundColor = isPlayableColor;}
else if (card.playable == IsNotPlayable) {
cell.backgroundColor = isNotPlayableColor;}
else if (card.playable == IsReallyPlayable) {
cell.backgroundColor = isReallyPlayableColor;}
//Rotate image to align with rotated tableview.
CGAffineTransform rotateImage = CGAffineTransformMakeRotation(M_PI/2);
cell.cardImage.transform = rotateImage;
cell.playableImage.transform = rotateImage;
cell.cardImage.layer.borderWidth = 2;
cell.cardImage.layer.borderColor = [UIColor clearColor].CGColor;
cell.cardImage.layer.shouldRasterize = YES;
cell.cardImage.layer.rasterizationScale = [[UIScreen mainScreen] scale];
cell.cardImage.layer.shadowColor = [UIColor blackColor].CGColor;
cell.cardImage.layer.shadowOffset = CGSizeMake(0, 1);
cell.cardImage.layer.shadowOpacity = 0.7;
cell.cardImage.layer.shadowRadius = 2.0;
cell.cardImage.clipsToBounds = NO;
return cell;}
To be clear; I did not change any code after the update, so the different behavior is caused by the update.
Hope you guys could help.
Thanks!
I ran into a very similar situation after upgrading iPad to ios8 just recently - Horizontal tables not appearing correctly.
I don't have a complete solution, but can tell you from research and testing that in my case it was due to the transform action and AutoLayout constraints on the UITableView not coordinating/cooperating. Evidently the way these two concepts work together changed somewhat in ios8.
A top constraint set in a storyboard becomes a left constraint after the transform (or right, never did figure it out properly).
Bottom line for me was that after trying a number of combinations of constraints, including removing them before transform, then adding constraints back in after the transform, I ended up converting from a UITableView to UICollectionView.