Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITableViewCell Z-Order

I have a uitableview which contains cells. I am trying to figure it out how to adjust the z order of the cells. I am trying to make this: enter image description here

But when I load the tableview I get this: enter image description here

I've already tried [tableView sendSubViewToBack:cell]. Also when I scroll to the bottom and then return to the top the result is like in picture 1 but when I scroll down the result is like in picture 2. I appreciate your help.

    static NSString *CellIdentifier = @"Cell";
NSString *row = [NSString stringWithFormat:@"%li",(long)indexPath.row];
GetMoreTableViewCell *cell = [_chapters dequeueReusableCellWithIdentifier:CellIdentifier];
NSMutableDictionary *deckCategory = [[_data valueForKey:key] valueForKey:row];

if (cell == nil) {
    cell = [[GetMoreTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}


[tableView bringSubviewToFront:cell];

if([[[_data valueForKey:key] valueForKey:[NSString stringWithFormat:@"%i",indexPath.row]] valueForKey:@"isDefault"] == [NSNumber numberWithBool:YES]) {
    cell.addButton.hidden = YES;
}
cell.ttitle.text = [[[_data valueForKey:key] valueForKey:row] valueForKey:@"Name"];
cell.backgroundColor = [UIColor clearColor];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
CALayer * l = [cell.cellImage layer];
[l setMasksToBounds:YES];
[l setCornerRadius:10.0];

CALayer * b = [cell.cellBackground layer];
[b setMasksToBounds:YES];
[b setCornerRadius:19.0];
cell.cellImage.image = [UIImage imageNamed:[deckCategory valueForKey:@"Image"]];

if(indexPath.row == 0) {
    cell.cellBackground.image = [UIImage imageNamed:@"card_green.png"];
}
else if(indexPath.row == 1) {
    cell.cellBackground.image = [UIImage imageNamed:@"card_orange.png"];
}
else if(indexPath.row == 2) {
    cell.cellBackground.image = [UIImage imageNamed:@"card_red.png"];
}

return cell;
like image 867
Viktor Todorov Avatar asked Sep 08 '14 06:09

Viktor Todorov


4 Answers

I faced the same problem when using shadows on my UITableViewCells, the cells further down the screen (In the Y direction) had shadows overlapping from the higher ones at the top of the screen.

My solution was to set the Z Position on the layer of UITableViewCell based upon the indexPath.

cell.layer.zPosition = CGFloat(indexPath.row)

My issue was only occurring within individual sections. If your cells from subsequent sections also face this problem then you will need to add section number into the calculation.

cell.layer.zPosition = CGFloat(indexPath.section) * 1000.0 +  CGFloat(indexPath.row)

If you have more than 1000 rows in each section then increase the magic number, or think about why you have 1000 rows in your App ;-)

like image 159
Brett Avatar answered Nov 08 '22 19:11

Brett


I faced the same issue some time back.

The solution that worked for me is using a Collection view instead of a TableView. Create a custom class by extending it from UICollectionViewFlowLayout and use that in your Collection View instead.

class OverlappedCustomFlowLayout: UICollectionViewFlowLayout {
    override func prepare() {
        super.prepare()

        // This allows us to make intersection and overlapping
        // A negative number implies overlapping whereas positive implies space between the adjacent edges of two cells.
        minimumLineSpacing = -100
    }

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        let layoutAttributes = super.layoutAttributesForElements(in: rect)
        for currentLayoutAttributes: UICollectionViewLayoutAttributes in layoutAttributes! {

            // zIndex - Specifies the item’s position on the z-axis. 
            // Unlike a layer's zPosition, changing zIndex allows us to change not only layer position, 
            // but tapping/UI interaction logic too as it moves the whole item.
            currentLayoutAttributes.zIndex = currentLayoutAttributes.indexPath.row + 1
        }
    }

    return layoutAttributes
}

P.S. - As per Apple's developer document of zIndex

This property is used to determine the front-to-back ordering of items during layout. Items with higher index values appear on top of items with lower values. Items with the same value have an undetermined order. The default value of this property is 0.

Hope it helps! :)

like image 3
Nisha Yadav Avatar answered Nov 08 '22 20:11

Nisha Yadav


It should work by changing the zPosition of the cell layer like this : cell.layer.zPosition = CGFloat(indexPath.row) in the tableView:cellForRowAtIndexPath: dataSource method. And don't forget to set the clipsToBound property to false for the cell.

like image 2
jffb Avatar answered Nov 08 '22 19:11

jffb


Unfortunately you can't control the order that cellForRow... is called in, so sending the cell to the back or the front isn't going to do it.

You would probably need to make a method which passed through the visible cells of the table and reordered them according to index path, but you're messing with views that you don't have control over. The table view can rearrange or add subviews at any time and you'd be trying to catch all of those events.

I would implement a view like this with a collection view rather than a table view, which would allow you to specify a z position for each indexPath using a custom layout, and would allow you to overlap the cells by a varying amount. Creating a custom layout is pretty simple, particularly for a table-type layout.

like image 1
jrturton Avatar answered Nov 08 '22 18:11

jrturton