Czy Mogę używać UIRefreshControl w UIScrollView?
Mam około 5 UIScrollView
' s już w mojej aplikacji, które wszystkie ładują Wiele .xib
plików. Teraz chcemy użyć UIRefreshControl
. Są one zbudowane do użycia z UITableViewControllers (zgodnie z odniesieniem do klasy UIRefreshControl). Nie chcę ponownie robić tego, jak działa wszystkie 5 UIScrollView
. Próbowałem już używać UIRefreshControl
w moich UIScrollView
i działa zgodnie z oczekiwaniami, z wyjątkiem kilku rzeczy.
Zaraz po tym, jak odświeżany obraz zamienia się w loader,
UIScrollView
skacze w dół o około 10 pikseli, co tylko nie zdarza się, gdy jestem bardzo ostrożny, aby przeciągnąćUIScrollview
w dół bardzo powoli.Kiedy przewijam w dół i uruchamiam przeładowanie, a następnie puszczam
UIScrollView
,UIScrollView
zostaje tam, gdzie go puszczam. Po zakończeniu przeładowania,UIScrollView
wskakuje na górę bez animacji.
Oto Mój kod:
-(void)viewDidLoad
{
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:@selector(handleRefresh:) forControlEvents:UIControlEventValueChanged];
[myScrollView addSubview:refreshControl];
}
-(void)handleRefresh:(UIRefreshControl *)refresh {
// Reload my data
[refresh endRefreshing];
}
Czy Jest jakiś sposób na zaoszczędzenie czasu i użycie UIRefreshControl
w UIScrollView
?
Dziękuję!!!
8 answers
Mam UIRefreshControl
do pracy z UIScrollView
:
- (void)viewDidLoad
{
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)];
scrollView.userInteractionEnabled = TRUE;
scrollView.scrollEnabled = TRUE;
scrollView.backgroundColor = [UIColor whiteColor];
scrollView.contentSize = CGSizeMake(500, 1000);
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:@selector(testRefresh:) forControlEvents:UIControlEventValueChanged];
[scrollView addSubview:refreshControl];
[self.view addSubview:scrollView];
}
- (void)testRefresh:(UIRefreshControl *)refreshControl
{
refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:@"Refreshing data..."];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[NSThread sleepForTimeInterval:3];//for 3 seconds, prevent scrollview from bouncing back down (which would cover up the refresh view immediately and stop the user from even seeing the refresh text / animation)
dispatch_async(dispatch_get_main_queue(), ^{
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"MMM d, h:mm a"];
NSString *lastUpdate = [NSString stringWithFormat:@"Last updated on %@", [formatter stringFromDate:[NSDate date]]];
refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:lastUpdate];
[refreshControl endRefreshing];
NSLog(@"refresh end");
});
});
}
Należy wykonać aktualizację danych w oddzielnym wątku lub zablokuje główny wątek(którego UI używa do aktualizacji interfejsu). Podczas gdy główny wątek jest zajęty aktualizowaniem danych, interfejs użytkownika jest również zablokowany lub zamrożony i nigdy nie widzisz płynnych animacji ani spinnera.
EDIT: ok, robię to samo co OP i dodałem do niego trochę tekstu (np. "Pull to Refresh") i musi wrócić do głównego wątku, aby to zaktualizować tekst.
Zaktualizowana odpowiedź.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-03 22:48:20
Dodając do powyższych odpowiedzi, w niektórych sytuacjach nie można ustawić contentSize (może używając auto layout?) lub wysokość contentSize jest mniejsza lub równa wysokości UIScrollView. W takich przypadkach UIRefreshControl nie będzie działać, ponieważ UIScrollView nie odbije się.
Aby naprawić ten zestaw Właściwość alwaysBounceVertical do TRUE .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-04 16:00:58
Jeśli i kiedy masz szczęście wspierać iOS 10+, możesz teraz po prostu ustawić refreshControl
z UIScrollView
. Działa to w ten sam sposób co poprzednio istniejące refreshControl
na UITableView
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-28 01:05:18
Oto Jak to zrobić w C # / Monotouch. Nie mogę znaleźć żadnych próbek do C# gdziekolwiek, więc tutaj jest.. Dzięki Log139!
public override void ViewDidLoad ()
{
//Create a scrollview object
UIScrollView MainScrollView = new UIScrollView(new RectangleF (0, 0, 500, 600));
//set the content size bigger so that it will bounce
MainScrollView.ContentSize = new SizeF(500,650);
// initialise and set the refresh class variable
refresh = new UIRefreshControl();
refresh.AddTarget(RefreshEventHandler,UIControlEvent.ValueChanged);
MainScrollView.AddSubview (refresh);
}
private void RefreshEventHandler (object obj, EventArgs args)
{
System.Threading.ThreadPool.QueueUserWorkItem ((callback) => {
InvokeOnMainThread (delegate() {
System.Threading.Thread.Sleep (3000);
refresh.EndRefreshing ();
});
});
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-18 11:01:09
W kwestii skoków, odpowiedź Tima Normana rozwiązuje to.
Oto wersja swift, jeśli używasz swift2:
import UIKit
class NoJumpRefreshScrollView: UIScrollView {
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func drawRect(rect: CGRect) {
// Drawing code
}
*/
override var contentInset:UIEdgeInsets {
willSet {
if self.tracking {
let diff = newValue.top - self.contentInset.top;
var translation = self.panGestureRecognizer.translationInView(self)
translation.y -= diff * 3.0 / 2.0
self.panGestureRecognizer.setTranslation(translation, inView: self)
}
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:39
Jak to zrobić w Swift 3:
override func viewDidLoad() {
super.viewDidLoad()
let scroll = UIScrollView()
scroll.isScrollEnabled = true
view.addSubview(scroll)
let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(pullToRefresh(_:)), for: .valueChanged)
scroll.addSubview(refreshControl)
}
func pullToRefresh(_ refreshControl: UIRefreshControl) {
// Update your conntent here
refreshControl.endRefreshing()
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-31 21:01:18
Sprawiłem, że UIRefreshControl
działa prawidłowo wewnątrz UIScrollView
. Odziedziczyłem UIScrollView
, zablokowałem zmianę contentInset i nadpisałem contentOffset setter:
class ScrollViewForRefreshControl : UIScrollView {
override var contentOffset : CGPoint {
get {return super.contentOffset }
set {
if newValue.y < -_contentInset.top || _contentInset.top == 0 {
super.contentOffset = newValue
}
}
}
private var _contentInset = UIEdgeInsetsZero
override var contentInset : UIEdgeInsets {
get { return _contentInset}
set {
_contentInset = newValue
if newValue.top == 0 && contentOffset.y < 0 {
self.setContentOffset(CGPointZero, animated: true)
}
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-18 05:23:35
Możesz po prostu utworzyć instancję kontrolki Odśwież i dodać ją u góry widoku przewijania. następnie w metodzie delegate dostosowujesz jego zachowanie do swoich wymagań.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-05 18:59:46