infinitered / redpotion

We believe iPhone development should be clean, scalable, and fast with a language that developers not only enjoy, but actively choose. With the advent of Ruby for iPhone development the RubyMotion community has combined and tested the most active and powerful gems into a single package called RedPotion
MIT License
233 stars 40 forks source link

UITableViewCell centre #101

Closed andersennl closed 9 years ago

andersennl commented 9 years ago

Hi, I have this code:

# app/views/my_cell.rb
class MyCell < PM::TableViewCell
  def on_load
    apply_style :my_cell

    content = find(self.contentView)
    @title = content.append! UILabel, :my_cell_title
    @segmented = content.append! UISegmentedControl, :segmented_control

    @segmented.segmentedControlStyle = UISegmentedControlStyleBar
    @segmented.insertSegmentWithTitle('One', atIndex: 0, animated: false)
    @segmented.insertSegmentWithTitle('Two', atIndex: 1, animated: false)
  end

  def title=(value)
    @title.text = value
  end
  def title
    @title
  end
end
# app/stylesheets/my_cell_stylesheet.rb
module MyCellStylesheet
  def my_cell_height
    40
  end

  def my_cell(st)
    st.frame = {l: 5, t: 100, w: 80, h: my_cell_height}
    # Style overall view here
  end

  def my_cell_title(st)
    st.frame = { l: 10, fr: 10, centered: :vertical, h: 20 }
    st.font = font.medium
    st.color = color.black
  end

  def segmented_control(st)
    st.frame = { left: 20, fr: 20, centered: :both, h: 30 }
  end
end

Which results in this: picture

I have two questions, first: shouldn't the segmented_control be horizontally centered?

And second question: if I use this code instead (in the stylesheet):

def segmented_control(st)
    st.frame = { left: 20, fr: 20, centered: :vertically, h: 30 }
end

How is this vertically centered? vertically cented

What am I doing wrong? If I had to guess, I would say that the view of the cell itself is not filling the whole available space and therefore the segmented_control is misplaced whilst despite centered. Thanks a lot!

markrickert commented 9 years ago

So I've run across this as well. Try throwing this into your cell (and make sure you're on the most recent version of redpotion)

def will_appear
  mp "just to make sure this is being called...
  find(@segmented).reapply_styles
end

The issue here is that cell's contentView isn't sized properly in on_load. It's only when the cell is about to appear that your segmented control's superview is of proper size.

Also note that we have stylers for segmented controls - https://github.com/infinitered/rmq/blob/master/motion/ruby_motion_query/stylers/ui_segmented_control_styler.rb

Perhaps you could send a pull request to RMQ that adds segmentedControlStyle? :grin:

squidpunch commented 9 years ago

@andersennl As @markrickert said the contentView (and cell) seem to default to 320 on all devices (at least phone devices)

you can see this by simply doing this in the REPL

UITableViewCell.alloc.init.frame
=> #<CGRect origin=#<CGPoint x=0.0 y=0.0> size=#<CGSize width=320.0 height=44.0>>

I think another way that should work, (but I haven`t been able to try it lately) is this:

  def on_load
    apply_style :my_cell
    content = find(self.contentView).apply_style(:content_view)
    ...

and in your styles...

def content_view(st)
  st.frame = { w: screen_width }
end

If that works, then we remove the reapply styles requirement on every display so I'd be interested in knowing if that solves it or not.

andersennl commented 9 years ago

I'm sorry that it took me so long to try this out. @markrickert I'm afraid I couldn't solve the problem with your hint using will_appear, but thanks anyway! And thanks for the hint with the prepend_segments. I didn't get it at first when I read the docs but it makes totally sense now. I'd love to send a pull request for segmentedControlStyle (even if I have great respect for committing to these gems).

@squidpunch your solution worked perfectly, thanks a lot!

squidpunch commented 9 years ago

Awesome. Good to hear! And yeah it's pretty much the same, I didn't want to make assumptions on the cell styles etc! I think marks suggestions should have been good too. I'm kicking some ideas around that may great a PR to make this just work by default. It's still just a thought but we will see if something comes of it. Thanks @andersennl !

twerth commented 9 years ago

Yeah, you always want to set the width of the ContentView. We need to add that to all of our templates.

If your superview changes sizes, the appropriate place to update the child views is in layoutSubviews, which is what it's designed for, and it gets called anytime subviews should be updated.

You can also setup your styles to only apply a frame when the style is reapplyed. Using:

unless st.view_has_been_styled?
  # do styles that should only be called once here
end