To keep a complete design control over my project I am using a static View Controller for my main application window where I superpose labels and buttons over my images.
The issue is obviously that I now need to add a refresh control to the view and since I am not using a Table View I don't have the Enable Refresh option.
Is there any simple trick to implement a pull-to-refresh control or am I forced to reproduce my design to Table View Cells?
I found a solution using a scroll view, here is what I did:
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(doSomething), for: .valueChanged)
scrollView.refreshControl = refreshControl
}
#objc func doSomething(refreshControl: UIRefreshControl) {
print("Hello World!")
refreshControl.endRefreshing()
}
I needed to extand the scroll view height to cover the pull extension at the top and at the bottom. I also added a background image to cover the white area that the pull created.
Now I need to write the code to update the data.
Related
Hi in my app I have a stretchy header and I am adding my refresh control like this tableView.addSubview(refreshControll)
But when using it, it is in middle or bottom of my view and not pinned to the top how do I fix this?
Since iOS 10 or iOS 11 UITableView and UICollectionView have gotten their own refresh control option.
var refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(reloadData), for: UIControl.Event.valueChanged)
tableView.refreshControl = refreshControl
You can also look at the Apple documentation about UITableViewController.
From iOS 10 you have two options to add a refresh control to a UIScrollView:
You can add it to the tableView like another refresh control :
tableView.addSubview(refreshControl)
This will show the refreshControl on top of the UITableView, more precisely like if it was added to the tableHeaderView.
The other option, is to use the already included refreshControl in the UIScrollView classes:
tableView.refreshControl = UIRefreshControl()
With this option the UIViewController takes control of where to put the refreshControl, since iOS 10 will move it to the top of the view just above the navigation bar. Check Mail app on the iPhone to see and example.
refreshControl.addTarget(self, action: #selector(refresh( sender:)), for: .valueChanged)
tableView.insertSubview(refreshControl, at: 0)
func refresh(sender: UIRefreshControl) {
sender.beginRefreshing()
// refresh tableview datasource
refresh()
}
I have trouble hiding refreshControl once a user leaves the ViewController while refreshControl is still visible. I have tried setting it removing it from superView (tableView), replacing it with new one, etc... The issue still remains with tableView when user returns to the screen, top content insets remain from refreshControl before and it leaves a white space on top of tableView and if I do not replace/hide refreshControl, it will be visible at this point.
Any suggestions?
Image: Transition between screens, refreshControl does not hide on viewDidDisappear
Try this one :-
refreshControl.tintColor = .clear
Initialize the refresh control:
lazy var refreshControl: UIRefreshControl = {
let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action:
#selector(ViewController.handleRefresh(_:)),
for: UIControlEvents.valueChanged)
refreshControl.tintColor = UIColor.red
return refreshControl
}()
Handle the refresh and end the refreshing:
func handleRefresh(_ refreshControl: UIRefreshControl) {
self.tableView.reloadData()
refreshControl.endRefreshing()
}
Add the refresh control:
self.tableView.addSubview(self.refreshControl)
When you present the new screen just use .endRefreshing() on your refreshControl.
I have contacted a friend that gave a really nice answer. This was the code that helped me smoothly remove refreshControl in case it was stuck in frozen state on screen:
func forceHideRefreshControl(tableView: UITableView) {
if tableView.contentOffset.y < 0 { // Move tableView to top
tableView.setContentOffset(CGPoint.zero, animated: true)
}
}
Though if view controller hasn't finished loading, it won't have refreshControl visible. For that you'd need to call beginRefreshing() on it again, but I would do it with delay to avoid any animation problems. In any case, I think this was the best solution that actually removed the white spacing on top. I do not know why endRefreshing() did not work, but at least I found another way. Hope this helps anyone! :)
NOTE: However, this solution is tested on stuck/frozen refreshControl only. I do not know what effect it will have if you do not have this problem, but still use this solution for hiding refreshControl.
I have attached headerView to UITableView. And I also want to use pull to refresh with tableview.
I have attached headerview to tableview with this code:
tblView.tableHeaderView = headerView
and used redresh controll as:
var refreshControl: UIRefreshControl!
refreshControl = UIRefreshControl()
refreshControl.attributedTitle = NSAttributedString(string: "Pull to refresh")
refreshControl.addTarget(self, action: #selector(self.refresh(_:)), forControlEvents: UIControlEvents.ValueChanged)
let tableController = UITableViewController()
self.addChildViewController(tableController)
tableController.tableView = self.tblView
tableController.refreshControl = self.refreshControl
Now issue is when I pull down tableview refreshcontrol showing but my header view position also changing with bounce effect. I don't want to change header position when I pulled down I want to display refreshcontrol under header view.
my header view and refreshcontrol is shown in screenshots. I want header view's position static joined with navigation bar but when user scroll up headerview will also have to scroll.
1)adding header view inside uiviewcontroller not to headerview for tableview,
2)you can change the headerframe accord scrollView of the tableView contentoffset,It is a little complex
3) github.com/CoderJackyHuang/StickyUpDownDemo this demo you can learn to solve your problem
Hello I am developing app which has UI like below images..
I am not able to understand how to create bottom swipe up view.
I have tried swipe up gesture on bottom view to open it.
But I want to open bottom view with finger (means slow upward drag of view should reveal bottom view slowly)
I am using auto layout and storyboard. How do I achieve this ?
I have searched a lot and I got this https://github.com/crocodella/PullableView but I am not able to add this view with storyboard and auto layout.
I Just want say before solution is that this is not gonna be drag like effect for that you need to use gesture...but It gives you similar effect if you strongly need it with button click.. I think its not what you want but this give you an option if you want
For drag bottom view to top,you shold use gesture and this may help you
Drag Down UIView in iOS 5
or this
http://www.jondev.net/articles/Dragging_View_with_Finger_(iPhone)
You got the similar effect using constant property of constraints..like Give the height constraint to bottom view and use constant property on click event to swipe up and down.
Still confused!!! Here is the solution
UI setup
Constraints Setup
After that You just need to make some outlets and click event of button...
make an outlet of height constraint of bottom view
make an outlet of button to change its title to up/down
make and click event of button
After this procedure you need to code on button action, So here is that code
class ViewController: UIViewController {
// Button outlet
#IBOutlet weak var btnUp: UIButton!
// Height Constraint outlet
#IBOutlet weak var constHeightBottomView: NSLayoutConstraint!
// Boolean property to handle click
var clicked = true
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func btnUpClicked(sender: UIButton) {
if clicked{
self.clicked = !clicked
UIView.animateWithDuration(0.2, animations: {
self.btnUp.setTitle("Down", forState: .Normal)
self.constHeightBottomView.constant = 200
self.view.layoutIfNeeded()
})
}
else{
self.clicked = true
UIView.animateWithDuration(0.2, animations: {
self.btnUp.setTitle("Up", forState: .Normal)
self.constHeightBottomView.constant = 0
self.view.layoutIfNeeded()
})
}
}
}
and the output of this work would be
How can you change the appearance of the UIRefreshControl to the "raindrop" style?
I looked up the docs and it doesn't seem to have any appearance related options, although it inherits UIView/UIControl.
Also it's not centered in the tableview. I tried to align it by assigning a frame with x=0, but that didn't change it to left align.
Here is what it looks like
And this is my code:
// in class description
var refreshControl: UIRefreshControl!
// in viewDidLoad()
refreshControl = UIRefreshControl()
//refreshControl.frame(CGRectMake(0, 0, 100, 100))
refreshControl.attributedTitle = NSAttributedString(string: "Pull to refresh")
refreshControl.addTarget(self, action: "refresh:", forControlEvents: UIControlEvents.ValueChanged)
tableView.addSubView(refreshControl)
func refresh(sender: AnyObject){
println("refreshing")
refreshControl.endRefreshing()
}
You cannot change it to the "raindrop" style. This was appearance of refresh control when Apple introduced it in UIKit (back in iOS 6) but then they switched to the current one. In fact there is almost no customization you can do with the built-in UIRefreshControl - just some basic text styling and color.
If you need more flexible control you either need to lookup 3rd party refresh controls or write something yourself.