I'm trying to add background image onto my screen and set some constraints, but unfortunately the image view doesn't appear and I don't know what the reason is. I've checked if the image file is in the project folder.
import UIKit
class ViewController: UIViewController {
let backgroundImageView = UIImageView()
override func viewDidLoad() {
super.viewDidLoad()
setBackground()
}
func setBackground() {
view.addSubview(backgroundImageView)
backgroundImageView.translatesAutoresizingMaskIntoConstraints = false
backgroundImageView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
backgroundImageView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
backgroundImageView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
backgroundImageView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
backgroundImageView.image = UIImage(named: "background-test-image")
}
}
Put your image in the Assets.xcassets folder
Related
I am building an application where I want to display a floor plan where the image is 1260x1000, larger than the size of my view controller. I want the user to be able to pan the image and zoom in and out, similar to how a map behaves in Mapview.
Below is the code in my view controller. When I run the simulator, the image is panning but the zooming in and out isn't working. Any suggestions on how to fix my code would be helpful.
class ViewController: UIViewController, UIScrollViewDelegate {
var scrollView: UIScrollView!
var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
imageView = UIImageView(image: UIImage(named: "myMap.pdf"))
scrollView = UIScrollView(frame: view.bounds)
scrollView.contentSize = imageView.bounds.size
scrollView.addSubview(imageView)
scrollView.delegate = self
scrollView.minimumZoomScale = 0.3
scrollView.maximumZoomScale = 5
view.addSubview(scrollView)
}
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return imageView
}
}
Your function signature is wrong:
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return imageView
}
Note: If you want to be able to scale your pdf image while keeping the vector-based rendering (so it doesn't get blurry when zoomed), you should probably use PDFKit and a PDFView.
Add your myMap.pdf file to your bundle... not to your Asset Catalog.
import UIKit
import PDFKit
class ZoomingPDFViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
guard let fileURL = Bundle.main.url(forResource: "myMap", withExtension: "pdf") else {
fatalError("Could not load myMap.pdf!")
}
// Add PDFView to view controller.
let pdfView = PDFView(frame: self.view.bounds)
pdfView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.view.addSubview(pdfView)
// Load myMap.pdf file from app bundle.
pdfView.document = PDFDocument(url: fileURL)
pdfView.autoScales = true
pdfView.maxScaleFactor = 5.0
pdfView.minScaleFactor = pdfView.scaleFactorForSizeToFit
}
}
I've got the following code:
[[UIApplication sharedApplication] sendAction:#selector(copy:) to:nil from:self forEvent:nil];
NSString *string = [UIPasteboard generalPasteboard].string;
The problem is that the pasteboard is returning what I've copied previously, not currently. Somehow it's hanging onto the previous item I've copied and returning that, and then next time around I get the item that I wanted and copied... strange behaviour.. any ideas?
Edit
I've got a solution using an observer, but not sure how elegant it is.. there seems to be some delay between copy and setting an item.. enough for it not to be set and for the previous one to be still on the UIPasteBoard.
I have composed a little sample to your code for copy/paste behavior and it works as expected: selected text is printed to console after tapping on the button.
class ViewController: UIViewController {
let textField = UITextField()
let copyButton = UIButton(type: .roundedRect)
#objc func copySelectedText() {
UIApplication.shared.sendAction(#selector(UIResponder.copy(_:)), to: nil, from: self, for: nil)
let copiedString = UIPasteboard.general.string
print(copiedString)
}
override func viewDidLoad() {
super.viewDidLoad()
textField.borderStyle = .roundedRect
view.backgroundColor = .darkGray
display(textField, copyButton)
copyButton.setTitle("tap to copy selected text", for: .normal)
copyButton.addTarget(self, action: #selector(copySelectedText), for: .touchUpInside)
}
private func display(_ textField: UITextField, _ copyButton: UIButton) {
copyButton.translatesAutoresizingMaskIntoConstraints = false
textField.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(copyButton)
view.addSubview(textField)
textField.backgroundColor = .white
textField.widthAnchor.constraint(greaterThanOrEqualToConstant: 200).isActive = true
textField.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
textField.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
copyButton.topAnchor.constraint(equalTo: textField.bottomAnchor, constant: 20).isActive = true
copyButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
}
}
I am learning to program views in Xcode instead of using the .storyboard.
I do not want the view to rotate whenever it is being rotated.
I have this so far.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.backgroundColor = .white
let imageView = UIImageView(image: #imageLiteral(resourceName: "facebook_logo.png"))
view.addSubview(imageView)
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
imageView.topAnchor.constraint(equalTo: view.topAnchor, constant: 300).isActive = true
imageView.widthAnchor.constraint(equalToConstant: 100).isActive = true
imageView.heightAnchor.constraint(equalToConstant: 100).isActive = true
}
I think the link provided by #oaccamsrazer above is the one you would need. To help out, I've implemented a small example project.
There are two view controllers, linked by a segue (and both wrapped in a UINavigationController).
In the AppDelegate you need the following:
var restrictRotation:UIInterfaceOrientationMask = .all
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask
{
return self.restrictRotation
}
And viewWillAppear (since it is called when we traverse through the stack, so is better than using viewDidLoad) we
override func viewWillAppear(_ animated: Bool) {
(UIApplication.shared.delegate as! AppDelegate).restrictRotation = .all
}
The second view will NOT rotate. It just features a label.
in viewDidLoad (you could also use viewWillAppear)
override func viewDidLoad() {
super.viewDidLoad()
(UIApplication.shared.delegate as! AppDelegate).restrictRotation = .portrait
}
Using the storyboard or code only makes no difference, the implementation will still be the same.
I want to display a gray UIViewIndicatorView in a view controller at the center of the view but this piece of code isn't showing anything:
class MyViewController: UIViewController {
var activityIndicatorView = UIActivityIndicatorView()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .black
displayActivityIndicator()
}
func displayActivityIndicator() {
view.addSubview(activityIndicatorView)
activityIndicatorView.style = .gray
activityIndicatorView.translatesAutoresizingMaskIntoConstraints = false
activityIndicatorView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
activityIndicatorView.widthAnchor.constraint(equalToConstant: 40).isActive = true
activityIndicatorView.heightAnchor.constraint(equalToConstant: 40).isActive = true
activityIndicatorView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
activityIndicatorView.startAnimating()
}
}
This only shows up the activity indicator view when I set the view controller's view to a color like white (excluding black).
How can I make it show up?
Change background to
view.backgroundColor = .green // for example
or
activityIndicatorView.style = .white
then you' ll see it , as it's nearly a color match between the indicator and the background view
My FSCalendar's content shrinks when I switch its scope from week to month if there is a view that's constrained to its bottom anchor.
Here is a quick gif to show what exactly is happening
I have tried everything at this point. Using calendar.setScope() instead of calendar.scope =, constraining attachedToCalendarView.topAnchor to calendar.bottomAnchor calendar.contentView.bottomAnchor, and calendar.daysContainer.bottomAnchor, even turning attachedToCalendarView 's constraints on and off depending on whether it's week scope or scope month.
Not sure what else to try. Here is the code:
import UIKit
import FSCalendar
class TestController : UIViewController, FSCalendarDataSource, FSCalendarDelegate, FSCalendarDelegateAppearance {
fileprivate weak var calendar: FSCalendar!
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
setUp()
}
#objc func switchCalendarScope(){
if self.calendar.scope == FSCalendarScope.month {
self.calendar.scope = FSCalendarScope.week
} else {
self.calendar.scope = FSCalendarScope.month
}
}
func setUp(){
let calendar = FSCalendar()
calendar.dataSource = self
calendar.delegate = self
self.calendar = calendar
self.calendar.scope = .week
self.calendar.locale = Locale(identifier: "en_EN")
self.calendar.calendarHeaderView.calendar.locale = Locale(identifier: "en_EN")
self.calendar.adjustsBoundingRectWhenChangingMonths = true
let testingView = UIView()
testingView.backgroundColor = .red
let attachedToCalendarView = UIView()
attachedToCalendarView.backgroundColor = .blue
view.addSubview(calendar)
view.addSubview(testingView)
view.addSubview(attachedToCalendarView)
self.calendar.translatesAutoresizingMaskIntoConstraints = false
self.calendar.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
self.calendar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
self.calendar.widthAnchor.constraint(equalToConstant: view.bounds.size.width).isActive = true
self.calendar.heightAnchor.constraint(equalToConstant: 300).isActive = true
testingView.translatesAutoresizingMaskIntoConstraints = false
testingView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
testingView.widthAnchor.constraint(equalToConstant: view.bounds.size.width).isActive = true
testingView.heightAnchor.constraint(equalToConstant: 20).isActive = true
attachedToCalendarView.translatesAutoresizingMaskIntoConstraints = false
attachedToCalendarView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
// Attaching this view's topAnchor to the calendar's bottom anchor
attachedToCalendarView.topAnchor.constraint(equalTo: self.calendar.contentView.bottomAnchor).isActive = true
attachedToCalendarView.widthAnchor.constraint(equalToConstant: view.bounds.size.width).isActive = true
attachedToCalendarView.heightAnchor.constraint(equalToConstant: 20).isActive = true
// Title and button to toggle the calendar scope
self.navigationItem.title = "Test"
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Toggle", style: .done, target: self, action: #selector(switchCalendarScope))
}
}
Well, I couldn't figure out how to fix the problem itself but I did find a workaround. I placed the calendar inside of an empty container view (just a simple UIView) and attached attachedToCalendarView to the container's bottomAnchor instead of the calendar's itself.
Do note however that using setScope, which animates the transition, still causes the same issue. For it to work you have to set it manually like calendar.scope = x
example:
#objc func switchCalendarScope(){
if self.calendar.scope == FSCalendarScope.month {
// self.calendar.setScope(FSCalendarScope.week, animated: true) // this will cause the calendar to be squished again
self.calendar.scope = .week
movingConstraint.constant = view.safeAreaLayoutGuide.layoutFrame.size.height * -0.20
} else {
// self.calendar.setScope(FSCalendarScope.month, animated: true)
self.calendar.scope = .month
movingConstraint.constant = 0
}
}