I have an iOS Application. When the user clicks on a textview, the cursor is very small initially. This is what it looks like:
As soon as the user begins typing, the cursor changes size and becomes much bigger. This is what it looks like:
As you can see, the cursor in the second image is bigger than the cursor in the first image. How do I make the initial cursor bigger? I want it to have the same size as the cursor that appears when the user starts typing.
Here is my code:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UITextViewDelegate {
#IBOutlet weak var userMessageTextView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
self.userMessageTextView.delegate = self
//Used to make the border of the TextView look the same as the border of a TextField
userMessageTextView.layer.borderColor = UIColor(red: 0.9, green: 0.9, blue: 0.9, alpha: 1.0).cgColor
userMessageTextView.layer.borderWidth = 1.0
userMessageTextView.layer.cornerRadius = 5
}
func textViewDidBeginEditing(_ textView: UITextView) {
//Used to Make the Cursor appear somewhat centered in the TextView; Without this, the bottom of the cursor is lined up with the bottom edge of the TextView, so the cursor is not centered within the textView
userMessageTextView.contentOffset.y = 4.0
}
}
Related
I'm creating an application for OSX and the only thing I need is to delete the background color of my application's window.
If I run the app, it will appear a window that could be white or black (Aqua, Dark Aqua).
So, i tried to move into the 'ViewController.swift' file and I wrote this code
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
// tell the controller's view to use a CALayer as its backing store
view.wantsLayer = true
// change the background color of the layer
view.layer?.backgroundColor = NSColor.red.cgColor
}
}
For example, in this way I turn the background colour to red.
BUT, this is not what I want. So I tried another way (using RGBA colours)
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
// tell the controller's view to use a CALayer as its backing store
view.wantsLayer = true
// change the background color of the layer
view.layer?.backgroundColor = CGColor(red: 255/255, green: 0/255, blue: 0/255, alpha: 1)
}
}
And I saw that decreasing the 'alpha' value, the opacity decreases too.
So, I tried with
CGColor(red: 255/255, green: 0/255, blue: 0/255, alpha: 0)
The red colour disappears, but now you can see the white (or black) colour of the ViewController.
I understood that I just create another layer (like an ImageView) with a colour, but I haven't modified the ViewController background.
Is there a way I can do this? Or it is just impossible?
I've found out the solution.
Just go to the "ViewController.swift" file and than write this
class ViewController: NSViewController {
override func viewWillAppear() {
super.viewWillAppear()
view.window?.isOpaque = false
view.window?.backgroundColor = NSColor(red: 1, green: 0.5, blue: 0.5, alpha: 0.0)
}
}
If you wanna change the colour, just fix the red, green, blue values. The alpha value determinate the transparency.
Xcode swift 4
I have some views that are added dynamically in code one below another.
Each new view top anchor is connected to previous view bottom anchor.
And each view have a button that make view to expand/collapse with animation. Here is button code :
let fullHeight : CGFloat = 240
let smallHeight : CGFloat = 44
let currentHeigth = rootView.frame.size.height //I use this to get current height and understand expanded view or not
let heighCons = rootView.constraints.filter //I use this to deactivate current height Anchor constraint
{
$0.firstAttribute == NSLayoutAttribute.height
}
NSLayoutConstraint.deactivate(heighCons)
rootView.layoutIfNeeded()
if currentHeigth == smallHeight
{
rootView.heightAnchor.constraint(equalToConstant: fullHeight).isActive = true
rootView.setNeedsLayout()
UIView.animate(withDuration: 0.5)
{
rootView.layoutIfNeeded() //animation itself
}
}
else
{
rootView.heightAnchor.constraint(equalToConstant: smallHeight).isActive = true
rootView.setNeedsLayout()
UIView.animate(withDuration: 0.5)
{
rootView.layoutIfNeeded() //animation itself
}
}
This all works perfectly but i have a problem : view that below current expanding view changes it y position immediately with no animation. Its just jumping to previous view bottom anchor, that would be active after animation finish.
So my question is :
1) what is the right way to make height constraint animation, when views are connected to each other by bottom/top animation?
2) my goal is just to make a view that would expand/collapse on button click, maybe i should do it another way?
Here's an approach using Visiblity Gone Extension
extension UIView {
func visiblity(gone: Bool, dimension: CGFloat = 0.0, attribute: NSLayoutAttribute = .height) -> Void {
if let constraint = (self.constraints.filter{$0.firstAttribute == attribute}.first) {
constraint.constant = gone ? 0.0 : dimension
self.layoutIfNeeded()
self.isHidden = gone
}
}
}
Usage
expanview.visiblity(gone: true,dimension: 0)
Example
#IBOutlet weak var msgLabel: UILabel!
#IBOutlet weak var expanview: UIView!
#IBAction func toggleCollapisbleView(_ sender: UIButton) {
if sender.isSelected{
sender.isSelected = false
expanview.visiblity(gone: false,dimension: 128)
sender.setTitle("Collapse",for: .normal)
}
else{
sender.isSelected = true
expanview.visiblity(gone: true,dimension: 0)
sender.setTitle("Expand",for: .normal)
msgLabel.text = "Visiblity gone"
}
}
I'm trying to animate a constraint but it seems to be effecting the entire view. Here is the code that I am using to animate the constraint.
#IBOutlet weak var personHeight: NSLayoutConstraint!
func animateBackgroundHeight() {
print("animate")
UIView.animate(withDuration: 5.0, animations: {
self.personHeight.constant = 19 // personHeight is the IBOutlet to the constraint
self.view.layoutIfNeeded()
})
}
Everything in the view moves when the animation is going on but I'm not sure why. What I want to animate is the height of the view, but not effect the TextField or the button. Think of the GreyView as a background element of the TextField.
Here is a image to show you which constraint I am trying to animate (green one)
Pink box represents the parent view.
Grey Box is the view that I am trying to animate the height of.
The TextField and button are above the Grey Box object.
You may animate the wrong view after all
so to be clear about your question
if you have x view that nested in another view
and want to animate only x view
then you should
make
self.x.layoutIfNeeded()
instead of
self.view.layoutIfNeeded()
So I reverently updated to Xcode 7 Beta and I'm somewhat unsure as to whether that is pertinent information but I figured I'd mention it anyway. My issue is that when I use the convertPointToView() function, it calls for an argument of type SKScene whereas (obviously) I want to it to take a point. I have another class which doesn't inherit SKScene where I want to use this function and it errors with "use of unresolved identifier convertPointToView" (I am importing SKScene). I find this to be very strange since I've written other programs that use this function and work fine even with the Xcode 7 beta, however, it doesn't seem to be working here. If anyone knows why I am having all this trouble, I'd really appreciate some help.
import Foundation
import SpriteKit
import SceneKit
class StandardLabel: UILabel {
init(x: Double, y: Double, width: Double, height: Double, doCenter: Bool, text: String, textColor: UIColor, backgroundColor: UIColor, font: String, fontSize: CGFloat, border: Bool, sceneWidth: Int) {
var frame = CGRect()
if doCenter {
frame = CGRect(x: convertPointToView(CGPoint(x: sceneWidth / 2, y: 0)).x, y: height, width: width, height: height)
} else {
frame = CGRect(x: x, y: y, width: width, height: height)
}
super.init(frame: frame)
self.text = text
self.textColor = textColor
self.backgroundColor = backgroundColor
self.textAlignment = NSTextAlignment.Center
self.font = UIFont(name: font, size: fontSize)
if border {
super.layer.borderColor = UIColor.blackColor().CGColor
super.layer.borderWidth = 5
}
}
I'd suggest that if you want to add text within your scene, that you use SKLabelNode, because it uses the same coordinate system as the other items that you'll be aligning, and you won't have to worry about converting your coordinates between different systems.
Use a UILabel if you want to display text outside of your scene (although for a SpriteKit (2D) game this wouldn't make sense because they're full screen, and I think would make sense mostly if you're making a SceneKit (3D) game).
Also, you don't need to make a subclass just to set default color and text size, it probably makes more sense to have this as a private helper method on your scene.
SKLabelNode doesn't have any 'border' property (like UILabel.layer does) so instead you'll need to draw an outline using SKShapeNode. This example uses the exact frame of the label so the text and the border are touching. You probably want to add a gap so there's space between the text and border but I'll leave that to you.
Here's a commented code snippet that adds two labels to a scene: "Baore" at size 80 with red text and border, and the label "Hello" at size 30 with blue text and border. Both are centered horizontally, "Baore" is also centered vertically, "Hello" is offset from the center by 150.
You could have also moved the position logic into the helper function, but to me that just feels weird... but up to you to decide how you want to do that!
import SpriteKit
class GameScene: SKScene {
override func didMoveToView(view: SKView) {
// `makeLabelWithOutline` is a helper function that takes 3 parameters
// - labelText
// - textSize
// - tint color to use for text and outline
// because textSize and tint have default values, you can
// omit them, and the default values will be used instead
// so this will be a label with text "Baore" at size 80 and red text and outline
let baoreLabel = self.makeLabelWithOutline("Baore")
baoreLabel.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame))
self.addChild(baoreLabel)
// so this will be a label with text "Hello" at size 30 and blue text and outline
let helloLabel = self.makeLabelWithOutline("hello", textSize: 30, tint: UIColor.blueColor())
helloLabel.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame)+150)
self.addChild(helloLabel)
}
private func makeLabelWithOutline(labelText:String, textSize:CGFloat = 80, tint:UIColor = UIColor.redColor()) -> SKNode {
let myLabel = SKLabelNode(fontNamed:"Futura-CondensedExtraBold")
myLabel.text = labelText
myLabel.fontColor = tint
myLabel.fontSize = textSize
// create the outline for the label
let labelOutline = SKShapeNode(rect: myLabel.frame)
labelOutline.strokeColor = tint
labelOutline.lineWidth = 5
labelOutline.addChild(myLabel)
return labelOutline
// we're returning an SKNode with this hierachy:
// SKShapeNode (the outline)
// ↳ SKLabelNode (the "Baore" label)
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
convertPointToView is an instance method of an SKScene object so you'll need to call it on some instance of an SKScene (maybe pass in a reference to the entire scene instead of just the sceneWidth?)
I'm not sure if it helps, but there's also convertPoint:toView: which might make more sense if you're dealing with a UILabel (??)
I have looked everywhere and tested all the code snippets posted on Stack, but nothing works for me as I need it to work.
I simply want to set:
Nav bar height
Nav bar bg color in RGB
Nav bar centered logo
I'm working with iOS8, Xcode 6 and Swift.
Many thanks for a clear answer!
This is my code in ViewController.swift
// Set nav bar height
navigationController?.navigationBar.frame.origin.y = -10
// Set nav bar bg color
var navBarColor = UIColor(red: 4 / 255, green: 47 / 255, blue: 66 / 255, alpha: 1)
navigationController?.navigationBar.barTintColor = navBarColor
// Set nav bar logo
let navBarImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
navBarImageView.contentMode = .ScaleAspectFit
let navBarImage = UIImage(named: "navBarLogo.png")
navBarImageView.image = navBarImage
navigationItem.titleView = navBarImageView
After applying the code in the accepted answer, the height doesn't seem to change at all..
It's not an easy job...and I've surveyed several articles online (most of them in Objective-C).
The most useful one is this: http://www.emdentec.com/blog/2014/2/25/hacking-uinavigationbar
But its final solution does not put items in the middle, and it's not in Swift.
So I come up with a workable version in Swift. Hope it helps some people as I was saved so many precious time on SO.
Solution in Swift:
The following code will solve some issues you may have encountered:
The title & items are not placed in the middle of the navigation bar
The title & items would flick when the user navigates between view controllers
You need to subclass the UINavigationBar first, and in your storyboard, select the navigation bar element, and in the "Identity Inspector" tab, set the new class as the Custom Class
import UIKit
class UINavigationBarTaller: UINavigationBar {
///The height you want your navigation bar to be of
static let navigationBarHeight: CGFloat = 64
///The difference between new height and default height
static let heightIncrease:CGFloat = navigationBarHeight - 44
override init(frame: CGRect) {
super.init(frame: frame)
initialize()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initialize()
}
private func initialize() {
let shift = UINavigationBarTaller.heightIncrease/2
///Transform all view to shift upward for [shift] point
self.transform =
CGAffineTransformMakeTranslation(0, -shift)
}
override func layoutSubviews() {
super.layoutSubviews()
let shift = UINavigationBarTaller.heightIncrease/2
///Move the background down for [shift] point
let classNamesToReposition: [String] = ["_UINavigationBarBackground"]
for view: UIView in self.subviews {
if classNamesToReposition.contains(NSStringFromClass(view.dynamicType)) {
let bounds: CGRect = self.bounds
var frame: CGRect = view.frame
frame.origin.y = bounds.origin.y + shift - 20.0
frame.size.height = bounds.size.height + 20.0
view.frame = frame
}
}
}
override func sizeThatFits(size: CGSize) -> CGSize {
let amendedSize:CGSize = super.sizeThatFits(size)
let newSize:CGSize = CGSizeMake(amendedSize.width, UINavigationBarTaller.navigationBarHeight);
return newSize;
}
}
Also on my gist: https://gist.github.com/pai911/8fa123d4068b61ad0ff7
iOS 10 Update:
Unfortunately, this code breaks in iOS 10, there is someone who helps fix it, here you go:
iOS 10 custom navigation bar height
And to be clear, this code is kind of hacky since it depends on the navigation bar's internal structure...so if you decide to use it anyway, be prepared for any upcoming changes that may break this code...
Nav bar height:
In a custom navigation controller subclass...
The trick with this one is to NOT change the actual height of the navigation bar and instead adjust its origin.
func viewDidLoad() {
super.viewDidLoad()
navigationBar.frame.origin.y = -10
}
Nav bar bg color in RGB:
In a custom navigation controller subclass...
func viewDidLoad() {
super.viewDidLoad()
navigationBar.barTintColor = // YOUR COLOR
}
or use the appearance proxy
UINavigationBar.appearance().barTintColor = // YOUR COLOR
Nav bar centered logo
In a custom view controller...
func viewDidLoad() {
super.viewDidLoad()
navigationItem.titleView = UIImageView(image: // YOUR LOGO)
}
Great answer from Bon Bon!
In Swift 3 however make sure you replace
let classNamesToReposition: [String] = ["_UINavigationBarBackground"]
with
let classNamesToReposition: [ String ] = [ "_UIBarBackground" ]
Otherwise, it wont work.