Overlay not scrolling with UITableView - iOS - objective-c

I have a UITableView class that uses the following methods to call a loading overlay when going to the next screen. The problem is that this loading screen does not scroll with the list... So if you scroll a little bit and click on something, the loading screen doesn't show (because it's at the top). How can I get the loading screen to stay on top of the UITableView at all times? Please know that each UITableView is contained within a UINavBar, which is contained within a UITabBar. Here is my code:
-(void)createLoadScreen
{
CGRect screenRect = [self.view bounds];
CGRect overlayFrame = CGRectMake(0.0, 0.0, screenRect.size.width, screenRect.size.height);
overlay = [[UIView alloc] initWithFrame:overlayFrame];
overlay.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.7];
CGRect frame = CGRectMake(screenRect.size.width / 2 - 25.0, screenRect.size.height / 2 - 70, 25.0, 25.0);
loading = [[UIActivityIndicatorView alloc] initWithFrame:frame];
[loading setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhiteLarge];
[loading sizeToFit];
loading.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleRightMargin |
UIViewAutoresizingFlexibleTopMargin |
UIViewAutoresizingFlexibleBottomMargin);
loading.hidesWhenStopped = YES;
[overlay addSubview:loading];
}
-(void)showActivityIndicator
{
[self.view addSubview:overlay];
[loading startAnimating];
}
-(void)removeActivityIndicator {
[loading stopAnimating];
[overlay removeFromSuperview];
}

Are you using a UITableViewController?
You should be able to fix your issue by adding the overlay view to the table's superview instead of the table view itself. This way your overlay is actually above and separate from your scrolling table view
-(void)showActivityIndicator
{
[[self.view superview] addSubview:overlay];
[loading startAnimating];
}

Related

Display issue with customized UINavigationBar

I'm currently encountering an issue with the customized navigation bar of my app, especially on iPad Pro and iPad.
I've extended UINavigationBar to create a personalized top bar.
I'm only using Objectiv-C, and here is the initialization function :
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:(NSCoder *)aDecoder];
if (self)
{
[self setTranslucent:FALSE];
UIImageView *mylogo = [[UIImageView alloc] initWithImage:[self imageWithImage:[UIImage imageNamed:#"minilogo.png"] scaledToSize:CGSizeMake(200, 25)]];
[self.topItem setTitleView:mylogo];
menuButton = [UIButton buttonWithType:UIButtonTypeCustom];
menuButton.frame = CGRectMake(0, 0, 44, 44);
[menuButton setImage:[UIImage imageNamed:#"menuButton.png"] forState:UIControlStateNormal];
[menuButton setContentMode:UIViewContentModeCenter];
CALayer *menuBorder = [CALayer layer];
[menuBorder setFrame:CGRectMake(43, 0, 1, 44)];
[menuBorder setBackgroundColor:[[UIColor blackColor] CGColor]];
[menuButton.layer addSublayer:menuBorder];
[self.topItem setLeftBarButtonItem: [[UIBarButtonItem alloc] initWithCustomView:menuButton]];
searchButton = [UIButton buttonWithType:UIButtonTypeCustom];
searchButton.frame = CGRectMake(0, 0, 44, 44);
UIImage *searchImage = [self imageWithImage:[UIImage imageNamed:#"boutonRecherche.png"] scaledToSize:CGSizeMake(44, 44)];
[searchButton setBackgroundImage:searchImage forState:UIControlStateNormal];
[searchButton setContentMode:UIViewContentModeCenter];
CALayer *searchBorder = [CALayer layer];
[searchBorder setFrame:CGRectMake(0, 0, 1, 44)];
[searchBorder setBackgroundColor:[[UIColor blackColor] CGColor]];
[searchButton.layer addSublayer:searchBorder];
[self.topItem setRightBarButtonItem:[[UIBarButtonItem alloc] initWithCustomView:searchButton]];
if (#available(iOS 15.0, *))
{
UINavigationBarAppearance *navBarApparance = [[UINavigationBarAppearance alloc] init];
[navBarApparance setBackgroundImage:[UIImage imageNamed:#"fd_entete.png"]];
[self setStandardAppearance:navBarApparance];
[self setCompactAppearance:navBarApparance];
[self setScrollEdgeAppearance:navBarApparance];
}
else
{
[self setOpaque:YES];
[self setBackgroundImage:[UIImage imageNamed:#"fd_entete.png"] forBarMetrics:UIBarMetricsDefault];
}
}
return self;
}
My navigation bar is added to the view using the storyboard and I specifying its class name in the identity inspector tab.
I've set layout constraints so the content of my view is right under this navigation bar.
Here is a sample with a simple controller having the navigation bar and a webview beneath :
The issue I'm having only concerns iPads. Here is a screenshot of how it looks like on an iPad pro :
(the grey rect is just to illustrate that I've shorten the screenshot)
But surprisingly, the navigation bar render correctly if the view beneath is a UITableView, but it still have the border issue for the buttons - understand here that the button border is missing some pixels on top and bottom :
(it is also how the nav bar looks like on an iPad for any view controller)
In comparison, I don't have the issue on iPhones :
Any help is appreciated.

lag scrolling scrollview with tableview inside it

I have important problem with UIScrollView.
I want to make one app like yahoo weather and using this source code : BTGlassScrollView
in this source code exist one view with name "foregroundView" that is info view. this info view appear when scrolling my ScrollView from bottom to top.
now I make and add my ScrollView by this code:
_viewScroller = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width + 2*blackSideBarWidth, self.view.frame.size.height)];
[_viewScroller setPagingEnabled:YES];
[_viewScroller setDelegate:self];
[_viewScroller setShowsHorizontalScrollIndicator:NO];
[self.view addSubview:_viewScroller];
_glassScrollView1 = [[BTGlassScrollView alloc] initWithFrame:self.view.frame BackgroundImage:[UIImage imageNamed:#"background3"] blurredImage:nil viewDistanceFromBottom:0 foregroundView:[self customView]];
[_viewScroller addSubview:_glassScrollView1];
in my code I write [self customView] that make me info view and this is customView function:
- (UIView *)customView {
//this method is for make UITableView
[self makeTableBuy:[[self.tableDic objectForKey:#"person"] count]];
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, _tableBuy.frame.size.width, _tableBuy.frame.size.height)];
view.layer.cornerRadius = 3;
view.backgroundColor = [UIColor colorWithWhite:0 alpha:.3];
[view addSubview:_tableBuy];
return view;
}
- (UITableView*)makeTableBuy:(int)numberOfRow {
_tableBuy = [[UITableView alloc] initWithFrame:CGRectMake(0,0,self.view.frame.size.width,numberOfRow*TABLE_HEIGHT) style:UITableViewStyleGrouped];
[_tableBuy setTag:1];
[_tableBuy setBackgroundColor:[UIColor clearColor]];
_tableBuy.showsVerticalScrollIndicator = NO;
_tableBuy.separatorStyle = UITableViewCellSeparatorStyleNone;
_tableBuy.rowHeight = TABLE_HEIGHT;
_tableBuy.scrollEnabled = NO;
_tableBuy.delegate = self;
_tableBuy.dataSource = self;
return _tableBuy;
}
now When I'm scrolling my ScrollView my info view (my tableview) moving to top and appear but my scrolling have so lagging.
please guide me how to fix this lag???

Create a temporary HUD popup notification in Cocoa App

Im trying to have a window pop up to notify the user of an action, kind of like how the Flutter app shows a play/pause notification when a gesture is received.
This comes up for about two seconds and vanishes. The app itself is run from the menu bar so this pop up doesn't take control from whatever application is currently in focus but rather just shows on top of it and cannot be interacted with. I basically want to recreate exactly this. Say in the body of
- (void)popup:(id)sender {}
This is essentially very similar to a toast on android.
Edit: I looked closer at the flutter app and all it does is display two images (.png) one for the huge pause and another to indicate what application its in (in this case iTunes). Question now is how do I display an image like this.
You should take a look at this:
https://github.com/Foxnolds/MBProgressHUD-OSX
or Growl:
http://growl.info/documentation/developer/
To replicate this I added a 'HUD Window" from the interface builder which is just an NSPanel. I then added a image view to the panel and set the panel's colour to clear. I was then able to position the panel where I wanted and overlay the appropriate image.
I'm using this code:
static void showHud(NSString* text, int width, int height, CGFloat duration, int fontSize) {
NSWindow* window = [NSWindow new];
[window setFrame:NSMakeRect(0,0,width,height) display:NO];
[window center];
window.titleVisibility = NSWindowTitleHidden;
window.styleMask = NSWindowStyleMaskBorderless;
window.alphaValue = 0.9;
window.movableByWindowBackground = YES;
[window setLevel: NSStatusWindowLevel];
[window setBackgroundColor: [NSColor clearColor]];
[window setOpaque:NO];
//[window setHasShadow:NO];
[window makeKeyAndOrderFront:NSApp];
NSVisualEffectView *view = [[NSVisualEffectView new] initWithFrame:window.contentView.bounds];;
view.translatesAutoresizingMaskIntoConstraints = NO;
[view setBlendingMode:NSVisualEffectBlendingModeBehindWindow];
[view setMaterial:NSVisualEffectMaterialDark];
[view setState:NSVisualEffectStateActive];
//[view setAppearance:[NSAppearance appearanceNamed:NSAppearanceNameVibrantDark]];
//[view setWantsLayer:NO];
[view setWantsLayer:YES];
view.layer.cornerRadius = 16.;
//view.layer.shouldRasterize = YES;
//view.layer.rasterizationScale = 0.45;
view.layer.shadowOpacity = 0.1; //0.01;
view.layer.edgeAntialiasingMask = kCALayerTopEdge | kCALayerBottomEdge | kCALayerRightEdge | kCALayerLeftEdge;
[window.contentView addSubview:view];
//window.contentView = view;
NSTextField *label = [[NSTextField alloc] initWithFrame:view.bounds];
[label setBezeled:NO];
[label setDrawsBackground:NO];
[label setEditable:NO];
[label setSelectable:NO];
label.stringValue = text;
label.alignment = NSTextAlignmentCenter;
label.textColor = [NSColor whiteColor];
label.backgroundColor = [NSColor clearColor];
label.font = [NSFont fontWithName:#"Arial-BoldMT" size:fontSize];
//NSRect titleRect = [label titleRectForBounds:view.bounds];
NSSize cellSize = [label.cell cellSizeForBounds:view.bounds];
NSSize strSize = cellSize; // [label.attributedStringValue size];
NSRect frame = view.frame;
frame.origin.y = frame.size.height / 2 - strSize.height / 2;
frame.size.height = strSize.height;
label.frame = frame;
[view addSubview:label];
[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
context.duration = duration;
window.animator.alphaValue = 0.;
} completionHandler:^{
[window close];
}];
}

UIScrollView with UIImageView partially visible on screen

I have a UIScrollView with a UIImageView in order to enable zoom features.
The problem now is that the scrollView should be shown fullscreen (except the navigationBar), but it's shown with a weird "offset".
Due that images explains more than 1000 words, here it is:
The red rectangles are the weird offset that's being shown, while the image should take the whole view, but it's not. As you see,it's being cut instead.
I tried changing the frame, bounds etc but same result.
Here's my code:
- (void)viewDidLoad
{ [super viewDidLoad];
self.view.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
imageScrollView.bouncesZoom = YES;
imageScrollView.delegate = self;
imageScrollView.clipsToBounds = NO; // If set to yes, the image would be like the screen above
imageView = [[UIImageView alloc] init];
imageView.clipsToBounds = YES;
imageScrollView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin);
//activity indicator
UIActivityIndicatorView *activityIndicator = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge] autorelease];
activityIndicator.hidesWhenStopped = YES;
activityIndicator.hidden = NO;
activityIndicator.center = CGPointMake(self.imageView.frame.size.width /2, self.imageView.frame.size.height/2);
[activityIndicator startAnimating];
[imageView setImageWithURL:[NSURL URLWithString:tipImageString]
placeholderImage:nil options:SDWebImageProgressiveDownload
success:^(UIImage *image) { [activityIndicator stopAnimating];[activityIndicator removeFromSuperview]; }
failure:^(NSError *error) { [activityIndicator stopAnimating];[activityIndicator removeFromSuperview]; }];
[imageView addSubview:activityIndicator];
imageView.userInteractionEnabled = YES;
imageView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin);
imageView.center = [[imageScrollView window] center];
imageView.contentMode = UIViewContentModeScaleAspectFit;
[imageScrollView setContentMode:UIViewContentModeScaleAspectFit];
[imageScrollView addSubview:imageView];
imageScrollView.contentSize = self.imageView.image.size;
imageScrollView.decelerationRate = UIScrollViewDecelerationRateFast;
CGSize boundsSize = self.imageScrollView.bounds.size;
imageView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
CGRect frameToCenter = imageView.frame;
// center horizontally
if (frameToCenter.size.width < boundsSize.width)
frameToCenter.origin.x = (boundsSize.width - frameToCenter.size.width) / 2;
else
frameToCenter.origin.x = 0;
// center vertically
if (frameToCenter.size.height < boundsSize.height)
frameToCenter.origin.y = (boundsSize.height - frameToCenter.size.height) / 2;
else
frameToCenter.origin.y = 0;
imageView.frame = frameToCenter;
// calculate minimum scale to perfectly fit image width, and begin at that scale
float minimumScale = 0.50;//[imageScrollView frame].size.width / [imageView frame].size.width;
imageScrollView.maximumZoomScale = 5.0;
imageScrollView.minimumZoomScale = minimumScale;
imageScrollView.zoomScale = minimumScale;
[imageScrollView setContentMode:UIViewContentModeScaleAspectFit];
[imageView sizeToFit];
[imageScrollView setContentSize:CGSizeMake(imageView.frame.size.width, imageView.frame.size.height)];
}
I tried everything, but with no success!
I think that's something with frames but i can't figure out what.
Any help appreciated
#Pheel Glad that you find it due to CGAffineTransformMakeRotation of the image. This may change the coordinates.
Try to change the Image Resolution. Also, did you try visually placing the scroll view and then placing the image view in Interface Builder. After doing that, you can initialize it in a method such as ViewDidLoad
Why don't you just do:
... set-up imageView...
imageView.frame = imageScrollView.bounds;
imageView.contentMode = UIViewContentModeScaleAspectFit;
[imageScrollView addSubview:imageView];
You have a lot of code that is redundant or have cumulative effect in your method (multiple consecutive changes of frame/center, contentMode, contentSize...), which makes it hard to know what is causing what (probably the scroll view is clipping the image view, whose center is first based on the window coordinate instead of its superview coordinates, but finally not, because you redefine its frame...). You should probably start from scratch with some simpler code, depending on what you want exactly, and the configuration you start with (what is the scroll view frame for instance?).

Extending UIScrollView when it fills up with more content

Ok, so i got a scrollview to load when an user logs in to my application. When the user is authenticated, i need to create a scrollview programmatically. To do so, i have the following code:
[scrollView removeFromSuperview];
UIScrollView *view = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, applicationFrame.size.width, self.view.frame.size.height)];
view.backgroundColor = [UIColor greenColor];
//-- get the y-coordinate of the view
CGFloat viewCenterY = self.view.center.y;
//--calculate how much visible space is left
CGFloat freeSpaceHeight = applicationFrame.size.height - keyboardBounds.size.height;
//-- calculate how much the scrollview must scroll
CGFloat scrollAmount = viewCenterY - freeSpaceHeight / 2.0;
if(scrollAmount < 0) scrollAmount = 0;
//set the new scrollsize contentview
view.contentSize = CGSizeMake(applicationFrame.size.width, applicationFrame.size.height + keyboardBounds.size.height);
//scroll the scrollview
[view setContentOffset:CGPointMake(0, scrollAmount) animated:YES];
for(int v = 0; v < 15; v++){
CGFloat yCoord = v * 100;
UILabel *mijnLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, yCoord, 200, 50)];
mijnLabel.text = #"1337";
mijnLabel.font = [UIFont fontWithName:#"Verdana" size:20];
mijnLabel.textColor = [UIColor redColor];
[view addSubview:mijnLabel];
[mijnLabel release];
}
[self.view addSubview:view];
[view release];
}
How do i extend my view according to the amount of labels i added? I also want to know how i can make my scrollview fill up the entire screen.. My scrollview is now only filling up the screen when in portrait mode.
This is the login screen that gets removed:
[scrollView removeFromSuperview];
you need to keep track of numbers of label that you are adding into the scroll view. suppose if your label's height is 50 then take a variable and make a total of all label's height and give a new frame to your scroll view. like :
view.frame = CGRectmake(0,0,applicationFrame.size.width,totalHeightOfLabel);
[self.view addSubview:view];
[view release];
hope this will give a idea...