wangmchn / WMPageController

An easy solution to page controllers like NetEase News
MIT License
2.92k stars 627 forks source link

ViewFrameDemo的问题 #204

Open WangYiOS opened 7 years ago

WangYiOS commented 7 years ago

今天做订餐的界面,类似美团的外卖界面,我当时第一时间就想到 大神 你的这个《ViewFrameDemo》,打开开始做界面,但是做到最后发现,底部的tableView是覆盖了上面的空白,而不是像美团的外卖界面那样是推上去的,很伤心,希望大神有时间了,完善下ViewFrameDemo这个推上去的功能吧 img_6091

img_6092

anthann commented 7 years ago

在WMHomeViewController.m的setViewTop:方法最后添加: CGRect tableViewFrame = self.tableView.frame; tableViewFrame.origin.y = _viewTop - 150.0; self.tableView.frame = tableViewFrame; demo中首页上面的tableView就可以被推上去了。

其实这个demo的主要问题还不是这个。而是子tableView的滚动不跟手,而是会比手指移动快一些,原因是tableView和其父view同时发生了位移(也是setViewTop:最后一句话导致的)。解决办法可以参考wwdc2013的这个session,比较tricky

WangYiOS commented 7 years ago

潸然泪下

qingyigeli commented 7 years ago

@anthann 当tableview滚动时,viewTop 介于指定最大值和最小值中间时,出现闪动,请问怎么解决的

wangmchn commented 7 years ago

这个demo我到时候试着用panGesture重写下吧,监听tableview的contentoffset这个方法不是很科学

发自我的 iPhone

在 2016年11月21日,19:07,Song Zhou notifications@github.com 写道:

@anthann 当tableview滚动时,viewTop 介于指定最大值和最小值中间时,出现闪动,请问怎么解决的

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.

WangYiOS commented 7 years ago

好的,期待从写

qingyigeli commented 7 years ago

@anthann @wangmchn 关于viewTop 介于指定最大值和最小值中间时,出现闪动和介意速率的暂时解决方法:从始至终我们不改变self.viewFrame的值,在-setViewTop:方法里对self.menuView的y值进行改变,CGRect rect = self.menuView.frame; rect.origin.y = _viewTop; self.menuView.frame = rect; 而子tableView的contentInset下移kWMHeaderViewHeight,在-scrollViewDidScroll:方法里hvc.viewTop的值多减一个kWMHeaderViewHeight,子tableView的-viewDidAppear:方法里加一行[self scrollViewDidScroll:self.tableView]; 。而menu上半部分照常加view,想一起推,-setViewTop:方法view.origin.y减去子tableView实际移的偏移量(减去contentInset的值)。这样效果还不错。

qingyigeli commented 7 years ago

漏了一处,去掉-pageController:willEnterViewController:withInfo:的内容

qingyigeli commented 7 years ago

压缩包里有两个实现文件

未命名文件夹.zip

yehuaqiang commented 7 years ago

大神什么时候完善下ViewFrameDemo这个推上去的功能

wangmchn commented 7 years ago

试试这个: https://github.com/wangmchn/WMPageController/commit/1dd637a794d7155421def2a504c3d8dfa47eb75c

guang-sun commented 7 years ago

大神 ,我是今天刚更新的demo, viewFrameDemo 上滑和下滑 tableview 都会跟着手势移动, 能否设置为 上滑时: 在headview 滑到顶部时 tableview 才开始滑动, 下滑时: 在headview 完全出现后 tableview 才开始滑动

wangmchn commented 7 years ago

@guang-sun 可以在PanGesture开始,但是HeadView还在屏幕内但不是全部展示的时候设置tableView.scrollEnable = NO, 这个具体时机可以自己把握一下

guang-sun commented 7 years ago

?? 大神 不太明白 怎么在 homeview 获取当前选中的 子WMTableViewController中tableview的 contentInset

wangmchn commented 7 years ago

一个是self.currentViewController就是WMTabeViewController 或者更直接的,可以通过 UIGestureRecognizerDelegate 来让TableView的手势不响应

guang-sun commented 7 years ago

大神 , 通过设置 tableView.scrollEnable 实现 有个问题 在滑到顶部 继续上滑是 tableview 还是不可以滑动 ,当你再次滑动是 才可以

CoderDoraemon commented 7 years ago
//
//  WMHomeViewController.m
//  Demo
//
//  Created by Mark on 16/7/25.
//  Copyright © 2016年 Wecan Studio. All rights reserved.
//

#import "WMHomeViewController.h"
#import "WMTableViewController.h"
#import "WMPanGestureRecognizer.h"

@interface WMHomeViewController () <UIGestureRecognizerDelegate>
@property (nonatomic, strong) NSArray *musicCategories;
@property (nonatomic, strong) WMPanGestureRecognizer *panGesture;
@property (nonatomic, assign) CGPoint lastPoint;

/** headerImageView头部视图 */
@property (nonatomic, strong) UIImageView *headerImageView; 

@end

@implementation WMHomeViewController

- (NSArray *)musicCategories {
    if (!_musicCategories) {
        _musicCategories = @[@"单曲", @"详情", @"歌词"];
    }
    return _musicCategories;
}

- (instancetype)init {
    if (self = [super init]) {
        self.titleSizeNormal = 15;
        self.titleSizeSelected = 15;
        self.menuViewStyle = WMMenuViewStyleLine;
        self.menuItemWidth = [UIScreen mainScreen].bounds.size.width / self.musicCategories.count;
        self.menuHeight = 50;
        self.viewTop = kNavigationBarHeight + kWMHeaderViewHeight;
        self.titleColorSelected = [UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1.0];
        self.titleColorNormal = [UIColor colorWithRed:0.4 green:0.8 blue:0.1 alpha:1.0];
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.title = @"专辑";

    self.panGesture = [[WMPanGestureRecognizer alloc] initWithTarget:self action:@selector(panOnView:)];
    [self.view addGestureRecognizer:self.panGesture];

    // 添加头部视图到View上 <最下层>
    [self.view insertSubview:self.headerImageView atIndex:0];
}

- (void)panOnView:(WMPanGestureRecognizer *)recognizer {

    WMTableViewController *vc = (WMTableViewController *)self.currentViewController;

    if (self.menuView.frame.origin.y == kNavigationBarHeight) {   // 当menuView滚动到最顶部
        if (vc.tableView.contentOffset.y > 0) {  // 当前视图的子控制器偏移量大于0,不滚动了
            return;
        }
    }

    CGPoint currentPoint = [recognizer locationInView:self.view];

    if (recognizer.state == UIGestureRecognizerStateBegan) {
        self.lastPoint = currentPoint;
    } else if (recognizer.state == UIGestureRecognizerStateEnded) {

        CGPoint velocity = [recognizer velocityInView:self.view];
        CGFloat targetPoint = velocity.y < 0 ? kNavigationBarHeight : kNavigationBarHeight + kWMHeaderViewHeight;
        NSTimeInterval duration = fabs((targetPoint - self.viewTop) / velocity.y);

        if (fabs(velocity.y) * 1.0 > fabs(targetPoint - self.viewTop)) {

            [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
                self.viewTop = targetPoint;
            } completion:nil];

            return;
        }

    }
    CGFloat yChange = currentPoint.y - self.lastPoint.y;
    self.viewTop += yChange;
    self.lastPoint = currentPoint;
}

// MARK: ChangeViewFrame (Animatable)
- (void)setViewTop:(CGFloat)viewTop {

    _viewTop = viewTop;

    if (_viewTop <= kNavigationBarHeight) {
        _viewTop = kNavigationBarHeight;
    }

    if (_viewTop > kWMHeaderViewHeight + kNavigationBarHeight) {
        _viewTop = kWMHeaderViewHeight + kNavigationBarHeight;
    }

    self.viewFrame = CGRectMake(0, _viewTop, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - _viewTop);

    WMTableViewController *vc = (WMTableViewController *)self.currentViewController;
    if (self.menuView.frame.origin.y != kNavigationBarHeight) {
        vc.tableView.contentOffset = CGPointZero;
    }

    // 更改头部视图的frame
    [self setupHeaderImageViewFrame:viewTop];
}

- (void)setupHeaderImageViewFrame:(CGFloat)offSetY {

    CGRect headerImageViewFrame = self.headerImageView.frame;
    headerImageViewFrame.origin.y = self.viewTop - kWMHeaderViewHeight;

    self.headerImageView.frame = headerImageViewFrame;
}

#pragma mark - Datasource & Delegate
- (NSInteger)numbersOfChildControllersInPageController:(WMPageController *)pageController {
    return self.musicCategories.count;
}

- (UIViewController *)pageController:(WMPageController *)pageController viewControllerAtIndex:(NSInteger)index {
    WMTableViewController *vc = [[WMTableViewController alloc] init];
    return vc;
}

- (NSString *)pageController:(WMPageController *)pageController titleAtIndex:(NSInteger)index {
    return self.musicCategories[index];
}

#pragma mark - lazy
- (UIImageView *)headerImageView {
    if (_headerImageView == nil) {
        _headerImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, kNavigationBarHeight, [UIScreen mainScreen].bounds.size.width, kWMHeaderViewHeight)];
        _headerImageView.image = [UIImage imageNamed:@"Snip20170428_1"];
    }
    return _headerImageView;
}

@end
mysekai7 commented 7 years ago

当子控制器 牵头嵌套的是个webview,当拖动时会出现卡顿,这个有什么好的解决办法没

wangmchn commented 7 years ago

@chaobj001 这个我也没有什么好的解决方案,试试设置viewFrame来移动的时候不改变viewFrame的宽高只改变origin.y看,是否有提升?

Share-Yida commented 6 years ago

这个问题的话 现在有什么好的解决方案吗

DamonLiii commented 6 years ago

真心想寻求一个子tableView下滑到顶的时候,manuView才会下滑的方案.现在不管我滑到哪里.只要一往下滑.manuView就跟着下滑了