I am looking at the TableViewSuite example code from Apple. In Suite 5 - they have a UITableViewCell which has another UIView within it. That view is responsible for drawing the view. My question is about how it handles highlighting. In the UIView they have the following:
- (void)setHighlighted:(BOOL)lit {
// If highlighted state changes, need to redisplay.
if (highlighted != lit) {
highlighted = lit;
[self setNeedsDisplay];
}
}
My question is - how does this get called? I searched for highlight and there aren't many matches in the project. Does a UITableViewCell call setHighlighted on all of its subviews when it has setHighlighted called on itself? I'm assuming this is what is happening but can't find any documentation that states this.
I'm pretty sure the table view cell recurses into its subviews. I recall having a subview in a custom table cell that would highlight if the cell was highlighted.
Related
I have a UItableview with custom cells in it. The height of the cell changes when you select it and gives an expanding effect. However, when you you select the cell the background of all the subviews become transparent it seems. I've tried setting the cell's SelectedBackgroundView but that doesn't really affect the cells subviews.
Here are some images:
Closed:
Open:
![enter image description here][2]
This is how its supposed to look or at least does in XCode - (Sorry for the bad graphic here)
Call [tableView deselectRowAtIndexPath:indexPath animated:YES]; at didSelectRowAtIndexPath. This should solve your issue.
Edit
If you don't want to see any grey selection at all, then, in your cellForRowAtIndexPath, set the cell.selectionStyle to UITableViewCellSelectionStyleNone, like so:
cell.selectionStyle = UITableViewCellSelectionStyleNone;
Presuming that you have subclassed UITableViewCell for your custom cells, you can modify a cell's appearance when selected/deselected by overriding the setSelected method in your custom subclass. For example:
- (void) setSelected:(BOOL)selected {
[super setSelected:selected];
if (selected) {
//Configure the selected state here
} else {
//Configure the deselected state here
}
}
UITableViewCell changes the backgroundColor of all subviews on selection for some reason.
This might help:
DVColorLockView
If you want the normal selection behavior but want to exclude specific cell subviews, you can do something like this to lock the background color by subclassing and checking if it is locked in the backgroundColor setter.
This question already has answers here:
How to know the UITableview row number
(10 answers)
How to get UITableView from UITableViewCell?
(21 answers)
Closed 8 years ago.
I've used this code for to get an UIButton from inside my UITableViewCell but it didn't work. So I've debugged it like half an hour to know what superview it in is.
UIButton *button = (UIButton *)sender;
UITableViewCell* cell = (UITableViewCell*)button.superview.superview.superview;
UITableView* tableView = (UITableView*) cell.superview.superview;
NSIndexPath* indexPath = [tableView indexPathForCell:cell];
The question for me is now: How can I know in the future in what hierarchy it is for a UITableView or others? Isn't there a list where I can see how much superviews I need to go without testing it 100 times and set BreakPoints to see what class it refers to?
Regards
You may just end up going with the superview hierarchy route, but know this is not a good idea because Apple could change their table view hierarchy any time. There are much better ways to get the index path for a table view cell given a button inside one of the cells.
If all the buttons are in one section of the table view, simply set each button's tag to the cell's index path row. Then you can recreate the index path knowing which row the button is in.
You can always subclass UITableViewCell and implement the action method for the button inside the subclass. The subclass might call a delegate method to whichever object wanted to know about the button tap.
So hopefully this gives you an idea of the alternatives to what you were doing before. As you said, it's time-consuming to figure out the superview hierarchy and it could change at any time.
If you want to check multiple superview hierarchy then check like that below:-
UIView * view=(UIView*)sender;
while ((view= [view superview])) {
if(viewisKindOfClass:[UITableView class]) {
//your code
return;
}
}
I'd like to know when a UICollectionViewCell is displayed on the actual screen. cellForRowAtIndexPath is insufficient, as the cell isn't actually seen at this point. didEndDisplayingCell is insufficient, as it gets called when the cell is removed from view.
UITableViewDelegate has a willDisplayCell method that I've found useful for similar stuff in the past, but it doesn't appear to exist in UICollectionViewDelegate.
How can I determine when the cell is brought on to the screen?
Make a subclass of UICollectionViewCell. Override its didMoveToWindow method:
- (void)didMoveToWindow {
if (self.window != nil) {
// I am now in the window's view hierarchy and thus “on screen”.
}
}
Technically, the cell could still be not visible, either because it's outside the window's visible bounds, or because it's covered by another view. But normally neither of those will be the case.
Note also that if a cell is reused, it might not get removed from and re-added to the view hierarchy. The collection view can just change the cell's frame. (I know UITableView does this with table view cells as of iOS 6.0.) In that case, you won't receive a didMoveToWindow message when the cell gets re-used for another item.
If you explain why you want to know when a cell is displayed, we might be able to give you a better answer.
-[UICollectionView visibleCells] returns a NSArray of all cells visible on screnn
I'm trying to get a UIScrollView to work correctly inside of a UICollectionViewCell.
The custom cell is being loaded in via a xib file and is a subclass of UICollectionViewCell. I had problems getting other controls working, such as a button and a gesture recognizer since the UICollecitonView doesn't seem to be passing any touches to the cells, but I got around those with gesture recognizers on the UICollectionView itself. The one remaining issue I have is the UIScrollViews...
The UICollectionView scrolls horizontally, and the UIScrollView in the cells scroll vertically. I've tried using a UIPanGestureRecognizer to scroll them, but that seems to disable the UICollectionView's ability to scroll.
Anybody have any thoughts?
EDIT: Got it!
So I had converted to a collection view from a previous third party library we were using before iOS6. Turns out the problem was with the xib files we were using for the cells. With the library before, the cells were just subclasses of UIViews. I changed the classes to subclass UICollectionViewCell, and updated the Custom Class. Turns out this was not enough. In order for touches to get passed to the cells I needed to actually had to drag in a new UICollectionViewCell from the Object library, copy over all the subviews and reconnect the IBOutlets. After this, it worked!
I fixed this in my code by making sure resizing of the scroll view happens on main thread.
My collection view is using nsfetchedresultscontroller that is using block calls to refresh selected cells. On the first time a cell was selected the scrollview would not scroll. However if you clicked on another cell and clicked back it would work fine. The initial load of the cell seemed like size calc might not be where it needed to be on main thread to affect behavior.
-(UICollectionViewCell *) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"CustomCell" forIndexPath:indexPath];
dispatch_async(dispatch_get_main_queue(), ^{
// resizeScrollViewMethod should be where scrollview content size > scroll view frame.
[cell resizeScrollViewMethod];
});
return cell;
}
- (void) resizeScrollViewMethod {
//Do your scrollview size calculation here
}
No problem with UISCrollView in UICollectionViewCell. Use StoryBoard and you'll scroll OK.
UIScrollView overlay UICollectionViewCell, so that didSelect work only when tap outside ScrollView and inside Cell (scrollView.frame < cell.frame).
If you want to implement tap or other gesture, just add it to UIScrollView in awakeFromNib
Refer code:
https://github.com/lequysang/github_zip/blob/master/CollectionViewWithCellScrollViewStoryBoard.zip
I've subclassed UITableViewCell to display a UIImage and two UILabel subviews. In the view controller for the table view, in the method cellForRowAtIndexPath: I've enabled an accessory view via setAccessoryType:UITableViewCellAccessoryDetailDisclosureButton.
Cells display correctly.
When I tap on the accessory disclosure button I want to replace the two label subviews with two different label subviews. My approach was the following:
In the subclassed UITableViewCell, inside layoutSubviews, create the
CGRects for the "alternate" labels, position them in the same
places as the two "original" label and hide them via setAlpha:;
When the disclosure button is tapped swap out the set of two
label by adjusting their respective alphas.
The problem is I can't figure out what logic in layoutSubviews I'd use to know whether the accessory button has been tapped. I see that in the view controller accessoryButtonTappedForRowWithIndexPath: is called when that button is tapped and from there it seems like I would call layoutSubviews but can't figure out how to use that fact to accomplish what I'm trying to do.
Am I going about this all wrong? Instead of hiding/showing CGRects with alpha should I simply be creating another subclass of UITableViewCell?
When I tap on the accessory disclosure button I want to replace the two UILabel subviews with two different UILabel subviews.
I'll do the following. Create a public method in your UITableViewCell subclass like the following:
- (void)changeContentForCell;
In this method you could set the contentView as you prefer.
Then in your view controller implement
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
CustomCell* cCell = (CustomCell*)[tableView cellForRowAtIndexPath:indexPath];
[cCell changeContentForCell];
}
This is a simple example for change the content. In my opinion you don't have to use layoutSubviews to add views.
Leave this logic in changeContentForCell and then call setNeedsLayout to change your layout. Maybe you could have a variable that tracks the state for your cell: normal state or modified state.
Hope it helps.