in viewDidLoad :
viewPager.dataSource = self
--
extension DetailsViewController:ViewPagerDataSource{
func numberOfItems(_ viewPager:ViewPager) -> Int {
return dict!.count
}
func viewAtIndex(_ viewPager:ViewPager, index:Int, view:UIView?) -> UIView {
func viewAtIndex(_ viewPager:ViewPager, index:Int, view:UIView?) -> UIView {
return view
the result is slow , it does not show the animation of transition maybe cuz I return the scrollview view not normal view , and when I swipe to left it shows nothing (swipe backwards) , is there anything better to implement ?
thanks for help.
Your question isn't very clear, and then you post a BUNCH of code, including code that's irrelevant to your question. You should only post the parts that directly relate to your question.
It looks like what you want is a UIPageViewController. That manages an array of view controllers, each of which holds the contents of one page. You can either user it with a page curl animation like iBooks, or a scrolling mode. You want the scrolling mode.
If you search in the Xcode help (or online, it looks like the link to download the app isn't in Xcode 8) on "PhotoScroller" You'll find a demo app that illustrates how it works.
That app is written in Objective-C, but it will at least show you the UI it offers.
In order to use a UIPageViewController you'll have to restructure your detail view controller to manage an array of child view controllers instead of only using a single view controller.
If you want side scrolling AND up and down scrolling among a grid of tiles then you want a collection view instead, but that's more work to set up.
Related
Is there any way to easily achieve the results in the pictures below (maybe by using MGSwipeTableCell or SwipeCellKit or any other pod you know of). I'm pretty sure you can't do that using the default iOS UIKit.
There are 2 things here to consider:
1) The table view cell swipe actions, should be completely customisable (putting an UIView there, so you can put anything you want inside the UIView) or at least, get closer to the screenshot, using 1 and then 5 buttons (therefore, different swipe-actions for smallswipe and fullswipe) ?
2) The tableview cell swipe action, must first (small-swipe) only show the "alarm' icon like in the first picture, and if you click on it, or swipe even further it should look like in the second picture, and most importantly, stay like that, no auto-unswiping (no action to be done, except waiting for input from user, to either select another cell, or any of the buttons there).
I'm not asking for a complete solution, I just want to know if it's possible and relatively easy to do, so I won't waste weeks in order to try to achieve this and find out in the end that it's not possible.
SmallSwipe
FullSwipeOrClick
I think in you tableCell, you can add view to contentView, that will be fill all cell and drag it via UIPanGestureRecognizer. Your action views will be under scrollable view. Something like this:
class SwipableTableViewCell: UITableViewCell {
#IBOutlet var actionView: UIView // under mainView
#IBOutlet var mainView: UIView // take whole place of contentView
#IBOutlet var panGesture: UIPanGestureRecognizer
#IBAction func panAction(_ sender: UIPanGestureRecognizer) {
// drag main view left or right and logic of auto swiping
}
}
I really don't know if you can make a small and full swipe native. The method for swipe for iOS 11 is tableView(_:trailingSwipeActionsConfigurationForRowAt:).
From there, I know there is performFirsActionWithFullSwipe, that doesn't allow full swipe on the first time. I think you can play with this two. In configuration you can add UIContextualAction that has an action, image and even background color that you can set.
I hope it helps.
I am attempting to implement a "Share" feature in my iOS app with a similar look and feel to that of the Google Photos iOS app:
The bottom two rows of icons are what I care about. They look nearly identical to those displayed when using the UIActivityViewController.
In the Google Photos app, these icons appear inline with the "select photos" portion of the screen (e.g. you can still interact with the upper portion of the screen). However, the documentation for the UIActivityViewController states that "On iPhone and iPod touch, you must present [the view controller] modally."
This is the difference that is really important to me -- I'd like for the "share" icons to display inline with the rest of my content, rather than having a modal that is displayed on top of my content.
Is it possible to use the UIActivityViewController to achieve a similar effect shown in the screenshot above? If not, is there a recommended approach that I might use to implement this sort of functionality?
As discussed in another answer, reverse engineering UIActivityViewController is the only option in order to be able to achieve a similar effect. I tried this using iPhone 6s - 10.3 Simulator. The following findings may not be accurate for iOS 9.x or 11.x or above.
A. Find out all internal variables for UIActivityViewController
var variablesCount: UInt32 = 0
let variables = class_copyIvarList(UIActivityViewController.self, &variablesCount)
for i in 0..<variablesCount {
if let variable = variables?[Int(i)] {
let name = String(cString: ivar_getName(variable))
let typeEncoding = String(cString: ivar_getTypeEncoding(variable))
print("\(name)\n\(typeEncoding)\n\n")
}
}
free(variables)
The ones those got my attention at first sight are (in order) -
_activityViewController
#"UIViewController"
_contentController
#"_UIActivityViewControllerContentController"
_activityAlertController
#"UIAlertController"
On inspecting them further, I found out that _contentController is the one we should be looking for. We need to look one level deeper in hierarchy for UICollectionViewController to get to where we want to be.
if let activityContentController = activityVC.value(forKeyPath: "_contentController") as? UIViewController {
print("Found _contentController!")
for child in activityContentController.childViewControllers {
print(String(describing: child))
if child is UICollectionViewController {
print("Found UICollectionViewController!")
break
}
}
}
Why did I look for UICollectionViewController?
Debug View Hierarchy has the answer for this.
I tried adding this as a childViewController to my UIViewController -
self.addChildViewController(child)
child.didMove(toParentViewController: self)
self.view.addSubview(child.view)
child.view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
child.view.topAnchor.constraint(equalTo: self.view.topAnchor),
child.view.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
child.view.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
child.view.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
])
IT SHOWS UP CORRECTLY ONLY IF YOU HAVE LOADED/PRESENTED UIActivityViewController FIRST.
I was able to achieve this using a silent present/dismiss call -
self.present(activityVC, animated: false, completion: {
self.dismiss(animated: false, completion: nil)
})
IS THIS APP STORE SAFE? - Most likely not.
As soon as you start stealing the view(s) or viewController(s) from UIKit's standard components, the behavior is not stable and it will break with upcoming updates for sure.
What Google Photos has is the result of way more advanced reverse engineering. In above implementation, you can't see More option screen. The hierarchy UIActivityViewController expects is broken.
Hope this helps.
Okay, I thought about this and I did some intensive research on the web but nobody ever seemed to needed to modify it like you want. So here are my guesses how Google engineers solved this:
They reverse engineered the UIActivityViewController and call some private APIs to get the same icons to show up and the reordering controllers
They use the UIViewController transitioning API and hack the view hierarchy of a modally presented UIActivityViewController, removing the cancel button and adding some custom views on top of its view
An indicator for the second option could be that the top of the presented "sheet" has a white background while the bottom has the greyish color.
Unfortunately I'm not very fit with the transitioning API as I'm just about to learn it but my understanding is that you can provide a custom object as the transitioning delegate.
This object then gets called when you present/dismiss or push/pop a UIViewController. It will get a reference to both, the presenting and the presented view controller and you can have fun with both of their views.
This should make it "quiet" easy to remove and add some subviews, change frames and colors etc while still having all the default behavior.
I hope this answer helps you to achieve what you want. However, be aware that the structure of the controller could change at any time so always make sure to also test agains betas so that you don't get caught by surprise when apple releases an update which breaks your UI. :)
I understand the concept that the focus engine will decide what can be selected. It also seems that it moves linearly vertically or horizontally and tries to find the next closest neighbor whose view intersects that vertical or horizontal line.
The problem I haven't solved just yet is how to set things up so that panning to switch between focusable subviews does not get prevented if one of them has a scrollable area (like a map).
I have two collection views that take up the width of the screen and sit one on top of the other. I can pan to switch between these just fine. Here is the code that overrides their shared custom UICollectionView class
override public func canBecomeFocused() -> Bool {
return true
}
public override func shouldUpdateFocusInContext(context: UIFocusUpdateContext) -> Bool {
return true
}
public override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
super.didUpdateFocusInContext(context, withAnimationCoordinator: coordinator)
}
In a separate view controller, I have a map view and a collection view above it. Both take up the width of the screen. I can pan to switch from the collection view down to the map view, but no matter how slow or fast I try to pan/swipe up, I cannot get the map view to lose its focus.
I did try adding some gesture recognizers and setting the delegate methods to try and make my GR win over the map view's scrolling GRs, but to no avail.
Any one else have similar experience? How do I get back out of the map view without having to add another dialogue or something to switch context back to the collection view?
Thank you in advance.
I'm sure there are a number of ways to solve the problem (like the one suggested in the comment by Eugene for example). In general, you'll probably need to determine when you want the focus to leave the map and trigger a focus update with setNeedsFocusUpdate(), updateFocusIfNeeded(). You would then override preferredFocusView (part of UIFocusEnvironment which is adopted by UIViewController and UIView among other things), to set the focus to whatever you want.
The real trick is to determine when it's appropriate to do this. A map is particularly hard because it's possible that it may scroll for a very long time prior to hitting a boundary (if it ever does). As such, you may need to utilize a button press as suggested by Eugene or perhaps by implementing some of the MKMapViewDelegate methods like mapView(_:regionWillChangeAnimated:) to determine when the map has moved a large distance. The "correct" answer would be determined by your desired behavior, of course.
Ok, so I will apologize in advance, but I am a complete noob to Swift and iOS development, but I really want to learn to code. I have followed quite a few tutorials and so forth online, but cannot seem to find an answer for this problem I am having. There has to be a simple solution to this because it doesn't seem like a very hard issue but the googles are not being my friend in finding an answer. I do not want to use storyboards because I want to learn the real meat and potatoes. I am using OS X 10.11, Xcode 7, writing the app for iOS 9, universal.
So, I designed a calendar app with quite a unique display, UI, and functionality than the other grid based calendars out there. I have a UIView that I want to be a container to hold the other views I need and pull them into the container view. The files I have are the included ViewController.swift and my custom files ContainerView.swift HeaderView.swift, CalView.swift, and CalDetailView.swift. I set classes for each file, the HeaderView is a basic UIView, CalView is a horizontal UIScrollView that enables pagination for the different calendar views like week, month, day, year, and so on. The CalDetailView is also a horizontal UIScrollView that will display event details to the user and also be the primary action area for the user for editing, adding events, etc.
Currently the ContainerView loads just fine and I can do whatever I want there and can create these other subviews without a problem but only in the ContainerView file. I want to keep these areas separated out into different files for my sanity and add them into ContainerView UIView as subViews with AutoLayout and everything, just like I am able to do inside the ContainerView file, but it would be enormous and I don't want that.
I believe the proper way to do this is to add these subViews under the viewDidLoad() method of the main VC and create my AutoLayout constraints in the VC file, then I just want to load my subViews in the ContainerView file and build the screen. The separate subView files will contain all of my drawing code and touch events and so forth for the views.
Here's a simple wireframe of what I am trying to accomplish...
The whole window is ContainerView.swift the rest, subViews of ContainerView.
WireFrame
This question is a little open ended and non specific, but let's ignore this for now (it is your first time), in future please be more specific, this is the kind of response a tutorial might be better providing. You will have enough to do, without avoiding Storyboards - feel free to use them.
In any case it is fine.
Given a UIView subclass MyView, in your main view controller:
override func viewDidLoad() {
super.viewDidLoad()
....
let myView = MyView()
self.view.addSubView(myView)
myView.frame = ... OR <SET CONSTRAINTS>
....
}
Essentially you will initialise those view subclasses and add them as appropriate.
Note: Using Monotouch and doing all the UI Programatically.
Hello everybody,
I have a question.
I have this main UIViewController object, and I have 2 UIVIews inside it. This views will perform commands in some devices, etc. I'm planning to do some menu with a slider effect appearing from the left side as it's drawn below. In this menu the user will select some buttons, and this is gonna make to change the another two UIViews.
Here's my question:
I'm planning to use Modal View Controller as UIModalPresentationPageSheet, but how can It appear at the center of the screen horizontaly. I'd like to put it on the center on the left side. How can I change it?
If it's impossible, should I use the UIPopover?
Image Below
Thank you.
Lyniker
I don't think either will get you the animation effect you want. In general I would choose to slide in a view using UIView animation:
if(IsDrawerVisible == false) {
UIView.Animate(0.5, () => {
DrawerView.Frame = new RectangleF(
this.View.Bounds.Left + 300,
DrawerView.Frame.Y,
DrawerView.Frame.Width,
DrawerView.Frame.Height);
}, UIViewAnimationOptions.CurveEaseIn);
}
else {
// Move the frame of the DrawerView by subtracting from Frame.X
}
Of course you need a reference point (usually the parent UIView's left bounds) and do the appropriate calculations to move the "Drawer" component into view. This can be arbitrary though :-)
NOTE: If DrawerView is of type UIViewController / DialogViewController please use the new iOS 5 custom containment APIs or you'll get some seriously wonky behavior. See my blog post on child view controllers here:
http://blog.devnos.com/wont-somebody-please-think-of-the-children