Adjusting the height of a wkwebview programmatically - html

This is my first question on Stack Overflow. I just started learning swift programming and got sucked into something.
I followed IAP tutorials on YouTube and successfully implemented AdMob banners and interstitial ads in my app. I was also able to turn off ads using the IAP. My question is:
I have a view in which I have two UI elements (WKWebViewand a GADBannerView). The WKWebView element covers 90% of the screen starting from x:0,y:0, whereas the GADBannerView element covers 10%. I turned off ads and hid the GADBannerView element using IAP.
Now I want to dynamically/programmatically adjust the WKWebView size to fill the entire screen, i.e 100%. In other words, I want the WKWebView element to extend over the hidden GADBannerView element.
This is because hiding the GADBannerView leaves a blank field which is not cool to the view and the WKWebView looks truncated.
Please note that neither of the views are subviews. Both are independent views added separately. I understand that I can initially make the web view fill entire screen, add the GADBannerView on top of it, and when I remove ads and hid the GADBannerView, the web view will fill screen. That is not what I want because some content of the web view can not be seen using this approach. If I have a button at the end of HTML page that loads on the web view, this button can not be clicked because it will always be behind the gad banner view even when scrolling reached the bottom. Yes, you can scroll and hold to see the button, but once you release it, it will go back down.
So as a recap, I have two separate views and want to hid one and extend the length of the other to cover the entire screen.
Please tell me how to achieve that.
thirdBannerView.isHidden = true //Hide the banner view
//then code below to increase the size of the web view to equal device //screen width and height i.e full screen.
func webViewDidFinishLoad(webView: WKWebView) {
//let screenBounds = UIScreen.main.bounds
// let heightq = screenBounds.height
//let widthq = screenBounds.width
//webView.frame.size.height = heightq
//webView.frame.size = webView.sizeThatFits(CGSize.zero)
//webView.frame = CGRectMake(0, 0, widthq, heightq);
webView.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)
}
This code is not effective at all as nothing changes. Please let me know how to achieve this.

This particular scenario looks promising for applying UIStackview. Add your two view ( WKWebview and GADBannerView). apply fixed height for the GADBannerview. Whenever necessary just hide the GADBannerview.
Sample code
class StackviewController : UIViewController {
let stackview: UIStackView = {
let view = UIStackView()
view.axis = .vertical
view.distribution = .fill
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
// Your WKWebview here
let sampleWKWebView: UIView = {
let view = UIView()
view.backgroundColor = .red
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
// Your GADBannerView here
let sampleGADBannerView: UIView = {
let view = UIView()
view.backgroundColor = .green
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
}
func setupViews() {
view.addSubview(stackview)
stackview.addArrangedSubview(sampleWKWebView)
stackview.addArrangedSubview(sampleGADBannerView)
NSLayoutConstraint.activate([
stackview.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0.0),
stackview.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0.0),
stackview.topAnchor.constraint(equalTo: view.topAnchor, constant: 0.0),
stackview.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0.0),
sampleGADBannerView.heightAnchor.constraint(equalToConstant: 100.0)
])
// Enable this line to hide the GADBannerView
// sampleGADBannerView.isHidden = true
}
}
Here is the output
I use two UIView to represent the WKWebView & GADBannerView. In the sample code uncomment the following to hide the bottom banner like green view.
sampleGADBannerView.isHidden = true

Related

Playing HTML video while taking a screenshot (drawHierarchy)

I'm having issues with thumbnailWebView.drawHierarchy(in:,afterScreenUpdates:) method and loading HTML code with a local video in it.
The issue comes when I capture the webview to get a tumbnail and then I click the video on the webview, the video start running (because the sound works) but the image keeps black. Also if I click the full screen option the video shows right.
The code is simple. Image capture:
UIGraphicsBeginImageContextWithOptions(self.thumbnailWebView.bounds.size, true, UIScreen.main.scale)
thumbnailWebView.drawHierarchy(in: thumbnailWebView.bounds, afterScreenUpdates: true)
let screenShot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext()
Init WKWebView:
let conf = WKWebViewConfiguration()
self.thumbnailWebView = WKWebView(frame: CGRect(x: 0, y: 0, width: 768, height: 1024), configuration: conf)
thumbnailGeneratorView.addSubview(self.thumbnailWebView)
thumbnailControl = ThumbnailControl()
thumbnailControl.delegate = self
thumbnailWebView.uiDelegate = thumbnailControl
thumbnailWebView.navigationDelegate = thumbnailControl
Loading the HTML:
self.thumbnailWebView.loadFileURL(contentURL!, allowingReadAccessTo: contentURL!.deletingLastPathComponent())
If I comment the drawHierarchy line, the video shows right.
I have also tried to use view.layer.renderInContext(UIGraphicsGetCurrentContext()!) instead drawHierarchy but the screenshot obtained is white.

Swift iOS -Programmatic RootViewController is Light Gray?

I'm just getting in to programmatic vc's with no more storyboards and I'm following YouTube's LetsBuildThatApp by Brian Voong for guidance https://youtu.be/NJxb7EKXF3U?list=PL0dzCUj1L5JHDWIO3x4wePhD8G4d1Fa6N.
I followed all the directions and for some reason when I launch my app I get this light gray haze over my screen and I can't figure out why? I can faintly see the navigation title and blue background but it's covered by a faded layer.
Step 1:
I deleted my storyboard file and sunder the General Tab under Deployment Info I deleted "Main" from Main Interface.
Step 2:
I changed my ProjectNavigator file to FeedController then Changed the file accordingly
import UIKit
class FeedController: UICollectionViewController {
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "Facebook Feed"
collectionView?.backgroundColor = UIColor.white
}
}
Step 3:
In AppDelegate I added a NavVC and made FeedVC it's root and made the NavVC the Window's root. I also change the NavBar and StatusBar color
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
let feedController = FeedController(collectionViewLayout: UICollectionViewFlowLayout())
let navVC = UINavigationController(rootViewController: feedController)
window?.rootViewController = navVC
UINavigationBar.appearance().tintColor = UIColor.blue
UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
application.statusBarStyle = .lightContent
return true
}
Step 4:
In info.plist I set View controller-based status bar appearance to NO
I can't figure out why I get this light gray haze over my screen
What am I missing here?
It looks like you are configuring the tintColor instead of the barTintColor. The tintColor changes the color for the navigation buttons and the barTintColor adjusts the navigation bar background color. You can watch this video for more details on customizing navigation bar appearance.
https://www.youtube.com/watch?v=RO8_mqRJO-4

Swipe from UITableView to UIButton via UIFocusGuide not working

I’m having trouble swiping right to move focus from a UITableView to a UIButton that is to the right and below the tableview. I’ve set up a UIFocusGuide and I believe I’ve got the geometry correct. (See attached screenshot, created using Pod VisualFocusGuide.)
When I use the built-in QuickLook on the UIFocusUpdateContext, it shows only the table view focus (the highlighted row in one color, and the other rows in another color), but that might be because I can only ever get focus in the table view, so perhaps that context is limited to the table.
I’ve seen a recommendation elsewhere to associate the focus guide with the button instead of the controller’s view, but that didn’t work. Out of desperation, I also tried associating the focus guide with the tableview, but still no luck.
Here are the pertinent methods. Any light anyone can shed will be appreciated! Thanks!
override func viewDidLoad() {
super.viewDidLoad()
self.view.addLayoutGuide(focusGuide)
self.focusGuide.widthAnchor.constraint(equalTo: self.infoButton.widthAnchor).isActive = true
self.focusGuide.heightAnchor.constraint(equalTo: self.tableView.heightAnchor).isActive = true
self.focusGuide.topAnchor.constraint(equalTo: self.tableView.topAnchor).isActive = true
self.focusGuide.leftAnchor.constraint(equalTo: self.infoButton.leftAnchor).isActive = true
self.focusGuide.preferredFocusEnvironments = [self.infoButton]
}
override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
super.didUpdateFocus(in: context, with: coordinator)
guard let nextFocusedView = context.nextFocusedView else { return }
// When the focus engine focuses on the focus guide, we can programmatically tell it which element should be focused next.
switch nextFocusedView {
case self.tableView:
self.focusGuide.preferredFocusEnvironments = [self.infoButton]
case self.infoButton:
self.focusGuide.preferredFocusEnvironments = [self.tableView]
default:
self.focusGuide.preferredFocusEnvironments = []
}
}
I've just gotten this to work. I added another focus guide below the table view, to the left of the button. I sized it to be the width of the tableview and the height of the button. I made its preferredFocusEnvironment the tableView. But that in itself wasn't enough. I then removed the didUpdateFocus method, and left and right swiping started working! Here's the resulting code:
override func viewDidLoad() {
super.viewDidLoad()
self.view.addLayoutGuide(focusGuide1)
self.focusGuide1.topAnchor.constraint(equalTo: self.tableView.topAnchor).isActive = true
self.focusGuide1.leftAnchor.constraint(equalTo: self.infoButton.leftAnchor).isActive = true
self.focusGuide1.heightAnchor.constraint(equalTo: self.tableView.heightAnchor).isActive = true
self.focusGuide1.widthAnchor.constraint(equalTo: self.infoButton.widthAnchor).isActive = true
self.focusGuide1.preferredFocusEnvironments = [self.infoButton]
self.view.addLayoutGuide(focusGuide2)
self.focusGuide2.topAnchor.constraint(equalTo: self.infoButton.topAnchor).isActive = true
self.focusGuide2.leftAnchor.constraint(equalTo: self.tableView.leftAnchor).isActive = true
self.focusGuide2.heightAnchor.constraint(equalTo: self.infoButton.heightAnchor).isActive = true
self.focusGuide2.widthAnchor.constraint(equalTo: self.tableView.widthAnchor).isActive = true
self.focusGuide2.preferredFocusEnvironments = [self.tableView]
}

How to set UIWebView initial position?

How to set the initial focus in a HTML page using UIWebView. For example, below is the HTML page. If i load this in UIWebView, it shows from (0,0) coordinates of a HTML view. But i want to change the starting position as described in the below image. I tried to change the offset, but no use.
webView.scrollView.contentOffset = CGPointMake(100, 100).
You probably shouldn't hard code this because for one reason, it's hard-coded. If google, or whatever website you want to display alters their layout your positions will be obsolete. And you will have to resubmit your entire app just to off-set this.
My recommendation is use auto layout and 'scales page to fit' for the UIWebView.
But your code is accurate. Make sure you put it in webViewDidFinishLoad: or viewDidLoad and your UIWebViewDelegate & UIScrollViewDelegate are added to your header file and called in your implementation file :
self.webView.delegate = self;
self.webView.scrollView.delegate = self;
Place the UIWebView into a subview. A generic UIView will work.
When instantiating the UIWebView, give it screen bounds with a slightly lower width than the containing UIView. Weird, I know.
Set the UIWebView's contentOffset in the webViewDidFinishLoad method of your UIWebViewDelegate
The following code works for me, in Xcode 6.1.1. To test, just make this ViewController class the root view controller for your app:
import UIKit
class ViewController: UIViewController, UIWebViewDelegate {
override func loadView () {
let screenBounds : CGRect = UIScreen.mainScreen().bounds
var slimmerBounds : CGRect = UIScreen.mainScreen().bounds
slimmerBounds.size.width = slimmerBounds.size.width - 1
let webView = UIWebView(frame: slimmerBounds)
let url = NSURL (string: "http://google.com/")
let req = NSURLRequest(URL: url!)
webView.loadRequest(req)
webView.delegate = self;
let contentView = UIView(frame: screenBounds)
contentView.addSubview(webView)
self.view = contentView
}
func webViewDidFinishLoad(webView: UIWebView) {
webView.scrollView.contentOffset = CGPointMake(0, 100)
webView.bounds = UIScreen.mainScreen().bounds
}
}
By the way ... this will set the initial position of all URLs loaded into this Web view. If you only want to position the first page, you'll need to add some additional logic to webViewDidFinishLoad

UISplitView with toolbar/tabbar at bottom of detail view

So here goes. I started with a standard out of the box splitview application for iPad. Root view left and detail view to the right. Detail view has it's toolbar at the top.
What I would like to add is a tab bar to the bottom of the detail view and have the tabs load in the details view, between the toolbar tabbar.
Here is the problem, do I add another view between them to load the tabs into, if so how do I get it resize and respect the toolbar and tabbar heights.
Clear?
Hope someone can point me in the right direction. Examples would be great, every example on the web seems to just be out of the box hello world style.
Yes the answer is really very simple. UITabBarControllers like SplitViewControllers were intended by Apple to only ever be the Root View Controller and hence you cannot nest a TabBarController in another view, but you can nest a UITabBar in a view, however.
I added the Tabbar to the details view at the bottom, a Navigation bar at the top and then a placeholder view between them. All in Interface Builder!, You will want to switch everything on with the autosize on the Placeholder view.
Next, Implement the UITabBarDelegate. For this you will need:
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item {
from that you can use item.tag which if you give each item a unique tag in Interface Builder will let you know which tab the user clicked. I setup defined values for mine:
#define VIEW_TAB_A 0
#define VIEW_TAB_B 1
#define VIEW_TAB_C 2
Then you will then want to... well best I just let you see
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item {
[self switchToView:item];
}
- (void) switchToView : (UITabBarItem*) item {
if( currentViewController != nil ) {
[currentViewController viewWillDisappear:NO];
[currentViewController.view removeFromSuperview];
}
switch(item.tag) {
case VIEW_TAB_A:
currentViewController = self.viewA;
break;
case SCAN_VIEW_TAB_B:
currentViewController = self.viewB;
break;
case PROMOTIONS_VIEW_TAB_C:
currentViewController = self.viewC;
break;
}
UIView *aView = currentViewController.view;
aView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
aView.frame = placeholderView.frame;
[currentViewController viewWillAppear:NO];
[self.view insertSubview:aView aboveSubview:placeholderView];
if( currentViewController != nil ) {
[currentViewController viewDidDisappear:NO];
}
[currentViewController viewDidAppear:NO];
}
Remember to alloc the views (viewA, viewB, viewC) first in you viewDidLoad and obviously release in dealloc. Also take note of the autoresizingMask!
Hope this helps others.