Timeline Widgets
iOS guide to Timeline Widgets
What are Timeline Widgets?
Timeline Widgets are a way to present Widgets in a scrollable list which user's can browse and interact with past widgets.
You can implement Timeline Widgets into your iOS application using the InteractiveWidgetTimelineViewController
. It is a UIViewController provided by the EngagementSDK.
Setup
Create an instance of the InteractiveWidgetTimelineViewController with a ContentSession and apply layout constraints.
class MyViewController: UIViewController {
private let timelineVC: InteractiveWidgetTimelineViewController
init(contentSession: ContentSession) {
self.timelineVC = InteractiveWidgetTimelineViewController(contentSession: contentSession)
super.init(nibName: nil, bundle: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
// Add timelineVC to layout
addChild(timelineVC)
timelineVC.didMove(toParent: self)
timelineVC.view.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(timelineVC.view)
// Apply layout constraints
NSLayoutConstraint.activate([
timelineVC.view.topAnchor.constraint(equalTo: view.topAnchor),
timelineVC.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
timelineVC.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
timelineVC.view.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
}
}
Apply Theme
By overriding the makeWidget method of the InteractiveWidgetTimelineViewController you can apply the theme to the stock widgets.
class MyTimelineViewController: InteractiveWidgetTimelineViewController {
let myTheme = Theme()
override func makeWidget(_ widgetModel: WidgetModel) -> UIViewController? {
let widget = DefaultWidgetFactory.make(from: widgetModel)
widget?.theme = myTheme
return widget
}
}
Using Custom Widget UI
By default, the InteractiveWidgetTimelineViewController will display widgets using the stock Widget UI. If you have built your own Custom Widgets styles it is easy to display those in the InteractiveWidgetTimelineViewController.
You will need to make a subclass of InteractiveWidgetTimelineViewController and override the makeWidget
method. In the makeWidget
method return the UIViewController
that represents the widget. You can also use DefaultWidgetFactory
to make an instance of the stock UI that represents the widget.
class MyTimelineViewController: InteractiveWidgetTimelineViewController {
override func makeWidget(_ widgetModel: WidgetModel) -> UIViewController? {
switch widgetModel {
case .alert(let alertModel):
// return the UIViewController that represents the widget
default:
// you can use the DefaultWidgetFactory to use the stock UI
return DefaultWidgetFactory.make(from: widgetModel)
}
}
}
Filtering Widgets
You may want to hide specific widgets types from appearing in the timeline - here is how you can do that:
In this example we will filter all Alert Widgets from being displayed in the timeline.
class MyTimelineViewController: InteractiveWidgetTimelineViewController {
override func didLoadInitialWidgets(_ widgetModels: [WidgetModel]) -> [WidgetModel] {
// filters the alerts from the initial widgets loaded from history
return widgetModels.filter { $0.kind != .alert }
}
override func didLoadMoreWidgets(_ widgetModels: [WidgetModel]) -> [WidgetModel] {
// filters the alerts from the next widgets loaded from history
return widgetModels.filter { $0.kind != .alert }
}
override func didReceiveNewWidget(_ widgetModel: WidgetModel) -> WidgetModel? {
// filters a new widget if it is an alert
guard widgetModel.kind != .alert else { return nil }
return widgetModel
}
}
Add Custom Spacer between Widgets
By subclassing the InteractiveWidgetTimelineViewController, you can override some UITableViewDelegate methods in order to add a custom view between widgets. The example below adds a view of height 40 and alternates between blue and red for the backgroundColor.
class MyTimelineViewController: InteractiveWidgetTimelineViewController {
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 40
}
override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let separatorView = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: 40))
if section % 2 != 0 {
separatorView.backgroundColor = .blue
} else {
separatorView.backgroundColor = .red
}
return separatorView
}
}
Updated about 1 year ago