iOS 7-Porady dotyczące układu

Mam następujący układ w moim kontrolerze widoku. Chcę mieć możliwość przewijania w pionie z nagłówkiem przewijającym się poza widokiem i kontrolką uisegmentedcontrol przyklejoną do góry widoku, poza tym Pozostałe przewijanie powinno być obsługiwane przez Widok kolekcji.

Jestem jednak nieco zdezorientowany co do tego, jakie jest najlepsze podejście do implementacji tego layoutu.

Układ

Wypróbowałem kilka implementacji o mieszanych wynikach:

  1. UIScrollView with UICollectionView jako podgląd podrzędny: UIScrollView jako widok nadrzędny z nagłówkiem, kontrolką segmentową i widokami kolekcji jako kontrolkami potomnymi. Problem z tym podejściem polega na tym, że zagnieżdżone przewijanie nie wydaje się działać poprawnie. Aby móc przewijać widok uiscrollview, tap musi znajdować się poza obszarem CollectionView, w przeciwnym razie tylko CollectionView przewija się, a sterowanie nagłówkiem i segmentem nie porusza się.

  2. Kontrola nagłówka i segmentacji w komórce nagłówka: I wypróbowałem inne podejście, używając pojedynczego widoku kolekcji. Dodałem nagłówek i sterowanie segmentowane jako podgląd pojedynczej komórki nagłówka widoku kolekcji. Gdy segmentowa wartość kontrolna została zmieniona, przełączam właściwość źródła danych widoku kolekcji, aby uzyskać 3 widoki wymagane dla widoku kolekcji. Wizualnie wszystko działa idealnie. Jedynym problemem jest tutaj stan Wyścigu podczas szybkiego przełączania między pierwszą, drugą i trzecią zakładką. Ładuję dane z serwisu WWW, jeśli usługa internetowa zajmuje czas i wciąż ładuje dane i szybko przełączam zakładki, a następnie natrafiam na błędy, w których dane zwracane są dla innego widoku kolekcji niż to, co jest obecnie wybrane, wiele problemów z synchronizacją.

  3. Update constant value for Autolayout Constraint: innym podejściem, które próbowałem, jest zmiana stałej wartości ograniczenia automatycznego układu zastosowanego do widoku "Header". Następnie dodałem gest do widoku kontrolera widoku, aby śledzić przewijanie, gdy użytkownik przewija się w pionie, dostosowuję stałą ograniczenia automatycznego układu, aby komórka "nagłówka" wyskakiwała z widoku. Znowu to nie wydaje się działać tak płynnie, ale przypuszczam, że mogę go dostosować, ale wydaje się to rodzaj hack.

Czy jest lepszy sposób na zaimplementowanie tego layoutu?

Author: 0m3r, 2015-06-09

6 answers

Myślę, że chcesz mieć taką samą funkcjonalność, jaką ma strona profilu Pinteresta. Aby zaimplementować taką funkcjonalność w łatwy sposób, musisz wykonać następujące czynności.

Krok 1 : Dodaj UIView jako tableHeaderView tych, którzy popisują się podczas przewijania w górę.

self.tableHeaderView = yourView

Krok 2 : dodaj {[2] } w widoku nagłówka sekcji.

 - (UITableViewHeaderFooterView *)headerViewForSection:(NSInteger)section{
  return your_segmentcontrolView;

}

Krok 3 : Dodaj UICollectionView do pierwszego wiersza pierwszej sekcji.

Wdrażając następujący sposób, możesz uzyskać swoje pragnienie funkcjonalność.

Mam nadzieję, że to ci pomoże.
 2
Author: Jatin Patel,
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
2015-06-16 10:49:54

# 2 wydaje się dobrym rozwiązaniem - gesty przewijania będą najbardziej zgodne z oczekiwaniami użytkowników, ponieważ wszystko to jeden widok przewijania. (Zgadzam się, że #3 brzmi jak hack.) Nagłówek można "sticky" z niektórych niestandardowych atrybutów układu.

Jedynym problemem jest stan rasy podczas szybkiego przełączania między pierwszą, drugą i trzecią zakładką.

Jest to częsty problem z ładowaniem asynchronicznym, gdy widoki są wyłączane (szczególnie podczas ładowania danych do pojedynczych komórek, które są ponownie używane podczas przewijania). Ważne jest, aby po otrzymaniu danych zawsze sprawdzać czy odbiorca nadal ich oczekuje; tzn. należy sprawdzić segmentową wartość kontrolną przed zmianą źródła danych. Można też:

  • używaj oddzielnych obiektów źródłowych danych dla różnych segmentów, każdy z nich zarządza własnym pobieraniem danych, aby nie mogły się pomieszać.
  • Anuluj zaległe żądania, jeśli możesz, podczas szybkiego przełączania kart, aby uniknąć niepotrzebnych żądań sieciowych.
  • pamięć podręczna danych, aby uniknąć ponownego pobierania za każdym razem, gdy przełączasz karty.
 9
Author: jtbandes,
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:24:17

Alternatywne podejście, które można rozważyć:

Użyj widoku UITableView, aby zawierać swój interfejs

  • Utwórz UITableView i ustaw nagłówek jako widok nagłówka UITableView.
  • użyj nagłówka sekcyjnego, aby zawrzeć element segmentedControl.
  • Umieść swój collectionView wewnątrz pojedynczego UITableViewCell. Alternatywnie możesz użyć widoku stopki UITableView do przechowywania widoku gridView.

Używając nagłówka sekcji, powinno to umożliwić nagłówek do przewijania poza widok, ale wtedy nagłówek sekcji będzie trzymać się poniżej paska nawigacyjnego lub u góry widoku treści, aż do pojawienia się innej sekcji (a w Twoim przypadku będziesz mieć tylko jedną sekcję.)

 2
Author: Aron C,
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
2015-06-17 21:21:23
  • Dodaj Widok nagłówka, Widok ciała (Widok segmentu i widok kolekcji) do widoku przewijania.
  • początkowo ustaw właściwość userInteractionEnabled NA " NO " dla widoku kolekcji.
  • śledź insekt widoku przewijania zawsze.
  • Jeśli współrzędna y przewijanego owada jest większa niż wysokość widoku nagłówka, ustaw właściwość userInteractionEnabled na "YES", aby następnie można było przewijać widok kolekcji.
  • Jeśli użytkownik przewija się poza widok przewijania i próbuje przynieść widok nagłówka w dół, czyli widok przewijania współrzędna y jest mniejsza niż wysokość widoku nagłówka, a następnie natychmiast zmień tryb iteracji użytkownika widoku kolekcji i pozwól użytkownikowi przewijać widok do góry.
 1
Author: Mithun R.,
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
2015-06-16 11:58:01

Zamiast implementować to ręcznie, możesz użyć biblioteki / cocoapod, aby skonfigurować to dla Ciebie. Ten wygląda całkiem nieźle: https://github.com/iosengineer/BMFloatingHeaderCollectionViewLayout

DODATKOWO, kod jest open-source, więc zawsze można modyfikować w razie potrzeby.

 1
Author: BevTheDev,
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
2015-06-19 14:25:51

Wszystko, co mogę powiedzieć, to to, że musisz podklasę UIView i uczynić z niej delegata UIGestureRecognizerDelegate i UICollectionViewDelegate, a następnie w swojej podklasie UIView, wykonaj następujące czynności, nie mogę już udzielać informacji na ten temat, ponieważ kod, chociaż należący do mnie, jest zastrzeżony do tego stopnia, że prawdopodobnie rozwściecza kilka organizacji, do których tego używałem, więc oto tajny sos: {]}

CGPoint contentOffset = [scrollView contentOffset];
CGFloat newHeight = [_headerView maxHeight] - contentOffset.y;
CGRect frame = [_headerView frame];

if (newHeight > [_headerView maxHeight]) {
    frame.origin.y = contentOffset.y;
    frame.size.height = [_headerView maxHeight];
    [_headerView setFrame:frame];
} else if (newHeight < [_headerView minHeight]) {

    frame.origin.y = contentOffset.y;
    frame.size.height = [_headerView minHeight];
    [_headerView setFrame:frame];
} else {
    frame.origin.y = contentOffset.y;
    frame.size.height = newHeight;
    [_headerView setFrame:frame];
}
if ([_delegate respondsToSelector:@selector(scrollViewDidScroll:)]) {
    return [_delegate scrollViewDidScroll:scrollView];
}

Musisz podklasować inny UIView, który jest zdefiniowany jako nagłówek dla tego custom UiCollectionView. Następnie należy zadeklarować niestandardowy widok nagłówka UIView wewnątrz niestandardowego subview delegata UIView/UICollectionView, a następnie ustawić nagłówek tego niestandardowego subview wewnątrz UICollctionViewdelegate. Następnie należy pobrać tę złożoną podklasę UIView/UIcollectionView do kontrolera UIViewController. Tak, a w layoutSubViews upewnij się, że wykonujesz obliczenia wysokości, które są przekazywane przez podklasę dwuwarstwową. Tak więc, będziesz mieć następujące pliki:

  1. UIVew to jest delegat UICollectionView i to, o czym wspomniałem wcześniej

  2. UIView to jest UISCrollViewDelegate i to jest widok nagłówka

  3. UIViewController, który ściąga podklasowany UIView w numerze 1

  4. Podklasa UIView liczby 1, która pobiera liczbę 2 i ustawia ją jako nagłówek

W części numer 4, Upewnij się, że zrobisz coś takiego:

- (CGFloat)maxHeight
{
    if (SCREEN_WIDTH == 414)
    {
        return 260;

    }else if (SCREEN_WIDTH == 375)
    {
        return 325;

    }else
    {
        return 290;
    }
}

- (CGFloat)minHeight
{
    if (SCREEN_WIDTH == 414)
    {

        return 90;
    }else if (SCREEN_WIDTH == 375)
    {
        return 325;
    }else
    {
        return 290;
    }
}

To wtedy minie przez podklasę UIView, która jest złożoną podklasą, jak już wyjaśniłem. Chodzi o to, aby uchwycić maksymalną jasność nagłówka w podklasie tego nagłówka UIView (numer 2 powyżej), a następnie przekazać to do głównej podklasy UIView, która przechwytuje te wartości w przewijaniu.

Ostatnia ciekawostka, upewnij się, że ustawiłeś layoutSubviews we wszystkich metodach przechwytywania zdarzeń przewijania. Na przykład w numerze 1 powyżej metoda layoutsubviews jest to:

- (void)layoutSubviews
{
    CGRect frame = [_headerView frame];
    frame.size.width = [self frame].size.width;
    [_headerView setFrame:frame];
    [super layoutSubviews];
}

To wszystko, co mogę ci dać, chciałbym móc publikować więcej, ale to powinno dać ci wyobrażenie o tym, jak to się robi w środowiskach produkcyjnych dla dużych aplikacji Czasu, które widzisz na wolności.

Jeszcze jedno. Kiedy zaczniesz podążać drogą intensywnych implementacji, takich jak ta, nie zdziw się, aby dowiedzieć się, że na przykład pojedynczy kontroler widoku w aplikacji, która działa z metodami, jak wyjaśniłem, będzie miał od 30 do 40 niestandardowych podklas, które są albo podklasy w swoich własnych lub złożonych podklas lub podklas moich własnych podklas lub moich własnych podklas. Mówię ci to, abyś miał pojęcie, ile kodu jest wymagane, aby to zrobić dobrze, nie po to, aby cię przestraszyć, ale aby dać Ci znać, że może to trochę potrwać, a nie kopać się w tyłek, jeśli zajmie to trochę czasu, aby zadziałać. Powodzenia!!
 -5
Author: Pretty Goodidea,
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
2015-06-14 19:06:00