GKAllRefreshViewController.m 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. //
  2. // GKAllRefreshViewController.m
  3. // ObjcExample
  4. //
  5. // Created by lcg on 2022/11/30.
  6. //
  7. #import "GKAllRefreshViewController.h"
  8. #import <MJRefresh/MJRefresh.h>
  9. #import "VoiceListViewController.h"
  10. /// bug 复现操作:
  11. /// 1. 首个 tab 列表上拉操作到吸顶状态后继续上拉一段距离
  12. /// 2. 切换到其他 tab 上拉到吸顶状态显示出刷新按钮
  13. /// 3. 点击刷新按钮,子列表刷新
  14. /// 4. 切换回首个 tab 列表,此时下拉会造成列表自动跳转到 offsetY = 0
  15. ///
  16. /// 原因:
  17. /// 第二步骤刷新时,会临时将 disableMainScrollInCeil = YES & allowListRefresh = YES 保证子列表可以展示 refreshHeader,
  18. /// 此时 listScrollViewDidScroll 会执行判断条件为 (offsetY <= 0) => (self.isDisableMainScrollInCeil) => (self.isAllowListRefresh && offsetY < 0 && self.isCeilPoint) else 的逻辑,self.isMainCanScroll = YES; 将允许 main 滚动
  19. /// 子列表刷新结束后,重置了 disableMainScrollInCeil = NO & allowListRefresh = NO,所以切换回首 tab 后, 下拉刷新会执行 mainScrollViewDidScroll() 的第 378 行代码,判断上步的 self.isMainCanScroll = YES 从而导致重置子列表的 offset = zero
  20. ///
  21. /// 解决办法:
  22. /// 按照 disableMainScrollInCeil 属性的定义,实际上当 disableMainScrollInCeil = YES & 子列表的 offsetY == 0 时,此时是临界状态,是不想主列表滚动的,所以应该将offset判断条件由 < 0 改为 <= 0。
  23. @interface GKAllRefreshViewController ()
  24. @property (nonatomic, strong) UIButton *listRefreshBtn;
  25. @end
  26. @implementation GKAllRefreshViewController
  27. - (void)viewWillLayoutSubviews
  28. {
  29. [super viewWillLayoutSubviews];
  30. CGFloat screenWidth = UIScreen.mainScreen.bounds.size.width;
  31. CGFloat screenHeight = UIScreen.mainScreen.bounds.size.height;
  32. self.listRefreshBtn.frame = CGRectMake(screenWidth - 44 - 15, screenHeight - 44 - 15, 44, 44);
  33. }
  34. - (void)viewDidLoad {
  35. [super viewDidLoad];
  36. self.gk_navTitle = @"AllRefresh";
  37. self.gk_navLineHidden = YES;
  38. self.gk_navTitleColor = [UIColor whiteColor];
  39. self.gk_navigationBar.hidden = YES;
  40. // 列表添加下拉刷新
  41. [self.childVCs enumerateObjectsUsingBlock:^(GKBaseListViewController *listVC, NSUInteger idx, BOOL * _Nonnull stop) {
  42. [listVC addHeaderRefresh];
  43. }];
  44. __weak __typeof(self) weakSelf = self;
  45. self.pageScrollView.mainTableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
  46. [self.pageScrollView.mainTableView.mj_header endRefreshing];
  47. [self.pageScrollView reloadData];
  48. [self loadDataFromNet:1];
  49. [self.childVCs enumerateObjectsUsingBlock:^(GKBaseListViewController *obj, NSUInteger idx, BOOL * _Nonnull stop) {
  50. [obj addHeaderRefresh];
  51. }];
  52. // 取出当前显示的listView
  53. VoiceListViewController *currentListVC = self.childVCs[self.segmentView.selectedIndex];
  54. [currentListVC headerReresh];
  55. }];
  56. self.pageScrollView.mainTableView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingBlock:^{
  57. // 取出当前显示的listView
  58. [self.pageScrollView.mainTableView.mj_footer endRefreshing];
  59. VoiceListViewController *currentListVC = self.childVCs[self.segmentView.selectedIndex];
  60. [currentListVC footerRereshing];
  61. [self.pageScrollView reloadData];
  62. }];
  63. [self.pageScrollView.mainTableView.mj_header beginRefreshing];
  64. }
  65. - (void)mainTableViewDidScroll:(UIScrollView *)scrollView isMainCanScroll:(BOOL)isMainCanScroll
  66. {
  67. self.listRefreshBtn.hidden = isMainCanScroll;
  68. }
  69. - (UIButton *)listRefreshBtn
  70. {
  71. if (!_listRefreshBtn)
  72. {
  73. _listRefreshBtn = [[UIButton alloc] init];
  74. if (@available(iOS 13.0, *)) {
  75. [_listRefreshBtn setImage:[UIImage systemImageNamed:@"arrow.clockwise.circle.fill"] forState:UIControlStateNormal];
  76. }
  77. [_listRefreshBtn addTarget:self action:@selector(refreshList) forControlEvents:UIControlEventTouchUpInside];
  78. [self.view addSubview:_listRefreshBtn];
  79. [self.view bringSubviewToFront:_listRefreshBtn];
  80. }
  81. return _listRefreshBtn;
  82. }
  83. #pragma mark - Action
  84. - (void)refreshList {
  85. self.pageScrollView.allowListRefresh = YES;
  86. self.pageScrollView.disableMainScrollInCeil = YES;
  87. GKBaseListViewController *currentListVC = self.childVCs[self.segmentView.selectedIndex];
  88. [currentListVC refreshWithCompletion:^{
  89. self.pageScrollView.allowListRefresh = NO;
  90. self.pageScrollView.disableMainScrollInCeil = NO;
  91. }];
  92. }
  93. @end