Edit the background colour of the "Edit" view in moreNavigationController? - ios

class mainTabBarViewController: UITabBarController, UITabBarControllerDelegate {
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
tabBarController?.delegate = self
self.moreNavigationController.topViewController.view.backgroundColor = UIColor(red: 25.0/255.0, green: 25.0/255.0, blue: 25.0/255.0, alpha: 1.0)
let view = self.moreNavigationController.topViewController.view as UITableView
for cell in view.visibleCells(){
let tableCell = cell as UITableViewCell
tableCell.backgroundColor = UIColor(red: 25.0/255.0, green: 25.0/255.0, blue: 25.0/255.0, alpha: 1.0)
tableCell.textLabel?.textColor = UIColor.whiteColor()
}
}
func tabBarController(tabBarController: UITabBarController, willBeginCustomizingViewControllers viewControllers: [AnyObject]) {
let editView = tabBarController.view.subviews[1] as UIView
editView.backgroundColor = UIColor.redColor()
}
}
Here is my current code. I got the code that's in the 'willBeginCustomizingViewControllers' from an old website (around 4-5 years old) and it worked then apparently but it's not doing anything now. I want to change the background of the "Edit" modal view within the moreNavigationController to the same colour as i have set to the table cells in the viewWillAppear. I've put red for now just to test. Any ideas?

I've done some research, but i cant seem to find anything. I'm not sure its even possible.
There is one more option, but its not so easy. You can call your fifth tab 'more', and place a collection view inside it to access all of the other tabs (just copy apple's 'more' tab, but just start from scratch on a new view controller.).

Related

Dismiss previous ViewController upon selecting UITabBarItem for second time

I work on an iOS application that implements a UITabBarController with 5 icons connected. The whole project is made via Storyboard. As I want to give the option for 4 themes to the user, which thing I do in a static tableView, I came across an issue.
When the user changes theme, the previously instantiated via the tabBar view controllers do not update to the theme change because they exist before the theme update. Can I somehow dismiss them and create new instances of the same view controller classes upon the didSelect method of the UITabBar delegate?
Am I approaching the issue correctly? Any help would be much appreciated!
Thanks you in advance for your help.
class MainTabController: UITabBarController
{
override func viewDidLoad()
{
super.viewDidLoad()
}
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem)
{
let theme = UserDefaults.standard.string(forKey: "selectedColor")
print(theme!)
for vc in self.viewControllers!
{
if (theme == "default")
{
vc.view.backgroundColor = UIColor(red: 0xF9 , green: 0xF7 , blue: 0xF7)
}else if (theme == "theme1")
{
vc.view.backgroundColor = UIColor(red: 0x1F , green: 0xFF, blue: 0xFF)
}else if (theme == "theme2")
{
vc.view.backgroundColor = UIColor(red: 0xE3 , green: 0xFD, blue: 0xFD)
}else if (theme == "theme3")
{
vc.view.backgroundColor = UIColor(red: 0x3E, green: 0xC1, blue: 0xD3)
}
}
}
}
example of implementing in each view controller:
override func viewDidLoad()
{
let theme = UserDefaults.standard.string(forKey: "selectedColor")
print(theme!)
if (theme == "default")
{
outerView.backgroundColor = UIColor(red: 0xF9 , green: 0xF7 , blue: 0xF7)
}else if (theme == "theme1")
{
outerView.backgroundColor = UIColor(red: 0x1F , green: 0xFF, blue: 0xFF)
}else if (theme == "theme2")
{
outerView.backgroundColor = UIColor(red: 0xE3 , green: 0xFD, blue: 0xFD)
}else if (theme == "theme3")
{
outerView.backgroundColor = UIColor(red: 0x3E, green: 0xC1, blue: 0xD3)
}
}
Inside didSelect you can access the tab VCs and change them as you like ( inside any VC in the tab )
for vc in self.tabBarController!.viewControllers! {
vc.view.backgroundColor = UIColor.red
// if you want to set a property
if let other = vc as? OtherViewController {
// change here
}
}
//
if you want this code inside the tabBar custom class
for vc in self.viewControllers! {
vc.view.backgroundColor = UIColor.red
// if you want to set a property
if let other = vc as? OtherViewController {
// change here
}
}
//
after your edit , you need to either create a protocol containing the outerView and conform to this protocol in every VC or cast to the VC and change it's property
Create custom UITabBarController class and in it's viewDidLoad add :
for vc in self.viewControllers! {
vc.view.backgroundColor = .....
}
Now link this custom class to the Storyboard's UITabBarController.
Update :
You are getting the value from UserDefaults incorrectly.
UserDefaults.standard.string(forKey: "selectedColor")
It should be :
UserDefaults.standard.object(forKey: "selectedColor")
The solution to my problem was really simple but only after many hours of searching!
I had to put all my code that is editing the view in viewDidAppear instead of viewDidLoad because viewDidLoad is running only on the first time in contrast with
viewDidAppear which is called every time the user presses this particular tab.
Thank you all for your fast answers!

UISegmentedControl labels not fitting

When using a UISegmentedControl, I have a problem fitting all the labels, precisely in Japanese.
I did not notice the same issue with the other language I used at this point.
Here is my code:
interfaceChoice = UISegmentedControl(items: ["白黒モード", "緑赤青・モード"])
for i in 0..<interfaceChoice.subviews.count {
interfaceChoice.subviews[i].tintColor = localColor
for subSubView in interfaceChoice.subviews[i].subviews {
if subSubView is UILabel {
(subSubView as! UILabel).adjustsFontSizeToFitWidth = true
}
}
}
I would hope the line ..adjustsFontSizeToFitWidth.. would sort things out, but it does not work as one can see in the picture below.
Anyone has an idea as what I am doing wrong?
Storyboard example
This is how I did it.
In a story board, drag and drop a segmented control into the title area of the view controller.
Link the segmented control to an IBOutlet in the view controller.
This code
class ViewController: UIViewController {
#IBOutlet weak var interfaceChoice: UISegmentedControl!
override func viewDidLoad() {
super.viewDidLoad()
interfaceChoice.removeAllSegments()
interfaceChoice.insertSegment(withTitle: "白黒モード", at: 0, animated: false)
interfaceChoice.insertSegment(withTitle: "緑赤青・モード", at: 1, animated: false)
interfaceChoice.selectedSegmentIndex = 0
let font = UIFont.boldSystemFont(ofSize: 16)
interfaceChoice.setTitleTextAttributes([NSFontAttributeName: font], for: .normal)
interfaceChoice.tintColor = UIColor(red: 27/CGFloat(255), green: 77/CGFloat(255), blue: 102/CGFloat(255), alpha: 1.0)
}
}
Note: I won't pretend to know exactly why it's not behaving for you, but I hope this can help. If it is absolutely imperative to fix your exact situation, I think we might need more information.
Pure code example
This produces the same result as setting it up in the storyboard.
class ViewController: UIViewController {
var interfaceChoice: UISegmentedControl!
override func viewDidLoad() {
super.viewDidLoad()
interfaceChoice = UISegmentedControl(items: ["白黒モード", "緑赤青・モード"])
interfaceChoice.selectedSegmentIndex = 0
let font = UIFont.boldSystemFont(ofSize: 16)
interfaceChoice.setTitleTextAttributes([NSFontAttributeName: font], for: .normal)
interfaceChoice.tintColor = UIColor(red: 27/CGFloat(255), green: 77/CGFloat(255), blue: 102/CGFloat(255), alpha: 1.0)
self.navigationItem.titleView = interfaceChoice
}
}

loading custom appearance values

I would like to know in which function e.g viewDidLoad etc.. would be the best approach to load custom view properties like image border heights, color, all appearance.
For example I add custom values like these in cellForRowAtIndexPath which I think is not best way to do it:
// corner radius
cell.feedImageView.layer.cornerRadius = 10
// border
cell.feedImageView.layer.borderWidth = 2.0
cell.feedImageView.layer.borderColor = UIColor.black.cgColor
cell.feedImageView.layer.masksToBounds = true
And these navigationBar appearance I load in viewDidLoad and i use it in many views:
navigationController?.navigationBar.barTintColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.5)
self.navigationItem.leftBarButtonItem = nil
navigationController?.navigationBar.isTranslucent = true
let fontDictionary = [ NSForegroundColorAttributeName:UIColor.white ]
self.navigationController?.navigationBar.titleTextAttributes = fontDictionary
self.navigationController?.navigationBar.tintColor = UIColor(red: 0.184, green: 0.996, blue: 0.855, alpha: 1.00)
So the question again, where should I load appearance values? I ask it because right now I am in situation where my image border is loading before image etc..
There are so many functions like viewDidLoadAppearance(), ViewDidload(). I've read many questions where they ask what is difference between them but I still do not know where is best to load appearance.
You have basically 3 different options.
1) You could get or set those values in the viewDidAppear() func, after they have been completely instantiated.
2) You could get or set them in the vieDidLayoutSubviews() function and set a bool to check if your task has been called.
var didConfigureUI = false
func viewDidLayoutSubviews() {
if !didConfigureUI {
didConfigureUI = true
updateUI()
}
}
3) You could get or set them in the viewDidLoad using layoutIfNeeded():
override func viewDidLoad() {
super.viewDidLoad()
xy.view.layoutIfNeeded() // <- This will update your initial view frames
updateUI()
}
And your func to do whatever:
func updateUI() {
//f.e feedImageView.layer.masksToBounds = true
}
And to do it in your cellForRowAtIndexPath, you would do something like this, using the layoutIfNeeded() as well.
cellForRowAtIndexPath {
let cell = tableView.blahblahcell
updateUICell(cell.feedImageView)
}
func updateUICell(imageView: UIImageView) {
imageView.layoutIfNeeded()
imageView.layer.cornerRadius = 10
imageView.layer.borderWidth = 2.0
imageView.layer.borderColor = UIColor.black.cgColor
imageView.layer.masksToBounds = true
}
And to answer the last question about the lifecircle:
The circle is:
init
UIViewController awakeFromNib
loadView // your pictureImageView is loaded here
UIView awakeFromNib
UIViewController viewDidLoad
viewWillAppear
viewDidAppear // the properties of your pictureImageView are available here

Button that will generate a random background color - Xcode - Swift

I'm trying to make a button that will change the background color to a random color. So far I have:
func randomCGFloat() -> CGFloat {
return CGFloat(arc4random()) / CGFloat(UInt32.max)}
extension UIColor {
static func randomColor() -> UIColor {
let r = randomCGFloat()
let g = randomCGFloat()
let b = randomCGFloat()
// If you wanted a random alpha, just create another
// random number for that too.
return UIColor(red: r, green: g, blue: b, alpha: 1.0)
}
}
All of this goes outside the view controller because 'extension' is not allowed inside the view controller and must be at file scope.
Then I have this inside the view controller:
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.randomColor()
For my action button:
#IBAction func changeColor(sender: UIButton) {}
So far the app boots up with a random color. I don't know how to make the action button change the background color to a new random color because background color is outside the scope of my action. I can't put the action outside of the view controller class. The button has to generate a new random color and update the background color.
As long as changeColor is in your view controller, you can just do
#IBAction func changeColor(sender: UIButton) {
self.view.backgroundColor = UIColor.randomColor()
}
and then you have to connect a touch event of your button (say, touchUpInside) to the action. You can do that in Interface Builder (easy) or in code (trickier, but equally easy when you get the hang of it).

Strange Custom Background Color on UIPickerView Swift

I'm getting strange colors when assigning a custom UIColor to the background of UIPickerViews. I have created a color for textViews and pickerViews as follows:
let myTextViewBackgroundColor = UIColor(red: 192.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 0.35)
And I assign it as:
myTextView.backgroundColor = myTextViewBackgroundColor
keywordPicker.backgroundColor = myTextViewBackgroundColor
Here's what it looks like:
As you can see, the color of the textViews and the color of the picker are different. The difference seems more pronounced on a device than in this snapshot, but the custom color looks muddy, almost like it is mixed with a default gray background.
If I comment out the pickerView color item above, I get a gray color background:
If I choose a standard UIColor, it appears to work correctly. UIColor.yellowColor in this instance. If I choose white, that looks good, too.
I create the pickerView in code and assign it to a textField which has no background color assigned.
var keywordPicker : UIPickerView?
keywordPicker = UIPickerView()
keywordPicker?.delegate = self
keywordPicker?.dataSource = self
keywordsForItemTextField.inputView = keywordPicker
keywordPicker.backgroundColor = myTextViewBackgroundColor
And for what it's worth, I have a date picker that I created as a modal screen with it's own view controller. In that case, the picker is created on the storyboard. I still assign my background color with code and that picker shows the correct color.
tkanzakic's answer finally allowed me to change the background color of UIDatePicker.
Here's the Swift 4 version:
class CustomDatePicker: UIDatePicker {
var customBackgroundColor = UIColor.black
override func willMove(toWindow newWindow: UIWindow?) {
super.willMove(toWindow: newWindow)
if newWindow != nil {
inputView?.backgroundColor = customBackgroundColor
}
}
}
Change the customBackgroundColor property to your liking.
I'm pretty sure this is a result of the UIPickerView having that silvery-grey filter over it always (notice how it's grey when you have it set to white?)
This response does not expose the cause of the issue, but I've included my resolution in case it will help others. I created a label for the selected row display and set the background color of the label. This label color is true to the custom settings.
I give a nod to Making App Pie and article https://makeapppie.com/2014/10/21/swift-swift-formatting-a-uipickerview/
which was the inspiration. Set the background to white:
keywordPicker?.backgroundColor = UIColor.whiteColor()
Also I added a border so the picker looks like the textViews I created:
keywordPicker?.layer.borderColor = UIColor(colorLiteralRed: 212.0/255.0, green: 212.0/255.0, blue: 212.0/255.0, alpha: 1.0).CGColor
keywordPicker?.layer.borderWidth = 1.0
keywordPicker?.layer.cornerRadius = 7.0
keywordPicker?.layer.masksToBounds = true
Setup the label:
func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView?) -> UIView {
let pickerLabel = UILabel()
var titleData : String = String()
if pickerView == keywordPicker {
titleData = crsuKeywordPickerList![row]
}
pickerLabel.text = titleData
pickerLabel.backgroundColor = myPickerBackgroundColor
pickerLabel.textAlignment = .Center
return pickerLabel
}//pickerView:viewForRow:...
The result:
As a second option as discussed above, if you instantiate the picker on the storyboard this problem does not appear.
In our case we have a wrapper around the UIPickerView to build a custom date picker. After setting the appearance proxy of the UITextField class to use dark mode for the inputView we have the same glitch if the first textField that becomes active is one with the custom picker as inputView, but if the user interact before with a textField with the normal keyboard as inputView the glitch do not appear.
In our particular case adding this hack to the wrapper view fix the issue:
- (void)willMoveToWindow:(UIWindow *)newWindow
{
[super willMoveToWindow:newWindow];
if (newWindow) {
self.pickerView.backgroundColor = self.colorPalette.inputViewBackgroundColor;
}
}
We also tried setting the color in the willMoveToSuperview: method but that does not work.
write your background color change code inside:-
func textFieldDidBeginEditing(_ textField: UITextField) {
if textField == self.tourtextfieldtextField {
//for background color of picker
datePickerView.backgroundColor = .red
//text color of picker
datePickerView.setValue( colorLiteral(red: 0, green: 0.5529411765, blue: 0.537254902, alpha: 1), forKeyPath: "textColor")
datePickerView.setValue(0.8, forKeyPath: "alpha")
}
}
swift 4.2 / xcode 10:
The background color need to be set in the main thread:
DispatchQueue.main.async {
keywordPicker.backgroundColor = myTextViewBackgroundColor
}
To remove the silvery-grey overlay on the UIPickerView you can add the following.
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
for subview in pickerView.subviews {
subview.backgroundColor = .clear
}
}

Resources