FUIAttachmentsCollectionViewCell

  • The reusable UI component implemented as a UICollectionViewCell to manage selecting attachments.

FUIAttachmentsCollectionViewCell uses a FUIAttachmentsViewController to display the title of the cell and a collection of icons to represent the attachments. The attachment icon size may change, depending on the system font size settings. The controller arranges the attachment icons so that as many icons can be fitted into a row as possible, in as many rows as possible, to display all the attachment icons. It will also try to make the row spacing equal to the spacing between icons. However, the row spacing is limited to a maximum of 20 pixels.

Developers should use the attachmentsController property to provide attachment information; the delegate, the dataSource and the list of FUIAttachmentAction implementations for the desired type of attachments. The app can use the built-in types or implement additional types as desired.

Color settings:

Setting tintColor to add a button for a state using the setTintColor(_:for:) API. Currently normal and .selected are supported.

 cell.setTintAttributes([NSAttributedString.Key.foregroundColor: UIColor.red], for: .actionTitle, state: .normal)

There are three versions of the built-in FUIAttachmentAction:

 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
     let cell = collectionView.dequeueReusableCell(withReuseIdentifier: FUIAttachmentsCollectionViewCell.reuseIdentifier, for: indexPath) as! FUIAttachmentsCollectionViewCell
     cell.attachmentsController.delegate = self
     cell.attachmentsController.dataSource = self

     let addPhotoAction = FUIAddPhotoAttachmentAction()
     addPhotoAction.delegate = self
     cell.attachmentsController.addAttachmentAction(addPhotoAction)

     let takePhotoAction = FUITakePhotoAttachmentAction()
     takePhotoAction.delegate = self
     cell.attachmentsController.addAttachmentAction(takePhotoAction)

     let filePickerAction = FUIDocumentPickerAttachmentAction()
     filePickerAction.delegate = self
     cell.attachmentsController.addAttachmentAction(filePickerAction)

     return cell
 }

 var attachmentURLs: [URL] = [URL]()

// MARK: FUIAttachmentsViewControllerDataSource methods
func attachmentsViewController(_ attachmentsViewController: FUIAttachmentsViewController, iconForAttachmentAtIndex index: Int) -> (image: UIImage, contentMode: UIViewContentMode)? {
    let urlString = self.attachmentURLs[index].absoluteString
    guard let image = self.attachmentThumbnails[urlString] else {
        return nil
    }
    return (image!, .scaleAspectFill)
}

func numberOfAttachments(in attachmentsViewController: FUIAttachmentsViewController) -> Int {
    return attachmentURLs.count
}

func attachmentsViewController(_ attachmentsViewController: FUIAttachmentsViewController, urlForAttachmentAtIndex index: Int) -> URL? {
    return attachmentURLs[index]
}

// MARK:  FUIAttachmentsViewControllerDelegateMethods
func attachmentsViewController(_ attachmentsViewController: FUIAttachmentsViewController, couldNotPresentAttachmentAtIndex index: Int) {

}

func focusOnNewAttachment() {
    DispatchQueue.main.async {
        if let cell = ... { // find the attachment cell
            if let newDoc = cell.accessibilityElements?.last {
                UIAccessibility.post(notification: .layoutChanged, argument: newDoc)
            }
        }
    }
}

func attachmentsViewController(_ attachmentsViewController: FUIAttachmentsViewController, didPressDeleteAtIndex index: Int) {
    self.attachmentURLs.remove(at: index)
    self.tableView.reloadSections(IndexSet(integer:attachmentSection), with: .automatic)
}


//MARK: FUIAddPhotoAttachmentActionDelegate
 func addPhotoAttachmentAction(_ action: FUIAddPhotoAttachmentAction, didSelectPhoto asset: PHAsset, at url: URL) {
    setupThumbnails(url, with: asset)
    self.addAttachmentURL(url)
}

//MARK: FUITakePhotoAttachmentActionDelegate

func takePhotoAttachmentAction(_ action: FUITakePhotoAttachmentAction, didTakePhoto asset: PHAsset, at url: URL) {
    setupThumbnails(url, with: asset)
    self.addAttachmentURL(url)
}


func addAttachmentURL(_ url: URL) {
    self.attachmentURLs.append(url)
    DispatchQueue.main.async {
        self.tableView.reloadSections(IndexSet(integer:self.attachmentSection), with: .automatic)
        self.tableView.scrollToRow(at: IndexPath(row: 0, section: self.attachmentSection) , at: .middle, animated: true)
        if UIAccessibility.isVoiceOverRunning {
            focusOnNewAttachment()
        }
    }
}

 func setupThumbnails(_ url: URL, with asset: PHAsset) {
     let imageManager = PHImageManager.default()
     imageManager.requestImage(for: asset, targetSize: CGSize(width: 80, height: 80), contentMode: .default, options: nil, resultHandler: { image, array in
         self.attachmentThumbnails[url.absoluteString] = image
         DispatchQueue.main.async {
             self.tableView.reloadSections(IndexSet(integer:self.attachmentSection), with: .automatic)
             self.tableView.scrollToRow(at: IndexPath(row: 0, section: self.attachmentSection) , at: .middle, animated: true)
         }
     })
 }

 //MARK: FUIDocumentPickerAttachmentActionDelegate {
 var documentPicker: UIDocumentPickerViewController {
     return UIDocumentPickerViewController(documentTypes: ["public.data"], in: .import)
 }

 func documentPickerAttachmentAction(_ action: FUIDocumentPickerAttachmentAction, didPickFileAt url: URL) {
     if let savedUrl = saveFileToTempFolder(url) {
         self.addAttachmentURL(savedUrl)
     }
     self.tableView.reloadSections(IndexSet(integer:self.attachmentSection), with: .automatic)
     if UIAccessibility.isVoiceOverRunning {
        focusOnNewAttachment()
     }
 }

## Theming

Supported TEXT class paths:

 fdlFUIAttachmentsFormView_attachmentTitleLabel {}
 fdlFUIAttachmentsViewController_alertActionTitle {}
 fdlFUIFileThumbnailCollectionItemView_titleLabel {}

Supported TEXT properties:

 font-color: Color;
 font-style: UIFontTextStyle;

Supported IMAGE class paths:

 fdlFUIFileThumbnailCollectionItemView_detailImageView {}

Supported IMAGE properties:

 tint-color: Color;

Supported BUTTON class paths:

fdlFUIAddButtonCell_addButton {}

Supported BUTTON properties:

 image: Image;
 tint-color: Color;

Supported CELL class paths:

 `fdlFUIAttachmentsFormCell_thumbnailCell {}`
 fdlFUIAttachmentsFormCell_addButtonCell {}

Supported CELL properties:

 border-color: Color;
 border-width: Integer;
 corner-radius: Integer;

Supported style classes

  • The controller managing the attachments displayed by this cell.

    Declaration

    Swift

    open private(set) var attachmentsController: FUIAttachmentsViewController { get }
  • Indicates whether the user can add an attachment or not. If this is true, a “+” button is displayed. When the user taps the button, it will bring up the “Add Attachment” pop-up allowing the user to select an additional attachment. Otherwise, the “+” button will not be shown. The default is true.

    Declaration

    Swift

    public var isEditable: Bool { get set }
  • isEnabled and isEditable are in sync.

    Declaration

    Swift

    public var isEnabled: Bool { get set }
  • Undocumented

    Declaration

    Swift

    public override init(frame: CGRect)
  • Declaration

    Swift

    public required init?(coder: NSCoder)
  • Declaration

    Swift

    public var state: UIControlState
  • Declaration

    Swift

    public func stateDidChange()
  • Declaration

    Swift

    public func setTintColor(_ color: UIColor, for state: UIControlState)
  • Declaration

    Swift

    public func tintColor(for state: UIControlState) -> UIColor?