0

I have SQLite database file and UILabel, and I set text for label from database on the number of characters after convert String to Characters, and I added extension its name (length), its job counts the number of characters.

enter image description here

My problem in this picture is : The UILabels are not organized in sizes and positions in per devices I want them to have their positions in the center of X-Axis

Questions:

1) How to set the label into center and set spaces right and left of screen for labels (per device) ??

2) How to set width for labels if device is iPhone 7/6S/6 plus width = 50, if device is iPhone 7/6S/6 width = 45 and if device is iPhone SE/5S/5C/5 width = 38 ??

3) Finally, how does the label become smaller by 10 if the number of characters is more than 8 ?

This my code :

func createTarget(id: Int) {

    listdata = dbHelpr.getDatabase(rowId: id)

    for data in listdata {

        let lengthOfChar : CGFloat = data.ans.length
        let yAxis : CGFloat = (self.view.frame.height) * 60%
        let width: CGFloat = view.frame.size.width - 40 // frame width
        var targetWidth: CGFloat = (width - (lengthOfChar - 1) * 5) / lengthOfChar
        let targetHeigt : CGFloat = 5

        if lengthOfChar >= 8 {
            targetWidth = 40
        } else {
            targetWidth = 50
        }

        let totalWidth: CGFloat = (targetWidth * lengthOfChar) + ((lengthOfChar - 5) * 5)

        for (indexTar, tar) in data.ans.characters.enumerated() {

            let x : CGFloat = (width / 2) - (totalWidth / 2)
            let xx : CGFloat = (CGFloat(indexTar) * targetWidth) + (CGFloat(indexTar) * 5) + 20
            var xAxis : CGFloat = (x + xx)
            xAxis = width - xAxis



            let targetLabel = UILabel(frame: CGRect(x: xAxis, y: yAxis, width: targetWidth, height: targetHeigt))
            targetLabel.backgroundColor = .white
            targetLabel.layer.masksToBounds = true
            targetLabel.layer.cornerRadius = 5
            targetLabel.text = String(describing: tar)
            targetLabel.textAlignment = .center
            targetLabel.textColor = .white
            self.view.addSubview(targetLabel)

        }

    }

}
Ameen MK
  • 121
  • 1
  • 14
  • Is anyone answer me please ?! – Ameen MK Aug 07 '17 at 13:09
  • You should be using auto layout for this. – dfd Aug 07 '17 at 14:16
  • I know using auto layout but I don't want to use auto layout, I need programmatically @dfd – Ameen MK Aug 07 '17 at 14:21
  • First off, you *can* programmatically create and change constraints in code. Second, with auto layout, you can create an array of labels and, either by setting them hidden or setting their width to 0 (in constraints), have a dynamic count of them appearing based on the size of the the DB return. Also, the size of *each* label width can be dynamic according to the device. This has actually been the "prescribed" way to do things in iOS since iOS 7. (What will you do when the iPhone Pro comes out next month with yet another new screen size?) – dfd Aug 07 '17 at 14:28
  • 1- I know but programmatically constraints is not accurate like initialize view.frame I'm tried that due for me many problems and errors. 2- See my code, in `yAxis` method I wrote (place the label in 60% of the total device volume) per device @dfd – Ameen MK Aug 07 '17 at 14:46
  • What's a solve ? Could you help me please ? @dfd – Ameen MK Aug 08 '17 at 11:22
  • I've given you my best solution - use auto layout. From what I see in your replies, you don't care for that. I'm not sure I can be of help to you. – dfd Aug 08 '17 at 11:40
  • OK how can I do it with constrains code ?? Could you write answer ?? @dfd – Ameen MK Aug 08 '17 at 14:13
  • But according to the conditions that you wrote in the post ! @dfd – Ameen MK Aug 08 '17 at 14:17
  • Please don't ask multiple questions all at once. It makes it difficult to answer . – Abizern Aug 11 '17 at 13:52
  • Is anyone answer me please ?! – Ameen MK Aug 14 '17 at 14:53
  • Is my question incomprehensible and has no solution at all ? – Ameen MK Aug 14 '17 at 14:56
  • Could you solve this question ?? @unkgd – Ameen MK Aug 14 '17 at 15:28

2 Answers2

0

In order to position your labels you need a few things things:

  1. Label container to keep everything centered and with margins from the screen sides
  2. Constraints between your labels depending on the device sizes etc..
  3. If you need to break lines - you need to handle it manually as well

To identify device kinds and have different logics, you can check this posts: iOS: How to determine the current iPhone/device model in Swift?

In order to fill your view with labels, here is a sample code to achieve this:

self.view.backgroundColor = UIColor.black

let labelContainerView : UIView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 10))
labelContainerView.translatesAutoresizingMaskIntoConstraints = false

let containerLeftConstraint : NSLayoutConstraint = NSLayoutConstraint(item: self.view, attribute: .left, relatedBy: .greaterThanOrEqual, toItem: labelContainerView, attribute: .left, multiplier: 1, constant: 8)
let containerRightConstraint : NSLayoutConstraint = NSLayoutConstraint(item: self.view, attribute: .right, relatedBy: .greaterThanOrEqual, toItem: labelContainerView, attribute: .right, multiplier: 1, constant: 8)
let containerCenterX : NSLayoutConstraint = NSLayoutConstraint(item: labelContainerView, attribute: .centerX, relatedBy: .equal, toItem: self.view, attribute: .centerX, multiplier: 1, constant: 0)
let containerCenterY : NSLayoutConstraint = NSLayoutConstraint(item: labelContainerView, attribute: .centerY, relatedBy: .equal, toItem: self.view, attribute: .centerY, multiplier: 1, constant: 0)

self.view.addSubview(labelContainerView)
self.view.addConstraints([ containerLeftConstraint, containerRightConstraint, containerCenterX, containerCenterY ])

// Add some labels
let totalLabels : Int = 10

var lastAddedLabel : UILabel? = nil

for labelAt : Int in 1 ... totalLabels
{
    var addedConstraint : [NSLayoutConstraint] = [NSLayoutConstraint]()

    let label : UILabel = UILabel(frame: CGRect.zero)
    label.translatesAutoresizingMaskIntoConstraints = false
    label.text = "_"
    label.textColor = UIColor.white
    label.textAlignment = .center
    label.adjustsFontSizeToFitWidth = true

    if (lastAddedLabel != nil)
    {
        // Add left constraint to previous label
        let leftConstraint : NSLayoutConstraint = NSLayoutConstraint(item: label, attribute: .left, relatedBy: .equal, toItem: lastAddedLabel!, attribute: .right, multiplier: 1, constant: 8)
        let equalWidth : NSLayoutConstraint = NSLayoutConstraint(item: label, attribute: .width, relatedBy: .equal, toItem: lastAddedLabel!, attribute: .width, multiplier: 1, constant: 0)

        addedConstraint.append(contentsOf: [ leftConstraint, equalWidth ])
    }
    else
    {
        // Add left constraint to super view
        let leftConstraint : NSLayoutConstraint = NSLayoutConstraint(item: labelContainerView, attribute: .left, relatedBy: .equal, toItem: label, attribute: .left, multiplier: 1, constant: 0)

        addedConstraint.append(leftConstraint)
    }

    // Add top bottom constraint
    let topConstraint : NSLayoutConstraint = NSLayoutConstraint(item: labelContainerView, attribute: .top, relatedBy: .equal, toItem: label, attribute: .top, multiplier: 1, constant: 0)
    let bottomConstraint : NSLayoutConstraint = NSLayoutConstraint(item: labelContainerView, attribute: .bottom, relatedBy: .equal, toItem: label, attribute: .bottom, multiplier: 1, constant: 0)

    addedConstraint.append(contentsOf: [ topConstraint, bottomConstraint ])

    // Add right constraint if this is the last label
    if (labelAt == totalLabels)
    {
        let rightConstraint : NSLayoutConstraint = NSLayoutConstraint(item: labelContainerView, attribute: .right, relatedBy: .equal, toItem: label, attribute: .right, multiplier: 1, constant: 0)

        addedConstraint.append(rightConstraint)
    }

    labelContainerView.addSubview(label)
    labelContainerView.addConstraints(addedConstraint)

    lastAddedLabel = label
}

self.view.layoutIfNeeded()

This gives out the output:

enter image description here

Changes you might need to make:

  1. Change the "totalLabels" number depending on your requirement
  2. Maybe adding another width constraint to the first generated label in order to define a specific with for all labels - the rest of the labels keep the same width as the first
  3. Adjust the containing view margins from both sides for different devices
  4. Handle new lines manually by pre-calculating the width the labels might use.

Good luck

unkgd
  • 661
  • 3
  • 12
  • This solution does not work with me because I am using a database and I want as in the picture that I have previously published but a Y-Axis is constant which is in my code I want to use it and also the spaces between UILabels and width is also constant but I want to be located in the Center of the X-Axis for only and grow up and smaller if the number The characters of the database, if the characters more than 8 the label should be smaller and if less than 8 should be 50, 45, 38 depending on the size of the device @unkgd – Ameen MK Aug 16 '17 at 09:21
  • I want from you just 2 things : 1- set X-Axis per devices 2- set width depending on the size of device @unkgd – Ameen MK Aug 16 '17 at 09:22
  • The example I provided should give you all the tools needed for you to solve your problem, use what it has and try implementing it as you need on your own. I also referenced you to a post which contains identifying various device types. – unkgd Aug 16 '17 at 09:39
  • Thanks for your suggested @unkgd – Ameen MK Aug 16 '17 at 13:05
0

I solved my problem and this answer :

func createTarget(id: Int) {

    listdata = dbHelpr.getDatabase(rowId: id)
    var targetHeigt = CGFloat()
    let viewWidth = self.view.frame.size.width
    if viewWidth == 320 {
        targetHeigt = 2.5
    } else {
        targetHeigt = 5
    }

    for data in listdata {
        let yAxis : CGFloat = (self.view.frame.height) * 60%
        let i = data.ans.length
        // char count
        let width: Int = Int(view.frame.size.width) - 40

        // frame width
        var targetWidth: Int = (width - (i - 1) * 5) / i

        if targetWidth > 50 {
            targetWidth = 50
        }
        let totalWidth: Int = (targetWidth * i) + ((i - 1) * 5)

        for x in 0..<i {
            let currentWidth: Int = (width / 2) - (totalWidth / 2) + (x * targetWidth) + (x * 5) + 20

            let targetLabel = UILabel(frame: CGRect(x: CGFloat(currentWidth), y: yAxis, width: CGFloat(targetWidth), height: targetHeigt))
            targetLabel.backgroundColor = .white
            targetLabel.layer.masksToBounds = true
            targetLabel.layer.cornerRadius = 5
            targetLabel.textAlignment = .center
            targetLabel.textColor = .white

            for i in listdata {
                let tar = data.ans.characters.map{String($0)}
                targetLabel.text = String(describing: tar)
            }
            self.view.addSubview(targetLabel)
        }
    }
}
Ameen MK
  • 121
  • 1
  • 14