Date
1 - 6 of 6
What is the best strategy for this?
Problem: I am designing a collection view with overlapping cells. Each cell has an active area inside it (and the active areas of adjacent cells do not overlap). (More information about what I'm doing at the bottom of this post.) I want a tap in the active area of a cell to select that cell, but a tap outside the active area of any cell should deselect the currently selected cell [single selection only; I don't need to support multi-selection at this point].
My original thought was to override the collection view's indexPathForItem(at:) and either the cell's touch event handlers or UICollectionView's touch event handlers. But, to make this work, I also need to know something about HOW the touch event handler interact with the UICollectionView. (This might be as simple as having touchesEnded(_:with:) call selectItem(at:animated:scrollPosition:) and deselectItem(at:animated:). Or?) Before I start possibly reinventing the wheel here, I'd like to ask if anyone has done anything similar and has any ideas to share. Thanks, Rick ------------------------- Consider a square cell which contains a diamond. The four vertices of the diamond are the midpoints of the four sides of the cell. The active region of each cell is the area inside the diamond. Cells are close-packed horizontally. Each section (i.e., "row") is offset a half-width down and a half-width to the side of the cells above it. In other words, the cells are positioned so that the diamond edges are superimposed. The attached image should give you an idea. |
|
On 2 Apr 2021, at 3:27 pm, Rick Aurbach via groups.io <rlaurb@...> wrote:Perhaps this is naïve, but the first thing that comes to mind: could you not simply deal with it as a regular matrix of squares, and then apply a 45 degree transform on the view? (I haven't tested anything like this, but I presume that touch events would be transformed accordingly…?) -ben |
|
It's an interesting idea, but there's an added complication (which I apologize for not making explicit in the original post) which makes this problematic. Each of these objects is a cell in a UICollectionView (with a custom Layout). I rather fear that without overriding pieces of touch processing, the collection view will not treat the rotated cell geometry properly.
Another way of thinking of this problem is as trying to create a non-rectangular collection-view cell which responds based on its shape, not its bounding box. |
|
Alex Zavatone
It would be interesting to try out. Try removing the spaces between each cell and issue the rotation, then try it out and find out.
toggle quoted message
Show quoted text
Alex Zavatone
|
|
On Apr 3, 2021, at 8:04 AM, Rick Aurbach via groups.io <rlaurb@...> wrote:Yes, so why not transform the collection view as a whole (not the cells)? -ben |
|
On 3 Apr 2021, at 8:46 am, Ben Kennedy <ben-groups@...> wrote:On Apr 3, 2021, at 8:04 AM, Rick Aurbach via groups.io <rlaurb@...> wrote: This piqued my curiosity, so I couldn't help myself and built a test case. This seems to work perfectly -- and no collection view required. The code is short enough that I've copy/pasted it all below. -ben class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let dimension = 4 let spacing = CGFloat(2.0) let containerStackView = UIStackView() containerStackView.axis = .vertical containerStackView.spacing = spacing containerStackView.alignment = .center containerStackView.distribution = .equalSpacing containerStackView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(containerStackView) NSLayoutConstraint.activate([ containerStackView.centerXAnchor.constraint(equalTo: view.centerXAnchor), containerStackView.centerYAnchor.constraint(equalTo: view.centerYAnchor), ]) for y in 1...(dimension * 2) { let rowStackView = UIStackView() rowStackView.axis = .horizontal rowStackView.spacing = spacing rowStackView.alignment = .center rowStackView.distribution = .equalSpacing rowStackView.translatesAutoresizingMaskIntoConstraints = false containerStackView.addArrangedSubview(rowStackView) for _ in 1...(y <= dimension ? y * 2 - 1 : (dimension * 2 - y + 1) * 2 - 1) { let cubbyHoleView = CubbyHoleView() cubbyHoleView.translatesAutoresizingMaskIntoConstraints = false rowStackView.addArrangedSubview(cubbyHoleView) NSLayoutConstraint.activate([ cubbyHoleView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.5 / CGFloat(dimension)), cubbyHoleView.heightAnchor.constraint(equalTo: cubbyHoleView.widthAnchor) ]) } } containerStackView.transform = CGAffineTransform.init(rotationAngle: -45.0 * CGFloat.pi / 180.0) } } class CubbyHoleView: UIView { let defaultBackgroundColor = UIColor.systemBlue.withAlphaComponent(0.1) init() { super.init(frame: .zero) backgroundColor = defaultBackgroundColor layer.borderColor = UIColor.black.cgColor layer.borderWidth = 2.0 } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { backgroundColor = .systemYellow } override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { backgroundColor = defaultBackgroundColor } } |
|