Swift, UitextField background with image on rightmost side - swift

I have one UItextField and I want to show the date image inside a textfield in the rightmost side.
Below is my code
txtEffectiveDate.rightView = UIImageView(image: UIImage(named:"sorting-selected-22pt" )) // named: "sorting-selected-22pt")
But somehow it is not displaying in the UI page.
Let me know what i am Doing wrong?

Related

Changing Label/Button Text colour dynamically based on the dynamically changing background

I know it may sound a little bit of a drag to ask this question but I am curious if anything like this is available.
I am building a app in which the background image (covers full view with a blur effect) of each view controller changes dynamically. This background image will be in all the view controllers, each one having a different set of UIControls (Labels, Buttons, Table Views, Collection Views, containers, tabs, etc).
Sometimes when the background image is very light, the foreground texts (labels, buttons) with white text colour are not visible at all. Also the vice versa is a problem too.
So I would like to know if there is any way to change the foreground text colour dynamically based on its background.
Recently I faced the same problem, And I think what you looking for is either image is bright or dark so that you can set property accordingly Hope this will help.
Create observer, everytime image change it will check if its a dark image or bright and based on that will call the function UIForDarkImage and UIForBrightImage
//ImageView observer to observe the image change and perform the UI action based on the image colour
//Your imageView you are using to set image
var imageView: UIImageView {
didSet {
if imageView.isDark(image.bounds) { //dont pass the full image bounds pass the rect where your buttons or label places it will save your hell lot of time
setUIForDarkImage() // here you set buttons and labels color to white or whatever changes you want to perform based dark image
}
else {
setUIForBrightImage() // here you set buttons and labels color to black or whatever changes you want to perform based bright image
}
}
}
UIImageViewExtension for checking if Image is a dark image or bright Image.
What happening is, It will go through image pixel-by-pixel and check if the pixel is bright or dark and if we get dark pixels more than the threshold we have set, we will assuming that its a dark image else it's a bright image.
PS: For better efficiency not checking the whole image (for a high-resolution image it will slow down if we will check all pixels) so only checking the part of the image in which we need our button or label, you can set rect based on your requirement. And also scaling by 0.45 to check few pixels in that rect(you can increase or decrease for more/less accuracy).
extension UIImageView {
func isDark(_ rect:CGRect)->Bool {
let s=image?.cgImage?.cropping(to: rect);
let data=s?.dataProvider?.data;
if data == nil {return false;}
guard let ptr = CFDataGetBytePtr(data) else {return false;}
let threshold = Int(Double(rect.width * rect.height) * 0.45);
var dark = 0,len=CFDataGetLength(data);
for i in stride(from: 0, to: len, by: 4) {
let r = ptr[i], g = ptr[i+1], b = ptr[i+2];
if (0.299 * Double(r) + 0.587 * Double(g) + 0.114 * Double(b)) < 100 {dark += 1;}
if dark > threshold {return true;}
}
return false;
}
}
PS: If you also like to know what I am doing in setUIForBrightImage() and setUIForDarkImage do let me know
Here's what I would do: Create a struct that contains the name of the image view and a tint color to use for your labels, buttons, etc.
Add a property to your view controllers using this new struct. Let's call it backgroundImageSettings.
Add a didSet method to the property that calls another method useBackgroundImageSettings() that installs the image into the background of the view controller's content view, sets the tint color for the view controller's content view, and calls setNeedsDisplay() on the content view.. Also call useBackgroundImageSettings() in your viewDidLoad so that setting your backgroundImageSettings still works even if you view controller's view hasn't been loaded yet.
I like Duncan's answer! An additional step you can take is to set a slight overlay onto your background image.
For example, if you have a background image with really dark colors and you can't see your black text very well, then you can add a layer with a background color of white and an opacity less than 1. That way there's a bit of white to make your text more readable, and you can still see the background image.
let overlay = UIView(frame: yourSuperView.bounds)
overlay.backgroundColor = UIColor.white
overlay.layer.opacity = 0.5
yourSuperView.addSubview(overlay)

Playground, unable to set same UIImageView to more than one UIView

I've got this code
override public func viewDidLoad() {
let imageBlankCard = UIImage(named: "BlankCard.png")
let imageViewBlankCard = UIImageView(image: imageBlankCard)
rockCard.addSubview(imageViewBlankCard)
scissorCard.addSubview(imageViewBlankCard)
paperCard.addSubview(imageViewBlankCard)
self.view.addSubview(rockCard)
self.view.addSubview(scissorCard)
self.view.addSubview(paperCard)
}
But when I run the playground, only the latest UIView (paperCard) is displayed properly, the other cards are not shown at all as you can see in the image here: there should be two cards like the last one, in place of the arrows.
Can someone help me? Thanks everybody!
According to the documentation,
Views can have only one superview. If view already has a superview and that view is not the receiver, this method removes the previous superview before making the receiver its new superview.
This explains the behaviour that you're getting.
One solution to this is to create three separate image views and add each of them as a subview.
Judging by the variable names, I think you are creating something similar to a rock paper scissors game. And you have three views that each holds an image view with the image of a blank card. And you want to add the image of a stone, paper and scissors as an overlay to the image view. If that's what you want to do, why not just make rockCard, paperCard and scissorsCard themselves UIImageViews and set the image to be BalnkCard.png?
let imageBlankCard = UIImage(named: "BlankCard.png")
rockCard.image = imageBlankCard
scissorsCard.image = imageBlankCard
paperCard.image = imageBlankCard

How to programmatically add textField to a scroll view

I have a button on my storyboard. This button is inside a view and that view is inside a scroll view.
What I am trying to do sounds relatively simple: When the button is pressed, the button moves down a little bit and a textField appears where the button had previously been.
However, what happens is the button animates, but then returns to its original position, instead of staying moved, and the textField appears as it should.
Because the position of the appearing textField is dependent on the position of the button, pressing the button multiple times simply places a bunch of textfields on top of each other.
Here is a picture of what happens:
my Screen:
Here is the code I am running when the button is pressed:
#IBAction func addIngredientButtonPressed(sender: UIButton) {
contentView.bounds.size.height += addIngredientLabel.bounds.height
scrollView.contentSize.height += addIngredientLabel.bounds.height
//Create Text Field and Set Initial Properties
let newIngredientTextField = UITextField(frame: CGRectMake(self.addIngredientLabel.frame.minX as CGFloat, self.addIngredientLabel.frame.midY as CGFloat, self.addIngredientLabel.bounds.width,self.addIngredientLabel.bounds.height * 0.60))
newIngredientTextField.font = UIFont.systemFontOfSize(15.0)
newIngredientTextField.placeholder = "ADD INGREDIENT HERE"
newIngredientTextField.contentHorizontalAlignment = UIControlContentHorizontalAlignment.Left
newIngredientTextField.alpha = 0.0
scrollView.addSubview(newIngredientTextField)
UIView.animateWithDuration(0.5) { () -> Void in
self.addIngredientLabel.center.y += self.addIngredientLabel.bounds.height
newIngredientTextField.alpha = 1.0
}
}
Note:** the length is also being added successfully to the screen, but the button is not staying moved. So in the screenshot above you can indeed scroll up and down **
I noticed that if you comment out the top 2 lines of code, the ones that add height to the contentView and the scrollView, you get almost the right behavior. The button moves and stays moved, the textField appears in the right spot, but if you keep pressing, it won't let you add more textFields than the screen size will hold.
Here is a picture of what happens if you comment out the top two lines. The button won't do anything more if you keep pressing it more:
screen filled:
I found lots of tutorials that tell you how to add more content than can fit into one screen using the storyboard and setting the inferred metrics to free form, but I have not found anyone trying to add elements dynamically like I am.
You appear to have a contentView -- presumably a direct subview of your scrollView, but you're adding the newIngredientTextField directly to your scrollView rather than to your contentView.
When you increase the bounds.size.height of the contentView, it decreases its frame.origin.y by half as much (to keep its center in the same place). As your original button is presumably a subview of this contentView, that will cause it to move independently of the newly-added text field.
In other words, write:
contentView.frame.size.height += addIngredientLabel.bounds.height
rather than
contentView.bounds.size.height += addIngredientLabel.bounds.height
and
contentView.addSubview(newIngredientTextField)
rather than
scrollView.addSubview(newIngredientTextField).

cocoa - what happen when close a window (by pressing the red X button)?

I'm writing an app for MacOS to display a string to a NSTextfield in a window when user click on the button in the status bar menu (application is an agent). The thing is I want to use the NSScrollView to embrace that NSTextview so that the NSTextview is scrollable. It sound simple but some thing happen:
(1) When I click the button on the menu, the window appear using the NSWindowController.showWindow(). But if the string is large (larger than the clipview), the NSScrollView isn't scrollable. If I select the text inside, then I can select the rest of the text that doesn't appear in the clipview
(2) If I leave the window there and click to the button again, then the the text is scrollable and the scrollbar appear!
(3) If I close the window by click on the red X button on top-left, then click to the button, then the window appear with the same situation at first (isn't scrollable). Notice that I don't recreate the new instance of NSWindowController of the window, at this time I just do the showWindow() with the old instance of the NSWindowController
This is the code:
if(newWC.window == nil){
let storyboard = NSStoryboard(name: "Main", bundle: nil)
newWC = storyboard?.instantiateControllerWithIdentifier("newWC") as! NewWindowController
newWC.window?.level = kCGStatusWindowLevelKey
println("new window")
}
newWC.showWindow(self)
//This is the ViewController contain the NSScrollView and the TextField
manualCopyView = newWC.window?.contentViewController as! ManualCopyViewController
var theScrollView = manualCopyView.theScrollView
var manualTextField = manualCopyView.manualEditTextField
//Calculate height of a block of string
manualTextField.stringValue = totalString.stringByAppendingString("")
var textFieldHeight = (manualTextField.cell() as! NSTextFieldCell).cellSizeForBounds(NSMakeRect(0, 0, 448, CGFloat(FLT_MAX))).height
if(textFieldHeight < 200){
textFieldHeight = 200
}
var frame = manualCopyView.manualEditTextField.frame
var clipViewFrame = theScrollView.contentView.frame
frame.size.height = textFieldHeight
//Change the frame of the textfield to fit the content string
manualTextField.frame = frame
//Gain focus to the new window
NSApp.activateIgnoringOtherApps(true)
It look like when the window first appear (or re-appear), the NSTextField is shrink even that I changed it's frame. But if I don't close it and show the window again, the frame expand as expected
I also used auto layout with constraints in the width and height of the scrollview and the width and minimum height (>= 200) of the textfield (because I think the height would be expanded)
Another question in this case: I have to set the scrollview Vertical Elasticity to No Elasticity or even the second case won't work. Is that normal?
Thank for any help.

Tab Bar - custom images without titles

I want to set my tab bar to have custom images but XCode insists in leaving the space for the tab bar item title text leaving my images positioned too high in the tab bar. I've tried the following code in my TabBarController.swift viewDidLoad function:
let tabItems = tabBar.items as [UITabBarItem]
tabItems[0].title = nil
tabItems[0].selectedImage = UIImage(named: "HomeWhiteIcon")
tabItems[1].title = "Database"
tabItems[1].selectedImage = UIImage(named: "Second")
tabItems[2].title = nil
tabItems[2].selectedImage = UIImage(named: "SettingsWhiteIcon")
tabItems[3].title = nil
tabItems[3].selectedImage = UIImage(named: "ReportsWhiteIcon")
However, although no title is displayed the images are positioned too high as pic below (please ignore database icon - I have not set this icon yet.
Here's a random stab as swift is not my strong suit, but perhaps the database icon having a title is causing the entire title row to not collapse. Try removing the title from the database icon.
Otherwise have you seen the setTitlePositionAdjustment method? Perhaps adjust the title's position up into the icon and the space below will go away.