Dimming other cells in UICollectionView when a cell is selected - ios

I'm trying to build a UICollectionView for a messaging application, where each UICollectionViewCell in the UICollectionView corresponds to a message. I am using MessageKit, which extends UICollectionView, to handle the messages. When the user taps a message, I want to reveal information about the message (time sent, user reactions to the message, etc.).
GroupMe does this in a very elegant way by (1) expanding the message vertically to reveal information, and (2) dimming the rest of the messages in the view and disabling user interaction for them. Note that the highlighted cell is still interaction enabled. See before/after images below.
Before tapping message
After tapping message
Here I am focused on achieving (2), i.e. when a message is tapped, I want to dim all other cells and disable user interaction for them. I also want to be able to animate this change so that it dims all the other cells over some short duration. When the user taps anywhere in the view, I'd like the highlighted cell to 'unhighlight', and user interaction to be re-enabled for all cells, and similarly animate the revert.
I'm a little stumped on how to achieve this behavior - any ideas on how to implement this in Swift? Any pointers that could get me started in the right direction would be greatly appreciated!

You could add a UIView for each Cell’s subview, except for the one selected. This view could be animated by changing the alpha value with fading/appearing effect.

You can override isSelected property in your custom UICollectionViewCell to handle the user interaction and alpha on cell selection, i.e.
class CollectionViewCell: UICollectionViewCell {
override var isSelected: Bool {
didSet {
self.isUserInteractionEnabled = self.isSelected
self.alpha = self.isSelected ? 1.0 : 0.5
}
}
//rest of the code...
}

Related

Why is my UI Button working but not animating or indicating to the user?

I have added a UI Button inside of a stack view which is inside of a table view in my storyboard. When I click on my button the correct output is printed in my debugger console but there is no indication in the app that the button has been clicked (no default animation). I have tried looking at my view hierarchy and changing all of the parent views to clip to bounds. Any idea why the button is functioning but not being animated to the user?
The quick fix to your problem is to set delaysContentTouches = false for your table view.
According to the Apple Docs,
If the value of this property is true, the scroll view delays handling the touch-down gesture until it can determine if scrolling is the intent. If the value is false, the scroll view immediately calls touchesShouldBegin(_:with:in:). The default value is true.
See the class description for a fuller discussion.
Alternatively, if you have subclassed the UIScrollView, you can get the same thing done by overriding the following function,
class MyScrollView: UIScrollView {
override func touchesShouldCancel(in view: UIView) -> Bool {
return type(of: view) == UIButton.self
}
}

How to retain previous selection in collectionview after reload in Apple TV

Hi in my Apple TV application i have one left collectionview right collectionview.Like splitview.When ever i focus cell on left data will refresh on right and when i select any cell in right collection view i am refreshing left and right collectionviews with new data (Like next level).And when on click on menu i will refresh both collectionviews with old data (Like coming to previous level). I want to highlight cell in left collectionview with red colour but i am reloading left collectionview while going forward or coming backward so always first cell is highlighting with Red colour. Can anyone suggest how to maintain previous selection in left collection-views because i am using only one collectionview for left menu and just reloading data.
The easiest way to retain focus in a UITableView or UICollectionView is to use UICollectionView.remembersLastFocusedIndexPath = true. This will automatically restore focus to the last focused item in a collection/table view and also automatically focus on the first item if there was no previously focused item or if the collection view data is reloaded.
If you need more control, the next level is to set UICollectionView.remembersLastFocusedIndexPath = false and use UICollectionViewDelegate.indexPathForPreferredFocusedView from your UIViewController instead. This method is only called whenever focus changes to a collection view programmatically though (but not if focus changes to a collection view as a result of TV remote interaction).
Now to ensure that indexPathForPreferredFocusedView is called when you switch between the left and right collection views using a TV remote, you will need to intercept shouldUpdateFocusInContext to override focus switches between the left and right collection view programmatically:
override func shouldUpdateFocusInContext( ... ) -> Bool {
if let nextView: UIView = context.nextFocusedView, let previousView: UIView = context.previouslyFocusedView{
if (nextView.isDescendant(of:leftCollectionView) && previousView.isDescendant(of:rightCollectionView)){
setFocusTo(leftCollectionView) // will invoke delegate indexPath method
return false // prevent system default focus change in favor of programmatic change
}
else if (nextView.isDescendant(of:rightCollectionView && previousView.isDescendant(of:leftCollectionView){
setFocusTo(rightCollectionView) // will invoke delegate indexPath method
return false
}
}
return true
}
internal var focusedView: UIView?
internal func setFocusTo(_ view:UIView){
focusedView = view
setNeedsFocusUpdate()
}
override var preferredFocusEnvironments -> [UIFocusEnvironment]{
return focusedView != nil ? [focusedView!] : super.preferredFocusEnvironments
}
func indexPathForPreferredFocusedView(in collectionView: UICollectionView) -> IndexPath? {
...
}
Alternatively, instead of using setFocusTo( collectionView ) + indexPathForPreferredFocusedView, you can just use setFocusTo( collectionViewCell ). Overriding indexPathForPreferredFocusedView is more robust though since it catches all cases where focus shifts for reasons other than user interaction (ex: system focus update due to an alert displaying + dismissing)

IBAction from TableViewCell triggers multiple cells

I have a UITableViewController with dynamic cells.
in my tableViewCellForRowAtIndexPath I set the indexPath.row as tag to one of my subviews from that cell. This subview has an IBAction when one clicks on it.
In my custom TableViewCell I call a listener when this subview is clicked and give the value of the tag as parameter, so that my TableViewController can act on it.
This is what I do then: (it is in java, because I am using multi-os-engine but it is very similar to swift/obj-c)
#Override
public void onOrderClicked(long index) {
OrdersTableViewCell cell = (OrdersTableViewCell) ordersList().cellForRowAtIndexPath(NSIndexPath.indexPathForRowInSection(index, 0));
if (cell.arrowView().image().equals(UIImage.imageNamed("downarrow"))) {
cell.arrowView().setImage(UIImage.imageNamed("uparrow"));
cell.orderDetailsView().setHidden(false);
}
else {
cell.arrowView().setImage(UIImage.imageNamed("downarrow"));
cell.orderDetailsView().setHidden(true);
}
Basically I just change the hidden state of one subview in my cell. Actually this works fine. BUT when clicking on one of my elements, the subview hidden state sometimes changes not only from this cell, but also from another one. I don't understand why. For more information: There are multiple cells so, that I even have to scroll to see them all. And when clicking on one of my cells, the hidden state of another cell changes too, which is not in the screen atm.
Anyone has a hint what I am doing wrong or why this is happening?

Handle the button list in UITableViewCell

I’m continuing to the last ViewController in my movie booking project. Because I’m new on iOS so please apologize if my question is so popular and very basic. Thank you in advance!.
So I have trouble to solve problem with the list of buttons in the cell.
E.g:
I have the swift class file for the button:
class ButtonReverse: UIButton {
require.init()
//something here. Color, etc.
}
class TypeOfSeat {
var normalSeat: Bool
var coupleSeat: Bool
var reversedSeat: Bool
var reversingSeat: Bool
// something here
}
class Total: TypeOfSeat {
var priceOfSeat: Int
func invoice () -> Int {
/// something here to return total of invoice.
// return total }
In the UITableViewCell.
I have list of the buttons to be ordered vertically.
How can I loop over the cell and create list of the buttons in one cell and random the button color that I have defined before be implement the function:
cellForRows at: IndexPath
All of buttons will be sorted in just one cell. Red is reversed seats. Yellow is reversing seat. And Green is available seat ready for reverse.
I have idea to use uicollectionview. But I want to use it with tableview only because i’m just starting with uitableview.
To handle the button in the cell I’m just using simple function to call delegate for UIAlert and show message: the seat is reversed or show the total......when user touch the button.
Many thanks,
To achieve your desired result you can follow these steps :
Use CollectionView.
Take your colors in an array and use random to get color randomly and make an array for your collection (say dataArray).
If you are using buttons just to click, then don't use them instead you can give cell's content view (or you can take one view in cell) corner radius to make them circle and assign the color.
Then implement didSelectItem method to get the click item of particular cell (or color) and fetch the data from your dataArray based on indexPath.item as index.

UIButton never fires off code in Action

I have the following screen:
The X is the image of a UIButton, I have add the appropriate action to the button. Yet when I click on the button it never fires off the code in the action.
Here is some code:
#IBAction func CloseProfilePage(sender: AnyObject) {
self.removeAnimate();
}
This is the code that is used to launch the view controller seen:
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let selectedAppointment = self.dayDatasource!.appointmentAtIndex(indexPath.item);
let profilePageViewController = ProfilePageViewController.init(withAppointment: selectedAppointment);
profilePageViewController.view.frame = self.view.frame
self.view.addSubview(profilePageViewController.view)
profilePageViewController.didMoveToParentViewController(self)
}
The button is definitely connected in the xib to the action:
When I check in the view hierachy, there isn't anything else on top of the button that would prevent the button but registering clicks. I'm assuming here that the imageView in the UIButton is clickable as its part of the button iteself.
The X in the image is not an image view I added, it is the image view that comes with the UIButton. With that said I've also resorted to the following:
self.profilePageClosePopUpButton.imageView?.userInteractionEnabled = true;
Still the button remains unclickable. Where am I going wrong?
It pains me to say this but I'm only writing a solution here just in case someone in the future struggles with the same issue and maybe this post could help them.
In the view, seen in the image below, I had some how unintentionally switched off User Interaction Enabled in interface builder. Because this was off, all other children didn't have interaction enabled on them and hence why the button was not clickable...
Moral of the story is, check your parent views and make sure their user interaction is enabled as well.

Resources