I have been working on a mainly text-based application with an Iadbanner in the bottom.
However as we all know, Iads aren't always there. So I would like to be able to dynamically update the height of my textView, so when the banner is hidden, the textView takes up the wasted space. And resize it when a banner is loaded.
Here's what I currently have for the Viewcontroller in question
import UIKit
import iAd
class DetailVC: UIViewController, UITextViewDelegate, ADBannerViewDelegate {
//Our label for displaying var "Items/cellName"
#IBOutlet var imageViewOutlet: UIImageView!
//connect in IB connection inspector with your ADBannerView
#IBOutlet var adBannerView: ADBannerView!
//Receiving variable assigned to our mainVC var "items"
var cellName: String = ""
var imageView: UIImageView = UIImageView()
var image = UIImage(named: "handcuffs.png")
var textViewText: String = ""
var textView: UITextView = UITextView(frame: CGRect(x: 5.0, y: 238.0, width: 315.00, height: 283.00))
//height = 332 for full screen 283 for small
override func viewDidLoad() {
super.viewDidLoad()
println("+--------------------+")
println("| Detail view loaded |")
println("+--------------------+")
// Iad stuff
self.adBannerView.delegate = self
self.canDisplayBannerAds = true
self.adBannerView.hidden = true //hide until ad loaded
//Setting up the textView
textView.text = textViewText
textView.editable = false
textView.backgroundColor = UIColor.clearColor()
textView.font = UIFont(name: "Helvetica", size: 15)
//adding textview as subview
self.view.addSubview(textView)
//ImageViewOutlets
imageViewOutlet.image = image
//Assign your string var to your navbar title
self.title = cellName
func bannerViewWillLoadAd(banner: ADBannerView!) {
NSLog("bannerViewWillLoadAd")
}
func bannerViewDidLoadAd(banner: ADBannerView!) {
NSLog("bannerViewDidLoadAd")
//self.textView.removeFromSuperview()
//textView = UITextView(frame: CGRect(x: 0.0, y: 238.0, width: 320.00, height: 283.00))
//self.view.addSubview(textView)
self.adBannerView.hidden = false //now show banner as ad is loaded
}
func bannerViewActionDidFinish(banner: ADBannerView!) {
NSLog("bannerViewActionDidFinish")
//optional resume paused app code
}
func bannerViewActionShouldBegin(banner: ADBannerView!, willLeaveApplication willLeave: Bool) -> Bool {
NSLog("bannerViewActionShouldBegin")
//optional pause app code
return true
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
NSLog("didFailToReceiveAdWithError")
}
//... your class implementation code
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
The commented out code in the function "bannerViewDidLoadAd" is what I thought would have fixed my issue. Sadly that function seems to never run? I'm not very familiar with Iads so hopefully someone out there can give me a hint as to how to change the height of a textView when an ad loads.
CanDisplayBannerAds :
Set this to enable automatic management of banner ad display with the view controller. It's important to note that this will modify the view hierarchy of the view controller by inserting a new container view above the view controller's view. The impact is that the view controller's view property will no longer return the originally provided view, it will return the new container. To access the original view, use the originalContentView property.
So, remove this line :
self.canDisplayBannerAds = true
Everything should work.
Related
I created a custom Numpad keyboard through xib and wanted to initialize it with a rounded corners.
Here is the code I use:
import UIKit
class NumpadView: UIView {
#IBOutlet weak var resetButton: NumpadButton!
#IBOutlet weak var decimalButton: NumpadButton!
var target: UITextInput?
var view: UIView?
init(target: UITextInput, view: UIView) {
super.init(frame: .zero)
self.target = target
self.view = view
initializeSubview()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
initializeSubview()
}
func initializeSubview() {
let xibFileName = "NumpadView"
let view = Bundle.main.loadNibNamed(xibFileName, owner: self, options: nil)![0] as! UIView
self.layer.cornerRadius = 30
self.layer.masksToBounds = true
self.addSubview(view)
view.frame = self.bounds
self.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}
}
But then I receive the strange view look in area where cornerRadius is implemented:
How to remove that grey background which is visible near the rounded corners?
UPDATE:
According to View Debugger it seems like this grey layer between yellow square and Visual Effect View is a UICompatibilityInputViewController:
How I presenting the Numpad:
1.I created a NumpadView as a UIView subclass in a xib:
2.In my VC I just change a standard textField.inputView property on my custom NumpadView:
import UIKit
class NumpadViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
setupKeyboardHide()
textField.delegate = self
textField.inputView = NumpadView(target: textField, view: view)
}
}
Test project on Github
Another option to get your "rounded corners"...
Get rid of the Visual Effect View in your Numpad class, and set a layer mask on the superview at run-time.
In class NumpadView: UIView, UIInputViewAudioFeedback:
override func layoutSubviews() {
super.layoutSubviews()
guard let sv = superview else { return }
let maskLayer = CAShapeLayer()
let bez = UIBezierPath(roundedRect: bounds, cornerRadius: 16)
maskLayer.path = bez.cgPath
sv.layer.mask = maskLayer
}
Looks like this:
Sure, the NumpadView object has rounded corner. However, you are using it like this:
textField.inputView = NumpadView(target: textField, view: view)
So, that part which is not rounded is the textField's inputView. I'm not quite sure if you can modify its layer to have corner radius. But, if you really want to get that rounded corner effect, an easier approach is just to add the NumpadView directly to the parent view and anchored to the bottom. Then show it via the begin editing delegate of the textfield (and hide via end editing).
I have a standard NSOutlineView. I would like it to have a background image, which tiles vertically, and which scrolls together with the outline view cells.
I've somewhat achieved this using the following in my ViewController:
class ViewController: NSViewController {
#IBOutlet weak var outlineView: NSOutlineView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
if let image = NSImage(named: "tile") {
let color = NSColor.init(patternImage: image)
outlineView.backgroundColor = color
}
}
}
That works, except when you scroll past the top or bottom of the view (with the stretch provided by the containing scroll view).
I've tried putting the background image on the scroll view, but then it is static and doesn't scroll with the outline view's content.
I've also tried subclassing various objects in the view hierarchy and overriding their draw(_ dirtyRect: NSRect) method and doing:
self.wantsLayer = true
self.layer?.backgroundColor = ...etc
but got no success from that either.
Can anyone provide any suggestions?
I ended up creating a new custom NSView:
class MyView: NSView {
override func draw(_ dirtyRect: NSRect) {
if let image = NSImage(named: "Tile") {
let color = NSColor.init(patternImage: image)
color.setFill()
dirtyRect.fill()
}
super.draw(dirtyRect)
}
}
Then in my ViewController class I added an instance of the custom view, and used autolayout constraints to pin the new view to my outlineView's clip view starting 2000points above it, and ending 2000 below. This means no matter how far you over-scroll into the stretch area, you still see the tiled background.
class MyViewController: NSViewController {
#IBOutlet weak var outlineView: NSOutlineView!
override func viewDidLoad() {
super.viewDidLoad()
guard let clipView = self.outlineView.superview else { return }
let newView = MyView(frame: .zero) // Frame is set by autolayout below.
newView.translatesAutoresizingMaskIntoConstraints = false
clipView.addSubview(newView, positioned: .below, relativeTo: self.outlineView)
// Add autolayout constraints to pin the new view to the clipView.
// See https://apple.co/3c6EMcH
newView.leadingAnchor.constraint(equalTo: clipView.leadingAnchor).isActive = true
newView.widthAnchor.constraint(equalTo: clipView.widthAnchor).isActive = true
newView.topAnchor.constraint(equalTo: clipView.topAnchor, constant: -2000).isActive = true
newView.bottomAnchor.constraint(equalTo: clipView.bottomAnchor, constant: 2000).isActive = true
}
}
I've removed other code from the above so hopefully I've left everything needed to illustrate the solution.
I'm trying to add a shadow to my (custom) nav bar when a user scrolls using scrollViewDidScroll but it doesn't do anything. I have the same exact code on another view controller but it has a tableView instead of a WKWebView and it works fine.
I tried adding webView.scrollView.delegate = self but I just get an error.
My code:
class ViewController: UIViewController {
#IBOutlet weak var webView: WKWebView!
#IBOutlet weak var navBar: UIView!
override func viewDidLoad() {
super.viewDidLoad()
addShadow()
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let navigationBar = navBar
let offset = scrollView.contentOffset.y / 10
if offset > 1.5 {
navigationBar?.layer.shadowOpacity = 0.15
} else {
navigationBar?.layer.shadowOpacity = Float(((3 * offset) / 20)/1.5)
}
}
func addShadow() {
navBar.layer.shadowColor = UIColor.black.cgColor
navBar.layer.shadowOffset = CGSize(width: 0, height: 2.0)
navBar.layer.shadowRadius = 6.0
navBar.layer.masksToBounds = false
}
}
I tried adding webView.scrollView.delegate = self but I just get an error.
You didn't share what the error was. I suspect though that you didn't declare your view controller as UIScrollViewDelegate conforming, which caused the compile time error when trying to set self as the scroll view delegate.
Change your view controller declaration to this:
class ViewController: UIViewController, UIScrollViewDelegate {
I am using a scrollview along with Nibs. The goal is to layout 3 nibs with image inside them and scroll through them. I am also using storyboards to layout the scrollview.
The issue is venting looks good besides on the iPhone Plus sizes. The nibs are not centered right and bleeds on the screen? how do I fix this? Please check my code below.
#IBOutlet private weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
imageArray = [imageOne, imageTwo, imageThree]
scrollView.contentSize = CGSize(width: self.view.bounds.width * CGFloat(imageArray.count), height: scrollView.frame.size.height)
loadOnboardingDescriptions()
}
// MARK: Load onboarding dscription features
func loadOnboardingDescriptions() {
for (index, image) in imageArray.enumerated() {
if let onboardingDescriptionView = Bundle.main.loadNibNamed(Constants.NibName.onboardingDescriptionView.rawValue, owner: self, options: nil)?.first as? OnboardingDescriptionView {
onboardingDescriptionView.onboardingImageView.image = UIImage(named: image["image"]!)
onboardingDescriptionView.frame.size.width = self.view.bounds.size.width
onboardingDescriptionView.frame.origin.x = CGFloat(index) * self.view.bounds.size.width
print(onboardingDescriptionView.frame.origin.x)
self.scrollView.addSubview(onboardingDescriptionView)
}
}
}
EDIT:
As suggested by Matt bellow, I should have called this function inside:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
loadOnboardingDescriptions()
}
I created a scroll view container that houses three view controllers. It's meant to mimic snapchat's swipe layout. however, I can't seem to get a code to manually switch to the next view controller without actually swiping (which I'm not interested in)
I tried calling the container class and setting it's scroll offset but it crashes... tried creating a delegate protocol, but delegate is returning nil... I'm stumped.
Here is my code:
class AViewController: UIViewController, ABViewControllerDelegate {
#IBOutlet var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
// 1) Create the three views used in the swipe container view
var ATVc : ATViewController = ATViewController(nibName: "ATViewController", bundle: nil);
var ACVc : ACViewController = ACViewController(nibName: "ACViewController", bundle: nil);
var ABVc : ABViewController = ABViewController(nibName: "ABViewController", bundle: nil);
// 2) Add in each view to the container view hierarchy
// Add them in opposite order since the view hieracrhy is a stack
self.addChildViewController(ABVc);
self.scrollView!.addSubview(ABVc.view);
ABVc.didMoveToParentViewController(self);
self.addChildViewController(ACVc);
self.scrollView!.addSubview(ACVc.view);
ACVc.didMoveToParentViewController(self);
self.addChildViewController(ATVc);
self.scrollView!.addSubview(ATVc.view);
ATVc.didMoveToParentViewController(self)
// 3) Set up the frames of the view controllers to align
// with eachother inside the container view
var adminFrame :CGRect = ATVc.view.frame;
adminFrame.origin.y = adminFrame.height;
ACVc.view.frame = adminFrame;
var BFrame :CGRect = ACVc.view.frame;
BFrame.origin.y = 2*BFrame.height;
ABVc.view.frame = BFrame;
// 4) Finally set the size of the scroll view that contains the frames
var scrollWidth: CGFloat = self.view.frame.width
var scrollHeight: CGFloat = 3 * self.view.frame.size.height
self.scrollView!.contentSize = CGSizeMake(scrollWidth, scrollHeight)
self.scrollView!.setContentOffset(CGPointMake(0, self.view.frame.height), animated: false)
var changeMe : String = "okay"
}
func scrollUp() {
println("clicked!")
self.scrollView.contentOffset.y - self.view.frame.height
}
}
and this is the view controller I'm trying to get out off by pressing a button..
protocol ABViewControllerDelegate {
func scrollUp()
}
class ABViewController: UIViewController {
let delegate = ABViewControllerDelegate?()
#IBAction func button(sender: AnyObject) {
println("button clicked!")
delegate!.scrollUp()
}
}
I feel like I'm leading myself on and that it can't be done!