Skip to content
This repository has been archived by the owner on Feb 17, 2021. It is now read-only.

UIButton Layout #54

Closed
pgherveou opened this issue Oct 13, 2016 · 6 comments
Closed

UIButton Layout #54

pgherveou opened this issue Oct 13, 2016 · 6 comments
Assignees
Milestone

Comments

@pgherveou
Copy link
Contributor

Hey there
Is there something equivalent to LabelLayout for views such as UIButton (or any other view that define an intrinsicContentSize)?

Right now I am using a SizeLayout but I am forced to define the size of my button

SizeLayout<UIButton>(
  width: 100, height: 50,
  alignment: .centerTrailing,
  flexibility: .flexible,
  config: { button in
    button.backgroundColor = UIColor.blue
    button.setTitle("Button", for: .normal)
    button.setTitleColor(.black, for: .normal)
  }
)

screen shot 2016-10-13 at 3 19 47 pm

@nicksnyder
Copy link
Collaborator

There is currently no layout specialized for buttons.

Doesn't sound difficult to do, we would just need to figure out how button padding works. I imagine the implementation of ButonLayout could just reuse a InsetLayout and a LabelLayout.

@pgherveou
Copy link
Contributor Author

Quick question
I am not familiar enough with the codebase

But would it make sense to have a layout for self-sizing view such as label, button, switch
that reuse UIView.sizeThatFits(maxSize: CGSize)

something like this

import UIKit

/// measurement references
fileprivate var references = [String: UIView]()

/// create or get an existing reference of type V
func getReference<V: UIView>() -> V {
  let key = String(describing: V.self)
  if let reference = references[key] as? V { return reference }
  let reference = V.self()
  references[key] = reference
  return reference
}

class SelfSizingViewLayout<V: UIView>: Layout {

  /// block that configure View size
  let configureSize: (V) -> Void

  init(configureSize: @escaping (V) -> Void) {
    self.configureSize = configureSize
  }

  open func measurement(within maxSize: CGSize) -> LayoutMeasurement {
    let reference: V = getReference()
    configureSize(reference)
    let fittedSize = reference.sizeThatFits(maxSize)
    return LayoutMeasurement(layout: self, size: fittedSize.decreasedToSize(maxSize), maxSize: maxSize, sublayouts: [])
  }

  /// rest of protocol ...
}

let size1 = CGSize(width: 100, height: 100)

SelfSizingViewLayout<UIButton>(
  configureSize: { $0.setTitle("Bim Foo Bar", for: .normal) }
).measurement(within: size1) // {w 98 h 34}

SelfSizingViewLayout<UILabel>(
  configureSize: { $0.text = "Bim Foo Bar" }
  ).measurement(within: size1) // {w 92.5 h 20.5}

@esam091
Copy link

esam091 commented Oct 15, 2016

I think you can copy ComponentKit's button layout implementation here.

@pgherveou
Copy link
Contributor Author

Thks @esam091 for the link.
My Point is, why dont we reuse sizeThatFits rather than trying to reimplement it
What are the disadvantage of the method I described above?
cc @nicksnyder

@nicksnyder
Copy link
Collaborator

nicksnyder commented Oct 15, 2016

@pgherveou

The implementation of measurement(within:) must be safe to run on a background thread so we can't use any UIView methods in it.

From the UIView documentation

Threading Considerations
Manipulations to your application’s user interface must occur on the main thread. Thus, you should always call the methods of the UIView class from code running in the main thread of your application. The only time this may not be strictly necessary is when creating the view object itself but all other manipulations should occur on the main thread.

Instantiating a UIView on a background thread may be fine, but in order to get a proper measurement we would need to set data on the UIView (e.g. button title). Per the above documentation, this type of manipulation should not be done from a background thread (even if it does seem to work now because it may break in the future).

@pgherveou
Copy link
Contributor Author

Make sense to me now, thks for the explanations

nicksnyder added a commit that referenced this issue Oct 18, 2016
This is in preparation for ButtonLayout (#54) which will also want to
use this type.
nicksnyder added a commit that referenced this issue Oct 18, 2016
This is in preparation for ButtonLayout (#54) which will also want to
use this type.
nicksnyder added a commit that referenced this issue Oct 18, 2016
This is in preparation for ButtonLayout (#54) which will also want to
use this type.
@nicksnyder nicksnyder added this to the 4.0 milestone Oct 18, 2016
nicksnyder added a commit that referenced this issue Oct 19, 2016
This is in preparation for ButtonLayout (#54) which will also want to
use this type.
nicksnyder added a commit that referenced this issue Oct 21, 2016
nicksnyder added a commit that referenced this issue Oct 21, 2016
nicksnyder added a commit that referenced this issue Oct 26, 2016
This is in preparation for ButtonLayout (#54) which will also want to
use this type.
nicksnyder added a commit that referenced this issue Oct 26, 2016
nicksnyder added a commit that referenced this issue Oct 26, 2016
This is in preparation for ButtonLayout (#54) which will also want to
use this type.
nicksnyder added a commit that referenced this issue Oct 26, 2016
nicksnyder added a commit that referenced this issue Oct 26, 2016
nicksnyder added a commit that referenced this issue Oct 28, 2016
@nicksnyder nicksnyder self-assigned this Oct 31, 2016
nicksnyder added a commit that referenced this issue Nov 1, 2016
nicksnyder added a commit that referenced this issue Nov 1, 2016
This is in preparation for ButtonLayout (#54) which will also want to
use this type.
nicksnyder added a commit that referenced this issue Nov 1, 2016
nicksnyder added a commit that referenced this issue Nov 1, 2016
This is in preparation for ButtonLayout (#54) which will also want to
use this type.
nicksnyder added a commit that referenced this issue Nov 1, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants