uipickerview的格式化对齐方式

Posted

技术标签:

【中文标题】uipickerview的格式化对齐方式【英文标题】:Formatting alignment of uipickerview 【发布时间】:2015-08-15 15:12:48 【问题描述】:

我已经搜索并找不到任何可以帮助我格式化我的pickerview 中每一行的对齐方式的东西。

目前看起来是这样的:

我想要做的是右对齐左£行和左对齐右便士行,这样就没有差距,当前值将是 25.31 英镑,或者现在存在的大差距。

我发现了一些格式化背景和字体大小但不对齐的代码。

任何帮助或链接将不胜感激。

这是我完整的 ViewController 代码...

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
    

【问题讨论】:

【参考方案1】:

也许是更好的方法....以下方法可能会有所帮助:

// Swift
//   UIPickerView Delegate method

func pickerView(pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat 
    return CGFloat(50.0)

使用它,可以消除代码的“膨胀”,并通过 2 个组件实现以下目标:

默认情况下,组件将居中对齐,并且看起来整个选择器也将居中对齐。

【讨论】:

【参考方案2】:

我用它来右对齐选择器视图中的文本:

func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView 
  var pickerLabel: UILabel? = (view as? UILabel)
  if pickerLabel == nil 
    pickerLabel = UILabel()
    pickerLabel?.font = UIFont.systemFont(ofSize: 20.0)
    pickerLabel?.textAlignment = .right
  

  pickerLabel?.text = data[row]
  pickerLabel?.textColor = UIColor.red

  return pickerLabel!

【讨论】:

这应该是选择的答案,比当前选择的要干净。只应注意 data[row] 应更改为您的数据变量。【参考方案3】:

这应该让你开始:

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
    

还有这个:

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

对于 Attributed 字符串,您可以在此处修改文本属性以适合您的需要,您可以设置类似这样的内容,您必须弄清楚如何放置 Attributed 字符串,但使用起来非常简单上面第二种方法:

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)

这似乎有效:

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

这是您重新格式化的代码,这应该可以工作:

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
    

您需要检查我的工作,并确保在调用 THIS 时:

let titleData = pickerData[component][row]

它实际上指向正确的字典项目,即英镑或便士。我实际上查看了您的代码,更多,我发现您已经有了 pickerData[component][row],所以我重新格式化,然后将它们用于可变属性的字符串调用者。查看修改后的代码,这确实是您的代码,但进行了更正

【讨论】:

谢谢...。不幸的是,当我使用前两位代码时,这类似于我在@makeapple.com 找到的代码...我得到一个 Swift 编译器错误...找不到'NSAttributedString' 类型的初始化程序,它在 let myTitle 行中都接受类型为 '(string: ([(String)]), attributes: [String : NSObject])' 的参数列表 是的,在 MakeApple.com 上也是一样,让我为你检查错误部分,一秒钟 谢谢...... 顺便说一句...我可能在我的问题中引入了混淆。我的选择器视图有两个微调器(列),而不是我所说的行。用户可以将 £ 列 (£0 - £99) 独立旋转到便士列 (.00 - .99),以便他们可以选择从 £0.00 到 (£99.99) 的任何金额。我需要的是这些列的对齐方式。 当然,np,我刚刚发布的解决方案将允许您独立调整两个选择器,您只需将 POUNDS 整数的 NSTextAlignment 调整为 RIGHT,然后将 PENCE 调整为 LEFT你应该拥有它【参考方案4】:

对于任何尝试对齐多个组件(例如在 UIDatePicker 中)的人,我正在为仅月和年的选择器视图执行此操作:

我有一个字符串扩展来计算宽度:

extension String 
func width(withConstraintedHeight height: CGFloat, font: UIFont) -> CGFloat 
    let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
    let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)

    return ceil(boundingBox.width)


然后我用它来计算每个组件中最大值的宽度,并在pickerview委托中设置它的宽度

func pickerView(_ pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat 
    let componentValues = self.pickerViewDataSource[component]
    var maxWidth = CGFloat(0)

    for value in componentValues 
        let valueWidth = value.width(withConstraintedHeight: 20, font: self.pickerLabelFont)
        if valueWidth > maxWidth 
            maxWidth = valueWidth
        
    

    return maxWidth + 5

现在我使用用于计算宽度的相同字体创建标签

func pickerView(_ pickerView: UIPickerView,
                viewForRow row: Int,
                forComponent component: Int,
                reusing view: UIView?) -> UIView


    var pickerLabel = view as? UILabel;

    if (pickerLabel == nil)
    
        pickerLabel = UILabel()

        pickerLabel?.font = self.pickerLabelFont
        pickerLabel?.textAlignment = NSTextAlignment.center
    

    if component < self.pickerViewDataSource.count && row < self.pickerViewDataSource[component].count 
        pickerLabel?.text = self.pickerViewDataSource[component][row]
    

    pickerLabel!.adjustsFontSizeToFitWidth = true
    return pickerLabel!;

这使得 UIPickerView 中的每个组件只使用显示最大值所需的宽度。默认情况下,UIPickerView 会将组件居中对齐,因此它们会彼此靠近,这就是为什么我将 +5 作为边距。请看下面我的选择器现在的示例:

【讨论】:

【参考方案5】:

您应该通过实现该方法来实现这一点:

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


【讨论】:

以上是关于uipickerview的格式化对齐方式的主要内容,如果未能解决你的问题,请参考以下文章

iOS Swift:UIPickerView 文本对齐

如何在 Android Studio 中对齐/格式化代码?

python中格式化输出和字母大小写转换,对齐填充方式

word2010插入公式以后无法调整公式左对齐、居中、右对齐等等,如何解决?

利用zipalign对齐so库回顾

在 Swift 中以编程方式将 UIImageView 左右对齐