Вопрос по uiscrollview, ios, objective-c, iphone, ipad – сделать UIView в UIScrollView придерживаться наверх при прокрутке вверх

17

Таким образом, в UITableView, когда у вас есть разделы, вид сечения придерживается вершины, пока следующий раздел не перекрывает его, а затем он заменяет его сверху. Я хочу получить аналогичный эффект, когда в основном у меня есть UIView в моем UIScrollView, представляющий разделы UIView, и когда он достигает вершины ... Я хочу, чтобы он оставался там и не увлекался. Как мне это сделать? Я думаю, что это нужно сделать либо в layoutSubviews, либо в scrollViewDidScroll и выполнить манипуляции с UIVIew.

Ваш Ответ

4   ответа
21

Чтобы создать UIView в UIScrollView, придерживайтесь вершины при прокрутке вверх:

- (void)createHeaderView:(UIView*)headerView {
    _headerView = [headerView retain];
    _headerViewInitialY = _headerView.frame.origin.y;
    [_scrollView addSubview:_headerView];
    _scrollView.delegate = self;
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    CGRect headerFrame = _headerView.frame;
    headerFrame.origin.y = MAX(_headerViewInitialY, scrollView.contentOffset.y);
    _headerView.frame = headerFrame;
}
Действительно хорошо выглядит
работает отлично ... спасибо
Я попробовал это, и это отлично работает, но мой взгляд становится прозрачным, и я попробовал все, но не удалось, поэтому, пожалуйста, не могли бы вы помочь мне объяснить, почему это происходит. Это только становится прозрачным в течение некоторого времени, пока это не придерживается вершины
Убедитесь, что представление, для которого вы собираетесь перехватывать прокрутки, имеет установленный делегат, и этот делегат находится там, где будет жить scrollViewDidScroll. Если вы позволите вашему контроллеру реализовать протокол & lt; UIScrollViewDelegate & gt;, вы можете назначить делегата как "apos; self" apos; в контроллере вродеthis
2

Решение Evya работает очень хорошо, однако если вы используете Auto Layout, вы должны сделать что-то вроде этого (синтаксис Auto Layout написан наКирпичная кладка, Но ты получил идею.):

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {

    //Make the header view sticky to the top.
    [self.headerView mas_remakeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.scrollView.mas_top).with.offset(scrollView.contentOffset.y);
        make.left.equalTo(self.scrollView.mas_left);
        make.right.equalTo(self.scrollView.mas_right);

        make.height.equalTo(@(headerViewHeight));
    }];

    [self.scrollView bringSubviewToFront:self.headerView];
}
mas_updateConstraints
К сожалению, это заставляет вас воссоздавать ограничения макета с каждым кадром движения прокрутки. Вместо этого вам нужно иметь контейнер, содержащийUIScrollView и сделать верх заголовка равнымcontainer's top, а не верхняя часть прокрутки и смещение контента. Делая это таким образом, вы можете установить ограничения один раз.
@AnthonyMills спасибо за комментарий! Помогло мне многое понять.
9

Быстрое решение, основанное на ответе EVYA:

var navigationBarOriginalOffset : CGFloat?

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    navigationBarOriginalOffset = navigationBar.frame.origin.y
}

func scrollViewDidScroll(scrollView: UIScrollView) {
    navigationBar.frame.origin.y = max(navigationBarOriginalOffset!, scrollView.contentOffset.y)
}
2

Если я правильно помню,2010 WWDC ScrollView Презентация точно описывает, как сохранить представление в фиксированном положении, в то время как другие элементы прокручивают его. Посмотрите видео, и у вас должен быть четкий подход к реализации.

Он по существу обновляет кадры на основе обратных вызовов scrollViewDidScroll (хотя память немного мрачнее в более тонких точках).

Больше ничего не зная о своем дизайне, трудно сказать точно, как вы должны "знать" который на вершине. Я бы подумал, что у контроллера представления есть смысл, который является «текущим» раздел, основанный на информации раздела, поступающей для вашей модели, или какой-либо другой основе. Попытка определить, какой раздел / заголовок должен быть сверху в области видимости (т. Е. Вы могли бы сделать это путем сравнения yOffsets, или rectContainsRect или подобного), не кажется идеальной стратегией imo.
Чтобы определить, какое представление находится сверху, вы можете запросить у суперпредставления массив его подпредставлений, например, NSArray * subviews = [superview subviews]. Затем попросите в вашем массиве индексы подпредставлений, которые вы хотите сравнить, например, NSUInteger oneIndex = [subviews indexOfObject: viewOne], twoIndex = [subviews indexOfObject: viewTwo]. После того как вы пройдете по указателям для обоих подпредставлений, просто оцените, какое из них больше, чтобы определить, что находится над другим.
хм .. в основном вы должны проверить, находится ли этот секционированный UIView сверху, и затем сохранить его там правильно? Моя проблема в том, как определить, находится ли этот секционированный UIView на & quot; top & quot; xonegirlz
когда я говорю сверху, не имея в виду один поверх друг друга .. но я имею в виду, который находится на contentOffSet.y xonegirlz

Похожие вопросы