Search code examples
iosswiftuipickerview

Formatting alignment of uipickerview


I have searched and cannot find anything that can help me format the alignment of each row in my pickerview.

Currently it looks like this:

PoundsPence_PickerView

What I would like to do is right justify the left £ row and left justify the right pence row so that there is no gap and the current value would be £25.31 instead or the large gap that exists now.

I found some code that formats backgrounds and font size but not alignment.

Any help or links would be appreciated.

This is my full ViewController code...

import Foundation
import UIKit

class LocationViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {

    @IBOutlet weak var DisplayStartMileage: UITextField!
    @IBOutlet weak var labelFuelAmount: UILabel!
    @IBOutlet weak var spinFuelAmount: UIPickerView!

    var mileageToPass: String!

    var fuelAmount: Double = 0.00

    var pickerData = [[String]]()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        var poundValues = [String]()
        var penceValues = [String]()
        for var indexP:Int = 0; indexP < 100; indexP += 1 {
            poundValues.append("£ \(indexP)")
            penceValues.append(NSString(format: ".%02d", indexP) as String)
        }

        self.pickerData = [poundValues, penceValues]

        spinFuelAmount.delegate = self
        spinFuelAmount.dataSource = self

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func FuelSegmentChanged(sender: UISegmentedControl) {

        switch sender.selectedSegmentIndex
        {
        case 0:
            labelFuelAmount.hidden = false
            spinFuelAmount.hidden = false

        case 1:
            labelFuelAmount.hidden = true
            spinFuelAmount.hidden = true

        default:
            break; 
        }

    }

    func numberOfComponentsInPickerView(spinFuelAmount: UIPickerView) -> Int {
        return pickerData.count
    }

    func pickerView(spinFuelAmount: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return pickerData[component].count
    }

    func pickerView(spinFuelAmount: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
        return pickerData[component][row]
    }

    func pickerView(spinFuelAmount: UIPickerView, didSelectRow row: Int, inComponent component: Int) {

        var firstComponent = pickerData[0][spinFuelAmount.selectedRowInComponent(0)]
        firstComponent = firstComponent.stringByReplacingOccurrencesOfString( "£ ", withString: "" )

        var secondComponent = pickerData[1][spinFuelAmount.selectedRowInComponent(1)]
        secondComponent = secondComponent.stringByReplacingOccurrencesOfString( ".", withString: "" )

        if let firstValue = firstComponent.toInt(), let secondValue = secondComponent.toInt() {
            let fuelAmount = firstValue + secondValue / 100
        }

    }

    func pickerView(spinFuelAmount: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {

        let titleData = pickerData[row]
        var myString1 = NSMutableAttributedString(string:titleData)
        let myString1Font1 = UIFont(name:"AvenirNext-Regular", size:24.0)
        let myString1Color1 = UIColor(red: 0.292745, green: 0.461693, blue: 0.998524, alpha: 1.000000)
        let originalNSString = myString1.string as NSString
        let myString1Range1 = originalNSString.rangeOfString(titleData)
        var myString1ParaStyle1 = NSMutableParagraphStyle()
        myString1ParaStyle1.baseWritingDirection = NSWritingDirection.Natural
        myString1ParaStyle1.lineBreakMode = NSLineBreakMode.ByWordWrapping
        myString1.addAttribute(NSUnderlineColorAttributeName, value:myString1Color1, range:myString1Range1)
        myString1.addAttribute(NSParagraphStyleAttributeName, value:myString1ParaStyle1, range:myString1Range1)
        myString1.addAttribute(NSFontAttributeName, value:myString1Font1!, range:myString1Range1)

        if component == 0 {
            myString1ParaStyle1.alignment = NSTextAlignment.Left
        } else if component == 1 {
            myString1ParaStyle1.alignment = NSTextAlignment.Right
        }

        return myString1
    }

    func pickerView(spinFuelAmount: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView!) -> UIView {

        var pickerLabel = view as! UILabel!
        if view == nil {
            pickerLabel = UILabel()
            let hue = CGFloat(row)/CGFloat(pickerData.count)
            pickerLabel.backgroundColor = UIColor(hue: hue, saturation: 1.0, brightness:1.0, alpha: 1.0)
        }
        let titleData = pickerData[row]
        var myString1 = NSMutableAttributedString(string:titleData)
        let myString1Font1 = UIFont(name:"AvenirNext-Regular", size:24.0)
        let myString1Color1 = UIColor(red: 0.292745, green: 0.461693, blue: 0.998524, alpha: 1.000000)
        let originalNSString = myString1.string as NSString
        let myString1Range1 = originalNSString.rangeOfString(titleData)
        var myString1ParaStyle1 = NSMutableParagraphStyle()
        myString1ParaStyle1.baseWritingDirection = NSWritingDirection.Natural
        myString1ParaStyle1.lineBreakMode = NSLineBreakMode.ByWordWrapping
        myString1.addAttribute(NSUnderlineColorAttributeName, value:myString1Color1, range:myString1Range1)
        myString1.addAttribute(NSParagraphStyleAttributeName, value:myString1ParaStyle1, range:myString1Range1)
        myString1.addAttribute(NSFontAttributeName, value:myString1Font1!, range:myString1Range1)
        pickerLabel!.attributedText = myString1

        if component == 0 {
            myString1ParaStyle1.alignment = NSTextAlignment.Left
        } else if component == 1 {
            myString1ParaStyle1.alignment = NSTextAlignment.Right
        }


        return pickerLabel
    }
}

Solution

  • This should get you started:

    func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView!) -> UIView {
            let pickerLabel = UILabel()
            let titleData = pickerData[row]
            let myTitle = NSAttributedString(string: titleData, attributes: [NSFontAttributeName:UIFont(name: "Georgia", size: 26.0)!,NSForegroundColorAttributeName:UIColor.blackColor()])
            pickerLabel.attributedText = myTitle
           return pickerLabel
        }
    

    and this:

    func pickerView(pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {
        let titleData = pickerData[row]
        var myTitle = NSAttributedString(string: titleData, attributes: [NSFontAttributeName:UIFont(name: "Georgia", size: 15.0)!,NSForegroundColorAttributeName:UIColor.blueColor()])
        return myTitle
    }
    

    For the Attributed string, this is where you can modified the text attributes to fit what you want, you can set up something like this, you'll have to figure out how to place the Attributed string, but it's very simple using the second method above:

    var myString1 = NSMutableAttributedString(string:"$45.45")
    
    let myString1Font1 = UIFont(name:"AvenirNext-Regular", size:24.0)
    
    let myString1Color1 = UIColor(red: 0.292745, green: 0.461693, blue: 0.998524, alpha: 1.000000)
    
    let originalNSString = myString1.string as NSString
    let myString1Range1 = originalNSString.rangeOfString("$45.45")
    
    var myString1ParaStyle1 = NSMutableParagraphStyle()
    myString1ParaStyle1.alignment = NSTextAlignment.Right
    myString1ParaStyle1.baseWritingDirection = NSWritingDirection.Natural
    myString1ParaStyle1.defaultTabInterval = 0
    myString1ParaStyle1.firstLineHeadIndent = 0
    myString1ParaStyle1.headIndent = 0
    myString1ParaStyle1.hyphenationFactor = 0
    myString1ParaStyle1.lineBreakMode = NSLineBreakMode.ByWordWrapping
    myString1ParaStyle1.lineHeightMultiple = 0
    myString1ParaStyle1.lineSpacing = 0
    myString1ParaStyle1.maximumLineHeight = 0
    myString1ParaStyle1.minimumLineHeight = 0
    myString1ParaStyle1.paragraphSpacing = 0
    myString1ParaStyle1.paragraphSpacingBefore = 0
    myString1ParaStyle1.tailIndent = 0
    
    myString1.addAttribute(NSUnderlineColorAttributeName, value:myString1Color1, range:myString1Range1)
    myString1.addAttribute(NSParagraphStyleAttributeName, value:myString1ParaStyle1, range:myString1Range1)
    myString1.addAttribute(NSFontAttributeName, value:myString1Font1!, range:myString1Range1)
    

    This seems to work:

    func pickerView(pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {
        let titleData = pickerData[row]
    
        var myString1 = NSMutableAttributedString(string:titleData)
        let myString1Font1 = UIFont(name:"AvenirNext-Regular", size:24.0)
        let myString1Color1 = UIColor(red: 0.292745, green: 0.461693, blue: 0.998524, alpha: 1.000000)
        let originalNSString = myString1.string as NSString
        let myString1Range1 = originalNSString.rangeOfString(titleData)
        var myString1ParaStyle1 = NSMutableParagraphStyle()
        myString1ParaStyle1.baseWritingDirection = NSWritingDirection.Natural
        myString1ParaStyle1.lineBreakMode = NSLineBreakMode.ByWordWrapping
        myString1.addAttribute(NSUnderlineColorAttributeName, value:myString1Color1, range:myString1Range1)
        myString1.addAttribute(NSParagraphStyleAttributeName, value:myString1ParaStyle1, range:myString1Range1)
        myString1.addAttribute(NSFontAttributeName, value:myString1Font1!, range:myString1Range1)
    
        if pickerView == myPickerf {
            myString1ParaStyle1.alignment = NSTextAlignment.Left
        } else if pickerView == myPicker {
            myString1ParaStyle1.alignment = NSTextAlignment.Right
        }
    
        return myString1
    }
    
    func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView!) -> UIView {
        var pickerLabel = view as! UILabel!
        if view == nil {
            pickerLabel = UILabel()
            let hue = CGFloat(row)/CGFloat(pickerData.count)
            pickerLabel.backgroundColor = UIColor(hue: hue, saturation: 1.0, brightness:1.0, alpha: 1.0)
        }
        let titleData = pickerData[row]
        var myString1 = NSMutableAttributedString(string:titleData)
        let myString1Font1 = UIFont(name:"AvenirNext-Regular", size:24.0)
        let myString1Color1 = UIColor(red: 0.292745, green: 0.461693, blue: 0.998524, alpha: 1.000000)
        let originalNSString = myString1.string as NSString
        let myString1Range1 = originalNSString.rangeOfString(titleData)
        var myString1ParaStyle1 = NSMutableParagraphStyle()
        myString1ParaStyle1.baseWritingDirection = NSWritingDirection.Natural
        myString1ParaStyle1.lineBreakMode = NSLineBreakMode.ByWordWrapping
        myString1.addAttribute(NSUnderlineColorAttributeName, value:myString1Color1, range:myString1Range1)
        myString1.addAttribute(NSParagraphStyleAttributeName, value:myString1ParaStyle1, range:myString1Range1)
        myString1.addAttribute(NSFontAttributeName, value:myString1Font1!, range:myString1Range1)
        pickerLabel!.attributedText = myString1
    
        if pickerView == myPickerf {
            myString1ParaStyle1.alignment = NSTextAlignment.Left
        } else if pickerView == myPicker {
            myString1ParaStyle1.alignment = NSTextAlignment.Right
        }
    
    
        return pickerLabel
    }
    

    Here's your code reformatted, this should work:

    import Foundation
    import UIKit
    
    class LocationViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
    
        @IBOutlet weak var DisplayStartMileage: UITextField!
        @IBOutlet weak var labelFuelAmount: UILabel!
        @IBOutlet weak var spinFuelAmount: UIPickerView!
    
        var mileageToPass: String!
    
        var fuelAmount: Double = 0.00
    
        var pickerData = [[String]]()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
    
            var poundValues = [String]()
            var penceValues = [String]()
            for var indexP:Int = 0; indexP < 100; indexP += 1 {
                poundValues.append("£ \(indexP)")
                penceValues.append(NSString(format: ".%02d", indexP) as String)
            }
    
            self.pickerData = [poundValues, penceValues]
    
            spinFuelAmount.delegate = self
            spinFuelAmount.dataSource = self
    
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    
        @IBAction func FuelSegmentChanged(sender: UISegmentedControl) {
    
            switch sender.selectedSegmentIndex
            {
            case 0:
                labelFuelAmount.hidden = false
                spinFuelAmount.hidden = false
    
            case 1:
                labelFuelAmount.hidden = true
                spinFuelAmount.hidden = true
    
            default:
                break;
            }
    
        }
    
        func numberOfComponentsInPickerView(spinFuelAmount: UIPickerView) -> Int {
            return pickerData.count
        }
    
        func pickerView(spinFuelAmount: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
            return pickerData[component].count
        }
    
        func pickerView(spinFuelAmount: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
            return pickerData[component][row]
        }
    
        func pickerView(spinFuelAmount: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    
            var firstComponent = pickerData[0][spinFuelAmount.selectedRowInComponent(0)]
            firstComponent = firstComponent.stringByReplacingOccurrencesOfString( "£ ", withString: "" )
    
            var secondComponent = pickerData[1][spinFuelAmount.selectedRowInComponent(1)]
            secondComponent = secondComponent.stringByReplacingOccurrencesOfString( ".", withString: "" )
    
            if let firstValue = firstComponent.toInt(), let secondValue = secondComponent.toInt() {
                let fuelAmount = firstValue + secondValue / 100
            }
    
        }
    
        func pickerView(spinFuelAmount: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {
    
            let titleData = pickerData[component][row] //this is bad, you'll have to compute what to do about this, but you get the point
            var myString1 = NSMutableAttributedString(string:titleData)
            let myString1Font1 = UIFont(name:"AvenirNext-Regular", size:24.0)
            let myString1Color1 = UIColor(red: 0.292745, green: 0.461693, blue: 0.998524, alpha: 1.000000)
            let originalNSString = myString1.string as NSString
            let myString1Range1 = originalNSString.rangeOfString(titleData)
            var myString1ParaStyle1 = NSMutableParagraphStyle()
            myString1ParaStyle1.baseWritingDirection = NSWritingDirection.Natural
            myString1ParaStyle1.lineBreakMode = NSLineBreakMode.ByWordWrapping
            myString1.addAttribute(NSUnderlineColorAttributeName, value:myString1Color1, range:myString1Range1)
            myString1.addAttribute(NSParagraphStyleAttributeName, value:myString1ParaStyle1, range:myString1Range1)
            myString1.addAttribute(NSFontAttributeName, value:myString1Font1!, range:myString1Range1)
    
            if component == 0 {
                myString1ParaStyle1.alignment = NSTextAlignment.Left
            } else if component == 1 {
                myString1ParaStyle1.alignment = NSTextAlignment.Right
            }
    
            return myString1
        }
    
        func pickerView(spinFuelAmount: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView!) -> UIView {
    
            var pickerLabel = view as! UILabel!
            if view == nil {
                pickerLabel = UILabel()
                let hue = CGFloat(row)/CGFloat(pickerData.count)
                pickerLabel.backgroundColor = UIColor(hue: hue, saturation: 1.0, brightness:1.0, alpha: 1.0)
            }
            let titleData = pickerData[component][row]
            var myString1 = NSMutableAttributedString(string:titleData)
            let myString1Font1 = UIFont(name:"AvenirNext-Regular", size:24.0)
            let myString1Color1 = UIColor(red: 0.292745, green: 0.461693, blue: 0.998524, alpha: 1.000000)
            let originalNSString = myString1.string as NSString
            let myString1Range1 = originalNSString.rangeOfString(titleData)
            var myString1ParaStyle1 = NSMutableParagraphStyle()
            myString1ParaStyle1.baseWritingDirection = NSWritingDirection.Natural
            myString1ParaStyle1.lineBreakMode = NSLineBreakMode.ByWordWrapping
            myString1.addAttribute(NSUnderlineColorAttributeName, value:myString1Color1, range:myString1Range1)
            myString1.addAttribute(NSParagraphStyleAttributeName, value:myString1ParaStyle1, range:myString1Range1)
            myString1.addAttribute(NSFontAttributeName, value:myString1Font1!, range:myString1Range1)
            pickerLabel!.attributedText = myString1
    
            if component == 0 {
                myString1ParaStyle1.alignment = NSTextAlignment.Left
            } else if component == 1 {
                myString1ParaStyle1.alignment = NSTextAlignment.Right
            }
    
    
            return pickerLabel
        }
    }
    

    You will need to check my work and make sure that when THIS is called:

    let titleData = pickerData[component][row]
    

    that it's actually pointing to the correct dictionary item which is either Pounds or Pense. I actually looked at your code, more and I see that you had pickerData[component][row] already, so I reformated and then used these for the mutableatributed string callers. see the revised code which is really your code but with the correction