evgenyneu / Cosmos

A star rating control for iOS/tvOS written in Swift
MIT License
2.19k stars 368 forks source link

Please help add view in code #18

Closed andreichirkunovgoon closed 8 years ago

andreichirkunovgoon commented 8 years ago

Could you please help me how to write the code to add Cosmos without storyboard? I need a row with a variable amount of cosmos UIViews depending on the size of an array.

I did not understand how you meant this: "Alternatively, one can instantiate CosmosView class and add it to the view manually without using Storyboard."

Thank you very much in advance!!

evgenyneu commented 8 years ago

Hi, one can use CosmosView like any other UIView from code. Here is an example that shows how to create a cosmos view and position it with auto layout constraints.

Here is a sample project: UsingCosmosWithoutStoryboard.zip.

func createCosmosView() {
  let cosmosView = CosmosView()
  view.addSubview(cosmosView)
  addLayoutConstrains(cosmosView)
}

func addLayoutConstrains(view: UIView) {
  guard let superview = view.superview else { return }
  view.translatesAutoresizingMaskIntoConstraints = false
  var constraints = [NSLayoutConstraint]()

  // Center view horizontally
  // --------------

  constraints.append(
    NSLayoutConstraint(item: view,
      attribute: .CenterX,
      relatedBy: .Equal,
      toItem: superview,
      attribute: .CenterX,
      multiplier: 1,
      constant: 0)
    )

  // Align the view's top with the top of its superview
  // --------------

  constraints.append(
    NSLayoutConstraint(item: view,
      attribute: .Top,
      relatedBy: .Equal,
      toItem: superview,
      attribute: .Top,
      multiplier: 1,
      constant: 100)
  )

  NSLayoutConstraint.activateConstraints(constraints)
}

Alternatively, if you need to have a collection of cosmos views you can use a table view and put CosmosView in a table view cell from the storyboard. There is another demo app in this Github repository that has a "Performance" button. The button shows a screen with a very long list of cosmos views in a table view.

a25804fc-d871-11e5-9169-fcace34f5388

Let me know how it goes.

andreichirkunovgoon commented 8 years ago

Dear Evgeny

Thank you very much for your reply. I found the reason why I couldn't make it work: If you load Cosmos using pods you cannot create a CosmosView(). If you import Cosmos it doesn't seem to work either.

I copied the CosmosDistrib.swift file from your sample project and now it works wonderfully. Thank you very much!

andreichirkunovgoon commented 8 years ago

Dear Evgeny

Thank you very much for your advice. I ended up doing a tableview. But how can I collect the information about the rating? I put a didFinishTouchingCosmos function inside of the TableViewCell, but it doesn't get called. What did I do wrong? Thank you very much in advance!

Best regards,

Andrei

andreichirkunovgoon commented 8 years ago

I saw that you wrote:

"To collect rating from the user and send it to your server you can use didFinishTouchingCosmos property of cosmos view, there is example in the readme. You can assign a function to it after getting your cell view with dequeueReusableCellWithIdentifier function." But I do not understand how to put this in code. Excuse me, I just started writing my app a few weeks ago and would be very glad if you could help me.

Best regards,

evgenyneu commented 8 years ago

@andreichirkunovgoon, if you are getting user's input from a cosmos view in a table view cell there may be weird touch problems because the table view itself is scrolled by touching. But if you are happy to try it anyway here is how to do it. In the demo app of this repository there is class called PerformanceTableViewCell. It has an update method that is called when the cell is dequeued in PerformanceTableViewController. In this update method you can assign a closure or a function. For example:

public class PerformanceTableViewCell: UITableViewCell {
  @IBOutlet var cosmosView: CosmosView!

  func update(rating: Double) {
    cosmosView.rating = rating

    cosmosView.didTouchCosmos = { rating in
      // Example of using a closure
    }

    cosmosView.didFinishTouchingCosmos = myFunction // Example of using a function
  }

  func myFunction(rating: Double) {
    cosmosView.backgroundColor = UIColor.redColor()
  }
}

Please beware that didFinishTouchingCosmos may not always trigger when the cosmos view is in the table view.

TCOA commented 7 years ago

A couple of things about this thread (which helped me get Cosmos running fast - thanks!)

  1. If you are having trouble with 'import Cosmos' not being recognized by xcode, do a 'Clean' (that seems to fix a world of woes!) - "Product => Clean"

  2. for Swift 3, the code is slightly different (so including it here - this works instantly to put the stars on the screen....

    
    import Cosmos

class RateARideViewController: UIViewController{ func createCosmosView() { let cosmosView = CosmosView() view.addSubview(cosmosView) addLayoutConstrains(view: cosmosView) } func addLayoutConstrains(view: UIView) { guard let superview = view.superview else { return } view.translatesAutoresizingMaskIntoConstraints = false var constraints = [NSLayoutConstraint]() // Center view horizontally // -------------- constraints.append( NSLayoutConstraint(item: view, attribute: .centerX, relatedBy: .equal, toItem: superview, attribute: .centerX, multiplier: 1, constant: 0) ) // Align the view's top with the top of its superview // -------------- constraints.append( NSLayoutConstraint(item: view, attribute: .top, relatedBy: .equal, toItem: superview, attribute: .top, multiplier: 1, constant: 100) ) NSLayoutConstraint.activate(constraints) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) createCosmosView() } override func viewDidLoad() { super.viewDidLoad() } }


(sorry, I can't seem to get this to format..... :( - but the code works, first time.... 👍 

3. I respectfully suggest that there should be a link perhaps only to this thread?) and/or more clear instructions on the main page of what "instantiate CosmosView class and add it to the view manually " means (for those of us moderately new to xcode....)
evgenyneu commented 7 years ago

Thanks for your tips, @TCOA. You are right, I should probably add a separate Wiki about this.

TCOA commented 7 years ago

@evgenyneu - could you please 'translate' the constraint code to help me get the stars where I want them on the screen? (super-newbie rating showing here! :)

When I use a separate view controller (as shown above), everything is great. But, now I have been asked to put the stars on top of another viewController and I can't figure out how to line them up.

What I am looking for is a way to place the frame where/as I need it programmatically, but then also have the CosmosView features - something like:

let cosmosView = CosmosView(frame: CGRect(origin: CGPoint(x: 0, y: 100), size: CGSize(width: self.view.frame.width, height: 50)))  
viewController.view.addSubview(cosmosView)
evgenyneu commented 7 years ago

@TCOA, your code where you create cosmos view with frame should work. Is there a problem?

TCOA commented 7 years ago

The problem was that I was mixing "self' and 'viewController' sizes and things weren't going where I wanted so I thought I was just doing it wrong.....

Here's the final I wound up with and it works great (makes this great library even more powerful! I will suggest when you update a Wiki that you include this sort of thing as well - for those of us that don't use the constraints method to include the subviews - this allows you to put the stars anywhere you want in a 'one liner')

let cosmosView = CosmosView(frame: CGRect(origin: CGPoint(x: viewController.view.frame.width / 4, y: 100), size: CGSize(width: viewController.view.frame.width / 2, height: 50)))

evgenyneu commented 7 years ago

I'm glad the problem is fixed. Thanks for your suggestion.