UIPageViewController with Peeking
I rewrite Kevin Jantzer answer in swift 4 and it's works!
override func viewDidLoad() {
super.viewDidLoad()
let pad: CGFloat = 20
let items: [UIColor] = [.blue, .yellow, .red, .green]
self.view.backgroundColor = .white
var pageScrollView = UIScrollView(frame: self.view.frame)
pageScrollView.isOpaque = false
pageScrollView.showsHorizontalScrollIndicator = false
pageScrollView.clipsToBounds = false
pageScrollView.isPagingEnabled = true
adjustFrame(myView: pageScrollView, x: pad, y: UIScreen.main.bounds.height / 4, w: -pad * 3, h: -UIScreen.main.bounds.height/2)
self.view.addSubview(pageScrollView)
let w = pageScrollView.frame.size.width
for (i, item) in items.enumerated() {
let myView = UIView(frame: pageScrollView.bounds)
myView.backgroundColor = item
setFrameX(myView: myView, x: (CGFloat(i) * w) + pad);
setFrameW(myView: myView, w: w-(pad*1));
pageScrollView.addSubview(myView)
}
pageScrollView.contentSize = CGSize(width: w * CGFloat(items.count), height: pageScrollView.frame.size.height);
}
func setFrame(myView: UIView, x: CGFloat?, y: CGFloat?, w: CGFloat?, h: CGFloat?){
var f = myView.frame
if let safeX = x {
f.origin = CGPoint(x: safeX, y: f.origin.y)
}
if let safeY = y {
f.origin = CGPoint(x: f.origin.x, y: safeY)
}
if let safeW = w {
f.size.width = safeW
}
if let safeH = h {
f.size.height = safeH
}
myView.frame = f
}
func setFrameX(myView: UIView, x: CGFloat) {
setFrame(myView: myView, x: x, y: nil, w: nil, h: nil)
}
func setFrameY(myView: UIView, y: CGFloat) {
setFrame(myView: myView, x: nil, y: y, w: nil, h: nil)
}
func setFrameW(myView: UIView, w: CGFloat) {
setFrame(myView: myView, x: nil, y: nil, w: w, h: nil)
}
func setFrameH(myView: UIView, h: CGFloat) {
setFrame(myView: myView, x: nil, y: nil, w: nil, h: h)
}
func adjustFrame(f: CGRect, x: CGFloat?, y: CGFloat?, w: CGFloat?, h: CGFloat?) -> CGRect {
var rect = f
if let safeX = x {
rect.origin = CGPoint(x: rect.origin.x + safeX, y: f.origin.y)
}
if let safeY = y {
rect.origin = CGPoint(x: f.origin.x, y: rect.origin.y + safeY)
}
if let safeW = w {
rect.size.width = safeW + rect.size.width
}
if let safeH = h {
rect.size.height = safeH + rect.size.height
}
return rect
}
func adjustFrame(myView: UIView, x: CGFloat, y: CGFloat, w: CGFloat, h: CGFloat) {
myView.frame = adjustFrame(f: myView.frame, x: x, y: y, w: w, h: h);
}
}
Like @davew said, peeking views will need to use UIScrollView
. I too searched for a way to use UIPageViewController
but couldn't find any resource.
Using UIScrollView
to make this feature was less painful that I had imagined.
Here is a simple example to see the basic controls in action.
First: make a UIViewController
, then in the viewDidLoad
method, add the following code:
float pad = 20;
NSArray* items = @[@"One", @"Two", @"Three", @"Four"];
self.view.backgroundColor = [UIColor greenColor];
UIScrollView* pageScrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];
pageScrollView.opaque = NO;
pageScrollView.showsHorizontalScrollIndicator = NO;
pageScrollView.clipsToBounds = NO;
pageScrollView.pagingEnabled = YES;
adjustFrame(pageScrollView, pad, deviceH()/4, -pad*3, -deviceH()/2);
[self.view addSubview: pageScrollView];
float w = pageScrollView.frame.size.width;
for(int i = 0; i < [items count]; i++){
UIView* view = [[UIView alloc] initWithFrame:pageScrollView.bounds];
view.backgroundColor = [UIColor blueColor];
setFrameX(view, (i*w)+pad);
setFrameW(view, w-(pad*1));
[pageScrollView addSubview:view];
}
pageScrollView.contentSize = CGSizeMake(w*[items count], pageScrollView.frame.size.height);
FYI, I used these util functions to adjust the size of the view frames; I get sick of manually changing them with 3+ lines of code.
Update
I have wrapped up this code in a simple ViewController and put it on GitHub
https://github.com/kjantzer/peek-page-view-controller
It is in no way complete, but it's a working start.
I was just searching for a good solution to the same feature. I found a nice tutorial on Ray Wenderlich's site titled "How To Use UIScrollView to Scroll and Zoom Content". It illustrates multiple things you can do with UIScrollView
. The fourth and final is "Viewing Previous/Next Pages" which is your "peek" feature.
I haven't implemented this yet, but the key steps seem to be:
- Create a
UIScrollView
narrower than your screen - Turn on
Paging Enabled
- Turn off
Clip Subviews
- Fill the
UIScrollView
with your pages side by side - Embed the
UIScrollView
inside aUIView
that fills the width of the screen so that you can capture and pass touches outside the Scroll View