UITableViewCell content overlaps delete button when in editing mode in iOS7 - objective-c

I am creating a UITableView with custom UITableViewCells. iOS 7's new delete button is causing some problems with the layout of my cell.
If I use the "Edit" button, which makes the red circles appear I get the problem, but if I swipe a single cell it looks perfect.
This is when the Edit button is used:
[self.tableView setEditing:!self.tableView.editing animated:YES];
This is when I swipe a single cell:
As you can se my labels overlaps the delete button in the first example. Why does it do this and how can I fix it?

try using the accessoryView and editingAccessoryView properties of your UITableViewCell, instead of adding the view yourself.
If you want the same indicator displayed in both editing and none-editing mode, try setting both view properties to point at the same view in your uiTableViewCell like:
self.accessoryView = self.imgPushEnabled;
self.editingAccessoryView = self.imgPushEnabled;
There seems to be a glitch in the table editing animation in IOS7, giving an overlap of the delete button and the accessoryView when switching back to non-editing state. This seems to happen when the accesoryView is specified and the editingAccessoryView is nil.
A workaround for this glitch, seems to be specifying an invisible editingAccessoryView like:
self.editingAccessoryView =[[UIView alloc] init];
self.editingAccessoryView.backgroundColor = [UIColor clearColor];

The problem is that in edit mode the cell's contentView changes in size. So either you have to override layoutSubviews in your cell and support the different frame sizes
- (void) layoutSubviews
{
[super layoutSubviews];
CGRect contentFrame = self.contentView.frame;
// adjust to the contentView frame
...
}
or you take the bait and switch to autolayout.
First I thought setting contentView.clipsToBounds to YES could be an ugly workaround but that does not seem to work.

I've resolved this problem with set up constraints without width only leading and trailing

As tcurdt mentioned, you could switch to autolayout to solve this issue. But, if you (understandably) don't want to mess with autolayout just for this one instance, you can set the autoresizingMask and have that turned automatically into the appropriate autolayout constraints.
label.autoresizingMask = UIViewAutoresizingFlexibleWidth;

Just use this method in your custom TableViewCell class you can get the perfect answer,
Here self is UITableviewCell
- (void)layoutSubviews {
[super layoutSubviews];
for (UIView *subview in self.subviews) {
for (UIView *subview2 in subview.subviews) {
if ([NSStringFromClass([subview2 class]) isEqualToString:#"UITableViewCellDeleteConfirmationView"]) { // move delete confirmation view
[subview bringSubviewToFront:subview2];
}
}
}
}

And if any one want to adjust the Delete Button Size, Use the following Code
- (void)layoutSubviews {
[super layoutSubviews];
for (UIView *subview in self.subviews) {
for (UIView *subview2 in subview.subviews) {
if ([NSStringFromClass([subview2 class]) isEqualToString:#"UITableViewCellDeleteConfirmationView"]) { // move delete confirmation view
CGRect rect = subview2.frame;
rect.size.height = 47; //adjusting the view height
subview2.frame = rect;
for (UIButton *btn in [subview2 subviews]) {
if ([NSStringFromClass([btn class]) isEqualToString:#"UITableViewCellDeleteConfirmationButton"]) { // adjusting the Button height
rect = btn.frame;
rect.size.height = CGRectGetHeight(subview2.frame);
btn.frame = rect;
break;
}
}
[subview bringSubviewToFront:subview2];
}
}
}
}

Best way to remove this problem is that add an image in cell and set it in Backside.
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"bgImg.png"]];
imageView.frame = CGRectMake(0, 0, 320, yourCustomCell.frame.size.height);
[yourCustomCell addSubview:imageView];
[yourCustomCell sendSubviewToBack:imageView];
If your text would overlap the delete button then implement Autolayout. It'll manage it in better way.
One more case can be generate that is cellSelectionStyle would highlight with default color. You can set highlight color as follows
yourCustomCell.selectionStyle = UITableViewCellSelectionStyleNone;
Set your table cell's selection style to UITableViewCellSelectionStyleNone. This will remove the blue background highlighting or other. Then, to make the text label or contentview highlighting work the way you want, use this method in yourCustomCell.m class.
- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
{
if (highlighted)
self.contentView.backgroundColor = [UIColor greenColor];
else
self.contentView.backgroundColor = [UIColor clearColor];
}
I hope you understand it in a better way.

Bringing to front UITableViewCellDeleteConfirmationView in the layoutSubviews of the custom cell works for me on iPhone, but not on iPad.
I have a UITableView in the master part of a splitViewController for the iPad, and in this case
the frame of the UITableViewCellDeleteConfirmationView is (768 0; 89 44), instead of (320 0; 89 44)
So I resize the frame in the layoutSubviews method and this works for me
- (void)layoutSubviews {
[super layoutSubviews];
for (UIView *subview in self.subviews)
{
for (UIView *subview2 in subview.subviews)
{
if ([NSStringFromClass([subview2 class]) isEqualToString:#"UITableViewCellDeleteConfirmationView"])
{
CGRect frame = subview2.frame;
frame.origin.x = 320;
subview2.frame = frame;
[subview bringSubviewToFront:subview2];
}
}
}
}

If you are putting content in the UITableViewCell's contentView, be sure you use self.contentView.frame.size.width and not self.frame.size.width in layoutSubviews.
self.frame expands width in editing mode, and will cause any content on the right to extend past the bounds of the contentView. self.contentView.frame stays at the correct width (and is what you should be using).

Try this: Might be you are setting cell setBackgroundImage in cellForRowAtIndexPath (Delegate Method). Do not set this here. Set your image in:
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { cell.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:#"cellList.png"]]; }
Enjoy Coding.

My solution is to move whole contentView to the left when Delete button showing:
override func layoutSubviews() {
super.layoutSubviews()
if editingStyle == UITableViewCellEditingStyle.Delete {
var rect = contentView.frame
rect.origin.x = self.showingDeleteConfirmation ? -15 : 38
contentView.frame = rect
}
}

Related

How to increase the height of NSTableHeaderView?

I need to implement a headerview with specific size and gradient. I have to insert images in certain cells of the headerview.Tried to create the cells for the headerview using the following code,but i was not able to customize the headerview.
[[tableColumn headerCell] setImage:[NSImage imageNamed:#"sampleHeader"]];
If I use the overridden subclass of headerview, I was not able to view the images or text in the header cell.Please provide me any pointers to solve this issue.
I was able to insert images and text by subclassing the NSTableHeaderCell.How to increase height of the NSTableHeaderView?
If I subclass both NSTableHeaderView and NSTableHeaderCell , was not able to view anything in the
headercell.I used the following code for setting headerview and headercell
[tableView setHeaderView:CustomHeaderView];
[tableColumn setHeaderCell:[[[CustomHeaderTableCell alloc] initImageCell:
[NSImage imageNamed:#"sample"]]autorelease]];
I have the same issue as given in the below url
http://lists.apple.com/archives/cocoa-dev/2002/Jun/msg00331.html
You don't need to subclass NSTableHeaderView.
I was able to change the height of the header view using the following snippet in the controller class:
-(void)awakeFromNib {
NSRect frame = tableView.headerView.frame;
frame.size.height = 26;
tableView.headerView.frame = frame;
}
It should be noted that the scroll view takes care of the layout. It automatically changes the frame of the headerView as necessary, but leaves the height intact. Resizing the clip view etc as suggested in the other answer is not necessary.
You can also create a NSTableHeaderView object, initialize it with a frame(rect with height and width) and set that NSTableHeaderView object to your table view.
NSTableHeaderView *tableHeaderView = [[NSTableHeaderView alloc] initWithFrame:NSMakeRect(0, 0, 120, 60)];
[myTableView setHeaderView:tableHeaderView];
[tableHeaderView release];
Following link helped me in solving the issue.
http://lists.apple.com/archives/cocoa-dev/2003/Feb/msg00676.html
You need to set the Frame for NSClipView, NSTableHeaderView and the CornerView
This is how I implemented the same in Code.
for(NSView * subview in [topScrollView subviews])
{
for(NSView * subSubView in [subview subviews])
{
if([[subSubView className] isEqualToString:#"NSTableHeaderView"] && [[subview className] isEqualToString:#"NSClipView"])
{
[subSubView setFrameSize:NSMakeSize(subSubView.frame.size.width, subSubView.frame.size.height+5)];//HeaderView Frame
[subview setFrameSize:NSMakeSize(subview.frame.size.width, subview.frame.size.height+5)];//ClipView Frame
}
}
if ([[subview className] isEqualToString:#"_NSCornerView"])
{
[subview setFrameSize:NSMakeSize(subview.frame.size.width, subview.frame.size.height+5)]; //CornerView Frame
}
}

Initial frame to use for UITableViewCell's backgroundView

I'm currently initializing my UITableViewCell's backgroundView's frame with self.frame. This seems to work fine for device orientation changes (cell background fills entire cell, looks fine etc). What's a better frame to use (if any)?
Edit #1: I've also initialized the backgroundView with CGRectZero as the frame. This seems to make no difference (UITableViewCells and backgroundViews function just fine in all interface orientations).
I've also tested setting the autoresizingMask property of the backgroundView. This made no difference either. I'd just like to understand what (if anything) is affected by the backgroundViews initial frame.
Assuming that you are trying to add a UIImageView as backgroundView and that you are trying to resize that imageView, here's my experience:
It seems to be impossible to change the frame of UITableViewCell.backgroundView (or at least not a thing Apple recommends, hence it's not mentioned in the documentation). To use a custom sized UIImageView, eg with a resizable UIImage, as background in a UITableViewCell, I do the following:
1) Create a UIImageView and set its image property to an image of your wish.
2) Add the UIImageView as a subview of the UITableViewCell using the addSubview: message.
3) Send the UIImageView to the back using sendSubviewToBack: message.
This puts your UIImageView behind any other added subviews and you are now able to manipulate the frame of your 'backgroundView' (aka the imageview).
To make sure the imageview will fit the tableViewCell's frame, use cell.frame's height and width properties when calculating the height of your imageview.
If you develop custom table view cell the solution is to adjust the frame in layoutSubviews method. Here is custom UITableViewCell from one of my projects, I needed 10 points margin from left:
#import "TETopicCell.h"
#import "UIColor+Utils.h"
#implementation TETopicCell
#synthesize topicTitleLabel = _topicTitleLabel;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
UIImageView *bgImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"theme_btn_yellow"]];
bgImageView.contentMode = UIViewContentModeTopLeft;
bgImageView.frame = CGRectMake(0.0f, 0.0f, 239.0f, 42.0f);
self.backgroundView = bgImageView;
_topicTitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(46.0f, 0.0f, 206.0f, 42.0f)];
_topicTitleLabel.backgroundColor = [UIColor clearColor];
_topicTitleLabel.textColor = [UIColor colorWithR:116 G:74 B:1];
[self.contentView addSubview:_topicTitleLabel];
}
return self;
}
- (void)layoutSubviews
{
[super layoutSubviews];
// update frame here
self.backgroundView.frame = CGRectOffset(self.backgroundView.frame, 10.0f, 0.0f);
// and here
if (self.selectedBackgroundView){
self.selectedBackgroundView.frame = CGRectOffset(self.selectedBackgroundView.frame, 10.0f, 0.0f);
}
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
if (selected) {
UIImageView *selectedImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"theme_btn_red"]];
selectedImageView.contentMode = UIViewContentModeTopLeft;
selectedImageView.frame = CGRectMake(0.0f, 0.0f, 239.0f, 42.0f);
self.selectedBackgroundView = selectedImageView;
[_topicTitleLabel setTextColor:[UIColor colorWithR:255 G:211 B:211]];
}
else {
self.selectedBackgroundView = nil;
[_topicTitleLabel setTextColor:[UIColor colorWithR:116 G:74 B:1]];
}
}
#end

How to disable a UITableView from scrolling up vertically?

I'm using EGORefreshTableHeader in conjunction with a static cell (defined in a nib) in a UITableView.
I'd like to be able to scroll the tableview down to trigger the EGORefreshTableHeader and thus refresh the data in the static cell. BUT, as the static cell is sized to fit perfectly in the window, I want to prevent folks from being able to scroll up.
Is there a way to do this?
Try this:
CGFloat a;
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
a = scrollView.contentOffset.y;
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (scrollView.contentOffset.y > a)
{
[scrollView setScrollEnabled:NO];
[scrollView setContentOffset:CGPointMake(0, a)];
}
[scrollView setScrollEnabled:YES];
}

Why do all backgrounds disappear on UITableViewCell select?

My current project's UITableViewCell behavior is baffling me. I have a fairly straightforward subclass of UITableViewCell. It adds a few extra elements to the base view (via [self.contentView addSubview:...] and sets background colors on the elements to have them look like black and grey rectangular boxes.
Because the background of the entire table has this concrete-like texture image, each cell's background needs to be transparent, even when selected, but in that case it should darken a bit. I've set a custom semi-transparent selected background to achieve this effect:
UIView *background = [[[UIView alloc] initWithFrame:self.bounds] autorelease];
background.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
background.opaque = NO;
[self setSelectedBackgroundView:background];
And although that yields the right look for the background, a weird side effect happens when I select the cell; all other backgrounds are somehow turnt off. Here's a screenshot. The bottom cell looks like it should and is not selected. The top cell is selected, but it should display the black and grey rectangular areas, yet they are gone!
Who knows what's going on here and even more important: how can I correct this?
What is happening is that each subview inside the TableViewCell will receive the setSelected and setHighlighted methods. The setSelected method will remove background colors but if you set it for the selected state it will be corrected.
For example if those are UILabels added as subviews in your customized cell, then you can add this to the setSelected method of your TableViewCell implementation code:
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
self.textLabel.backgroundColor = [UIColor blackColor];
}
where self.textLabel would be whatever those labels are that are shown in the picture above
I'm not sure where your adding your selected view, I usually add it in the setSelected method.
Alternatively, you can subclass the UILabel and override the setHighlighted method like so:
-(void)setHighlighted:(BOOL)highlighted
{
[self setBackgroundColor:[UIColor blackColor]];
}
The cell highlighting process can seem complex and confusing if you don't know whats going on. I was thoroughly confused and did some extensive experimentation. Here's the notes on my findings that may help somebody (if anyone has anything to add to this or refute then please comment and I will endeavour to confirm and update)
In the normal “not selected” state
The contentView (whats in your XIB unless you coded it otherwise) is drawn normally
The selectedBackgroundView is HIDDEN
The backgroundView is visible (so provided your contentView is transparent you see the backgroundView or (if you have not defined a backgroundView you'll see the background colour of the UITableView itself)
A cell is selected, the following occurs immediately with-OUT any animation:
All views/subviews within the contentView have their backgroundColor cleared (or set to transparent), label etc text color's change to their selected colour
The selectedBackgroundView becomes visible (this view is always the full size of the cell (a custom frame is ignored, use a subview if you need to). Also note the backgroundColor of subViews are not displayed for some reason, perhaps they're set transparent like the contentView). If you didn't define a selectedBackgroundView then Cocoa will create/insert the blue (or gray) gradient background and display this for you)
The backgroundView is unchanged
When the cell is deselected, an animation to remove the highlighting starts:
The selectedBackgroundView alpha property is animated from 1.0 (fully opaque) to 0.0 (fully transparent).
The backgroundView is again unchanged (so the animation looks like a crossfade between selectedBackgroundView and backgroundView)
ONLY ONCE the animation has finished does the contentView get redrawn in the "not-selected" state and its subview backgroundColor's become visible again (this can cause your animation to look horrible so it is advisable that you don't use UIView.backgroundColor in your contentView)
CONCLUSIONS:
If you need a backgroundColor to persist through out the highlight animation, don't use the backgroundColor property of UIView instead you can try (probably with-in tableview:cellForRowAtIndexPath:):
A CALayer with a background color:
UIColor *bgColor = [UIColor greenColor];
CALayer* layer = [CALayer layer];
layer.frame = viewThatRequiresBGColor.bounds;
layer.backgroundColor = bgColor.CGColor;
[cell.viewThatRequiresBGColor.layer addSublayer:layer];
or a CAGradientLayer:
UIColor *startColor = [UIColor redColor];
UIColor *endColor = [UIColor purpleColor];
CAGradientLayer* gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = viewThatRequiresBGColor.bounds;
gradientLayer.colors = #[(id)startColor.CGColor, (id)endColor.CGColor];
gradientLayer.locations = #[[NSNumber numberWithFloat:0],[NSNumber numberWithFloat:1]];
[cell.viewThatRequiresBGColor.layer addSublayer:gradientLayer];
I've also used a CALayer.border technique to provide a custom UITableView seperator:
// We have to use the borderColor/Width as opposed to just setting the
// backgroundColor else the view becomes transparent and disappears during
// the cell's selected/highlighted animation
UIView *separatorView = [[UIView alloc] initWithFrame:CGRectMake(0, 43, 1024, 1)];
separatorView.layer.borderColor = [UIColor redColor].CGColor;
separatorView.layer.borderWidth = 1.0;
[cell.contentView addSubview:separatorView];
When you start dragging a UITableViewCell, it calls setBackgroundColor: on its subviews with a 0-alpha color. I worked around this by subclassing UIView and overriding setBackgroundColor: to ignore requests with 0-alpha colors. It feels hacky, but it's cleaner than any of the other solutions I've come across.
#implementation NonDisappearingView
-(void)setBackgroundColor:(UIColor *)backgroundColor {
CGFloat alpha = CGColorGetAlpha(backgroundColor.CGColor);
if (alpha != 0) {
[super setBackgroundColor:backgroundColor];
}
}
#end
Then, I add a NonDisappearingView to my cell and add other subviews to it:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
UIView *background = [cell viewWithTag:backgroundTag];
if (background == nil) {
background = [[NonDisappearingView alloc] initWithFrame:backgroundFrame];
background.tag = backgroundTag;
background.backgroundColor = backgroundColor;
[cell addSubview:background];
}
// add other views as subviews of background
...
}
return cell;
}
Alternatively, you could make cell.contentView an instance of NonDisappearingView.
My solution is saving the backgroundColor and restoring it after the super call.
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
UIColor *bgColor = self.textLabel.backgroundColor;
[super setSelected:selected animated:animated];
self.textLabel.backgroundColor = bgColor;
}
You also need to do the same thing with -setHighlighted:animated:.
Found a pretty elegant solution instead of messing with the tableView methods. You can create a subclass of UIView that ignores setting its background color to clear color. Code:
class NeverClearView: UIView {
override var backgroundColor: UIColor? {
didSet {
if UIColor.clearColor().isEqual(backgroundColor) {
backgroundColor = oldValue
}
}
}
}
Obj-C version would be similar, the main thing here is the idea
I created a UITableViewCell category/extension that allows you to turn on and off this transparency "feature".
You can find KeepBackgroundCell on GitHub
Install it via CocoaPods by adding the following line to your Podfile:
pod 'KeepBackgroundCell'
Usage:
Swift
let cell = <Initialize Cell>
cell.keepSubviewBackground = true // Turn transparency "feature" off
cell.keepSubviewBackground = false // Leave transparency "feature" on
Objective-C
UITableViewCell* cell = <Initialize Cell>
cell.keepSubviewBackground = YES; // Turn transparency "feature" off
cell.keepSubviewBackground = NO; // Leave transparency "feature" on
Having read through all the existing answers, came up with an elegant solution using Swift by only subclassing UITableViewCell.
extension UIView {
func iterateSubViews(block: ((view: UIView) -> Void)) {
for subview in self.subviews {
block(view: subview)
subview.iterateSubViews(block)
}
}
}
class CustomTableViewCell: UITableViewCell {
var keepSubViewsBackgroundColorOnSelection = false
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
// MARK: Overrides
override func setSelected(selected: Bool, animated: Bool) {
if self.keepSubViewsBackgroundColorOnSelection {
var bgColors = [UIView: UIColor]()
self.contentView.iterateSubViews() { (view) in
guard let bgColor = view.backgroundColor else {
return
}
bgColors[view] = bgColor
}
super.setSelected(selected, animated: animated)
for (view, backgroundColor) in bgColors {
view.backgroundColor = backgroundColor
}
} else {
super.setSelected(selected, animated: animated)
}
}
override func setHighlighted(highlighted: Bool, animated: Bool) {
if self.keepSubViewsBackgroundColorOnSelection {
var bgColors = [UIView: UIColor]()
self.contentView.iterateSubViews() { (view) in
guard let bgColor = view.backgroundColor else {
return
}
bgColors[view] = bgColor
}
super.setHighlighted(highlighted, animated: animated)
for (view, backgroundColor) in bgColors {
view.backgroundColor = backgroundColor
}
} else {
super.setHighlighted(highlighted, animated: animated)
}
}
}
All we need is to override the setSelected method and change the selectedBackgroundView for the tableViewCell in the custom tableViewCell class.
We need to add the backgroundview for the tableViewCell in cellForRowAtIndexPath method.
lCell.selectedBackgroundView = [[UIView alloc] init];
Next I have overridden the setSelected method as mentioned below.
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
UIImageView *lBalloonView = [self viewWithTag:102];
[lBalloonView setBackgroundColor:[[UIColor hs_globalTint] colorWithAlphaComponent:0.2]];
UITextView *lMessageTextView = [self viewWithTag:103];
lMessageTextView.backgroundColor = [UIColor clearColor];
UILabel *lTimeLabel = [self viewWithTag:104];
lTimeLabel.backgroundColor = [UIColor clearColor];
}
Also one of the most important point to be noted is to change the tableViewCell selection style. It should not be UITableViewCellSelectionStyleNone.
lTableViewCell.selectionStyle = UITableViewCellSelectionStyleGray;

Custom NSWindow content margin causes mess up with autoresizing mask

I'm currently using the method shown in this Cocoa with Love article to create a custom NSWindow subclass. As in the example, I needed to have a roughly 10px margin around the content of the window in order to draw an arrow (I'm creating a popover style window). I had to have the margin around the entire window instead of just the side with the arrow on it because I wanted to be able to change the arrow position without having to reposition the content.
To summarize, the method I'm using to do this is (relevant code is at the bottom):
Override the contentRectForFrameRect: and frameRectForContentRect:styleMask: methods of NSWindow to add the padding around the content:
Sets the custom drawn frame view of the window as the contentView and then overrides the setter and getter for the contentView so that the view that is passed in is added as a subview of the frame view.
The problem is that the autoresizing masks of views inside the actual content view of the window are completely messed up. Here is how I'm setting up the content in interface builder:
Here's how the autoresizing mask of the table view scroll view is set up:
And here's how the text label's autoresizing mask is set:
And here's what the result looks like in-app:
Relevant code (derived from the aforementioned article)
#define CONTENT_MARGIN 10.0
- (NSRect)contentRectForFrameRect:(NSRect)windowFrame
{
windowFrame.origin = NSZeroPoint;
return NSInsetRect(windowFrame, CONTENT_MARGIN, ICONTENT_MARGIN);
}
- (NSRect)frameRectForContentRect:(NSRect)contentRect
{
return NSInsetRect(contentRect, -CONTENT_MARGINT, -CONTENT_MARGIN);
}
+ (NSRect)frameRectForContentRect:(NSRect)contentRect
styleMask:(NSUInteger)windowStyle
{
return NSInsetRect(contentRect, -CONTENT_MARGIN, -CONTENT_MARGIN);
}
- (NSView*)contentView
{
return _popoverContentView;
}
- (void)setContentView:(NSView *)aView
{
if ([_popoverContentView isEqualTo:aView]) { return; }
NSRect bounds = [self frame];
bounds.origin = NSZeroPoint;
SearchPopoverWindowFrame *frameView = [super contentView];
if (!frameView) {
frameView = [[[SearchPopoverWindowFrame alloc] initWithFrame:bounds] autorelease];
[super setContentView:frameView];
}
if (_popoverContentView) {
[_popoverContentView removeFromSuperview];
}
_popoverContentView = aView;
[_popoverContentView setFrame:[self contentRectForFrameRect:bounds]];
[_popoverContentView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
[frameView addSubview:_popoverContentView];
}
I thought that maybe the popover content was going over the margins somehow, so I drew a border around the content view, but no, everything is as should be. The only issue is that the autoresizing masks of the label and table view inside the content view do not work as they should. Any advice is greatly appreciated.
EDIT: If anyone's interested, I've open-sourced the complete code for this popover window/controller on github as INPopoverController. Includes a sample project in case you want to try and reproduce the issue.
-( void )scaleWindowForHeight:( float )height
{
if (height > 22)
{
NSWindow* window = [self window];
NSRect old_window_frame = [window frame];
NSRect old_content_rect = [window contentRectForFrameRect: old_window_frame];
NSSize new_content_size = NSMakeSize( old_window_frame.size.width, height );
// need to move window by Y-axis because NSWindow origin point is at lower side:
NSRect new_content_rect = NSMakeRect( NSMinX( old_content_rect ), NSMaxY( old_content_rect ) - new_content_size.height, new_content_size.width, new_content_size.height );
NSRect new_window_frame = [window frameRectForContentRect: new_content_rect];
[window setFrame: new_window_frame display:YES animate: [window isVisible] ];
}
else
NSLog(#"window size too small");
}