Uiscrollview poziome stronicowanie jak Mobilne Karty Safari
Mobile Safari Umożliwia przełączanie stron poprzez wprowadzenie pewnego rodzaju poziomego widoku stronicowania uiscrollview z kontrolką strony u dołu.
Próbuję odtworzyć to zachowanie, w którym przewijany poziomo UIScrollView pokazuje część zawartości następnego widoku.
Przykład Apple: PageControl pokazuje, jak używać widoku uiscrollview do stronicowania poziomego, ale wszystkie widoki zajmują całą szerokość ekranu.
Jak uzyskać UIScrollView, aby pokazać niektóre zawartość następnego widoku jak w mobilnym Safari?
9 answers
A {[1] } z włączonym stronicowaniem zatrzyma się przy wielokrotnościach szerokości ramki (lub wysokości). Pierwszym krokiem jest ustalenie, jak szeroka ma być Twoja strona. Niech będzie to szerokość UIScrollView
. Następnie Ustaw rozmiary subview, niezależnie od tego, jakie są duże, i ustaw ich centra na podstawie wielokrotności szerokości UIScrollView
.
Następnie, ponieważ chcesz zobaczyć inne strony, oczywiście ustaw clipsToBounds
na NO
, jak stwierdził mhjoy. Sztuczka polega teraz na tym, aby przewijać go, gdy użytkownik zacznie przeciągnięcie poza zakres ramki UIScrollView
. Moje rozwiązanie (kiedy musiałem to zrobić bardzo niedawno) było następujące: {]}
Utwórz podklasę UIView
(tj. ClipView
), która będzie zawierać UIScrollView
i jest to podwidywalność. Zasadniczo powinien mieć ramę tego, co można by założyć, że UIScrollView
będzie miał w normalnych okolicznościach. Umieść UIScrollView
w środku ClipView
. Upewnij się, że ClipView
' S clipsToBounds
jest ustawiona na YES
, jeśli jej szerokość jest mniejsza niż szerokość widoku nadrzędnego. Ponadto ClipView
potrzebuje odniesienie do UIScrollView
.
Ostatnim krokiem jest obejście - (UIView *)hitTest:withEvent:
wewnątrz ClipView
.
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
return [self pointInside:point withEvent:event] ? scrollView : nil;
}
To zasadniczo rozszerza obszar dotykowy UIScrollView
do ramki widoku rodzica, dokładnie tego, czego potrzebujesz.
Inną opcją byłoby podklasowanie UIScrollView
i nadpisanie jej metody - (BOOL)pointInside:(CGPoint) point withEvent:(UIEvent *) event
, jednak nadal będziesz potrzebował widoku kontenera do przycinania i może być trudno określić, kiedy zwrócić YES
tylko na podstawie ramki UIScrollView
.
Uwaga: powinieneś również spojrzeć na Juri Pakaste hitTest: withEvent: modification jeśli masz problemy z interakcją z subview.
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:16:51
Powyższe rozwiązanie zadziałało dla mnie, ale musiałem wykonać inną implementację -[UIView hitTest:withEvent:]
. Wersja Ed Marty ' ego nie dostała interakcji z użytkownikiem pracującym z pionowymi przewijaniami, które mam wewnątrz poziomego.
Następująca wersja zadziałała dla mnie:
-(UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
{
UIView* child = nil;
if ((child = [super hitTest:point withEvent:event]) == self)
return self.scrollView;
return child;
}
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
2009-09-03 12:25:46
Ustaw rozmiar ramki scrollView jako rozmiar stron:
[self.view addSubview:scrollView];
[self.view addGestureRecognizer:mainScrollView.panGestureRecognizer];
Teraz możesz przesuwać self.view
, a zawartość w widoku przewijania zostanie przewinięta.
Użyj również scrollView.clipsToBounds = NO;
, aby zapobiec przycinaniu zawartości.
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-01-27 22:32:44
Sam zacząłem korzystać z niestandardowego UIScrollView, ponieważ była to najszybsza i prostsza metoda, jaką mi się wydawało. Jednak nie widziałem żadnego dokładnego kodu, więc pomyślałem, że podzielę się. Moje potrzeby były dla UIScrollView, który miał małą zawartość i dlatego sam UIScrollView był mały, aby osiągnąć wpływ stronicowania. Jak pisze post, nie możesz przesuwać palcem. Ale teraz możesz.
Utwórz klasę CustomScrollView i podklasę UIScrollView. Następnie wszystko, co musisz zrobić, to dodać to do.na plik:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
return (point.y >= 0 && point.y <= self.frame.size.height);
}
To pozwala na przewijanie z boku na bok (poziomo). Dostosuj odpowiednio granice, aby ustawić obszar dotykowy przesuwania / przewijania. Smacznego!
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-05-15 16:29:06
Wykonałem kolejną implementację, która może automatycznie zwracać widok przewijania. Więc nie musi mieć IBOutlet, który ograniczy ponowne użycie w projekcie.
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
if ([self pointInside:point withEvent:event]) {
for (id view in [self subviews]) {
if ([view isKindOfClass:[UIScrollView class]]) {
return view;
}
}
}
return nil;
}
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
2012-08-17 10:28:59
Mam kolejną potencjalnie przydatną modyfikację dla implementacji clipview hitTest. Nie podobało mi się, że trzeba podać odniesienie UIScrollView do ClipView. Moja implementacja poniżej pozwala na ponowne użycie klasy ClipView, aby rozszerzyć obszar hit-test czegokolwiek, i nie trzeba dostarczać mu odniesienia.
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
if (([self pointInside:point withEvent:event]) && (self.subviews.count >= 1))
{
// An extended-hit view should only have one sub-view, or make sure the
// first subview is the one you want to expand the hit test for.
return [self.subviews objectAtIndex:0];
}
return nil;
}
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
2012-03-09 07:52:37
Zaimplementowałem powyższą sugestię, ale UICollectionView
używałem czegokolwiek poza kadrem, aby być poza ekranem. Spowodowało to, że pobliskie komórki renderowały poza granicami tylko wtedy, gdy użytkownik przewijał w ich kierunku, co nie było idealne.
Skończyło się na emulowaniu zachowania widoku przewijania przez dodanie poniższej metody do delegata (lub UICollectionViewLayout
).
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
if (velocity.x > 0) {
proposedContentOffset.x = ceilf(self.collectionView.contentOffset.x / pageSize) * pageSize;
}
else {
proposedContentOffset.x = floorf(self.collectionView.contentOffset.x / pageSize) * pageSize;
}
return proposedContentOffset;
}
Pozwala to całkowicie uniknąć delegowania akcji machnięcia, co było również bonusem. UIScrollViewDelegate
ma podobna metoda o nazwie scrollViewWillEndDragging:withVelocity:targetContentOffset:
, która może być użyta do stronicowania UITableViews i uiscrollviews.
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
2012-10-30 00:17:39
Włączanie zdarzeń stukania w dziecięcych widokach widoku przewijania, wspierając technikę tego pytania. Używa odniesienia do widoku przewijania (self.scrollView) dla czytelności.
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView *hitView = nil;
NSArray *childViews = [self.scrollView subviews];
for (NSUInteger i = 0; i < childViews.count; i++) {
CGRect childFrame = [[childViews objectAtIndex:i] frame];
CGRect scrollFrame = self.scrollView.frame;
CGPoint contentOffset = self.scrollView.contentOffset;
if (childFrame.origin.x + scrollFrame.origin.x < point.x + contentOffset.x &&
point.x + contentOffset.x < childFrame.origin.x + scrollFrame.origin.x + childFrame.size.width &&
childFrame.origin.y + scrollFrame.origin.y < point.y + contentOffset.y &&
point.y + contentOffset.y < childFrame.origin.y + scrollFrame.origin.y + childFrame.size.height
){
hitView = [childViews objectAtIndex:i];
return hitView;
}
}
hitView = [super hitTest:point withEvent:event];
if (hitView == self)
return self.scrollView;
return hitView;
}
Dodaj to do widoku dziecka, aby uchwycić Zdarzenie dotykowe:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
(jest to wariant rozwiązania user1856273. Oczyszczone pod kątem czytelności i włączone poprawki błędów Bartserka. Myślałem o edytowaniu odpowiedzi user1856273, ale to była zbyt duża zmiana, aby dokonać.)
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-07-25 17:49:49
Moja wersja Naciśnięcie przycisku leżącego na przewijaku-work =)
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView* child = nil;
for (int i=0; i<[[[[self subviews] objectAtIndex:0] subviews] count];i++) {
CGRect myframe =[[[[[self subviews] objectAtIndex:0] subviews]objectAtIndex:i] frame];
CGRect myframeS =[[[self subviews] objectAtIndex:0] frame];
CGPoint myscroll =[[[self subviews] objectAtIndex:0] contentOffset];
if (myframe.origin.x < point.x && point.x < myframe.origin.x+myframe.size.width &&
myframe.origin.y+myframeS.origin.y < point.y+myscroll.y && point.y+myscroll.y < myframe.origin.y+myframeS.origin.y +myframe.size.height){
child = [[[[self subviews] objectAtIndex:0] subviews]objectAtIndex:i];
return child;
}
}
child = [super hitTest:point withEvent:event];
if (child == self)
return [[self subviews] objectAtIndex:0];
return child;
}
Ale tylko [[self subviews] objectAtIndex: 0] musi być zwój
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-03-15 16:57:07