FUIAttachmentsCollectionViewCell
open class FUIAttachmentsCollectionViewCell : FUIInlineValidationDrawingCollectionViewCell<FUIAttachmentCellView>, FUIStateTintable
- 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
:
FUIAddPhotoAttachmentAction
: Choose photo from the photo library.FUITakePhotoAttachmentAction
: Take photo using the camera.FUIDocumentPickerAttachmentAction
: Select file using the standardUIDocumentPickerViewController
.
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 istrue
.Declaration
Swift
public var isEditable: Bool { get set }
-
isEnabled
andisEditable
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?