ios scrollview嵌套tableview同向滑动的示例

2025-05-29 0 47

我讨论的问题是嵌套同向滑动,能避免尽量避免。最好用一个tableview实现。一个tableview不够用了再嵌套,适用复杂场景。

首先我说下不适用的,免得大家浪费时间。

1.不适用上下拉刷新加载更多的页面。

2.不适用点击cell获取点击事件的页面,可以加入button点击获取事件。

官方文档说尽量不要进行两个竖直或两个水平方向滑动的视图嵌套。因为这个时候机器不知道用户要让哪个滑动,但在我们这个神奇的国度,项目中经常出现这样的需求,产品经理总爱这样做,andriod那边是比较容易实现的,ios这边十分复杂,我研究了一天,写了个demo,可以勉强实现,我的项目中就有上下拉,因此我就硬嵌套了,用户滑动的时候不能准确地按自己的意愿滑动scrollview、tableview。就这样了,这个没有解决方案的。

我做到的效果是手点在哪个视图上,哪个视图就滚动,当小的scroll滚到到自己的临界值就滚动大的scroll,当大的也到临界值就不滚动。顺便实现了一个伪悬浮的secview如果没有那个悬浮的就把那个悬浮高度floatviewheight置0。剩下的根据页面调整frame即可通用。

这是效果图

ios scrollview嵌套tableview同向滑动的示例

下面我说一下在没有以上两点不适用的页面的实现的思路:

scrollview在控制器的view上,是一个大的视图,tablewview在scrollview上。根据拖拽手势配合,先判断首先触摸点在哪个view上,再对哪个view滑动操作。解决手势和button点击冲突。下面看代码,注释十分清晰。github有demo,欢迎阅读: https://github.com/qingyindaoren/scrollinsettable.git

核心代码如下:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288
#import "viewcontroller.h"

#import "yygesturerecognizer.h"

#import "scrolltableviewcell.h"

#import "mbprogresshud+add.h"

#define screenwidth [uiscreen mainscreen].bounds.size.width

#define screenheight [uiscreen mainscreen].bounds.size.height

//虚假的悬浮效果

static cgfloat floatviewheight = 30.0;

static cgfloat navheitht = 64;

// 这个系数根据自己喜好设置大小,=屏幕视图滑动距离/手指滑动距离

#define movescale 2

@interface viewcontroller ()<uitableviewdelegate,uitableviewdatasource,uigesturerecognizerdelegate>

@property (nonatomic,weak)uiscrollview *scroll;

@property (nonatomic, strong) nsarray *titles;

@property (nonatomic,weak)uitableview *insettableview;

@property (nonatomic,assign)cgfloat tabley;

@property (nonatomic,assign)cgfloat tablestarty;

@property (nonatomic,assign)cgfloat scrolly;

@property (nonatomic,assign)cgfloat scrollstarty;

//tableview 的y值 在scrollview中的位置

@property (nonatomic,assign)cgfloat tableframey;

@end

@implementation viewcontroller

- (void)viewdidload {

[super viewdidload];

// do any additional setup after loading the view, typically from a nib.

self.view.backgroundcolor = [uicolor whitecolor];

self.title = @"scrollscroll";

// 有导航最上部视图是scrollview 内部空间位置会下移,设置这个属性后不下移。

if ([self respondstoselector:@selector(setautomaticallyadjustsscrollviewinsets:)]) {

self.automaticallyadjustsscrollviewinsets = no;

}

uiscrollview *scroll = [[uiscrollview alloc]initwithframe:cgrectmake(0,navheitht, screenwidth, screenheight-navheitht)];

scroll.backgroundcolor = [uicolor colorwithred:0.4 green:0.3 blue:0.2 alpha:1.0];;

[self.view addsubview:scroll];

self.scroll = scroll;

//根据需求设置tableview的y值 暂写scroll高的2分之一

self.tableframey = self.scroll.frame.size.height/2;

uiimageview *headimage = [[uiimageview alloc]initwithframe:cgrectmake(0, 0, screenwidth, self.tableframey-floatviewheight)];

headimage.image = [uiimage imagenamed:@"scrollhead"];

headimage.contentmode = uiviewcontentmodescaleaspectfill;

[self.scroll addsubview:headimage];

nsarray *titles = @[@"ico详情",@"央行放大招",@"比特币会涨",@"神秘中本村"];

self.titles = titles;

uisegmentedcontrol *segment = [[uisegmentedcontrol alloc] initwithframe:cgrectmake(5, scroll.bounds.size.height/2-30, self.scroll.bounds.size.width - 10, 30)];

[segment addtarget:self action:@selector(segmentvaluechanged:) forcontrolevents:uicontroleventvaluechanged];

for (nsstring *title in _titles) {

[segment insertsegmentwithtitle:title atindex:segment.numberofsegments animated:false];

}

segment.selectedsegmentindex = 0;

[self.scroll addsubview:segment];

uitableview *insettable = [[uitableview alloc]initwithframe:cgrectmake(0,self.tableframey, self.view.bounds.size.width, screenheight-navheitht-floatviewheight)];

insettable.backgroundcolor = [uicolor colorwithred:0.9 green:0.9 blue:0.9 alpha:1.0];

insettable.datasource = self;

insettable.delegate = self;

[self.scroll addsubview:insettable];

self.insettableview = insettable;

//github搜索 yykit 或yytext 里面有 yygesturerecognizer这个类,这个类需要做一些修改, // 在yygesture中所有触摸事件方法里 加上super的方法,原文件里没有,否则响应链条中断,scroll或tablew的按钮点击事件不执行。

//这个类原文件继承于uigesturerecognizer, 改为继承于uipangesturerecognizer 否则点击事件不执行。

//运行效果详见我的demo

yygesturerecognizer *yyges = [yygesturerecognizer new];

yyges.action = ^(yygesturerecognizer *gesture, yygesturerecognizerstate state){

if (state != yygesturerecognizerstatemoved) return ;

if (cgrectcontainspoint(self.insettableview.frame, gesture.startpoint)) {

//滑动tableview

[self tablescrollwithgesture:gesture];

}else{

//滑动scrollview

[self scrollscrollwithgesture:gesture];

}

};

//必须给scroll 加上手势 不要给view加,不然滑动tablew的时候会错误判断去滑动scroll。

[self.scroll addgesturerecognizer:yyges];

//实现手势代理,解决交互冲突

yyges.delegate = self;

scroll.contentsize = cgsizemake(self.view.bounds.size.width, self.tableframey+self.insettableview.frame.size.height);

}

//解决手势按钮冲突

- (bool)gesturerecognizer:(uigesturerecognizer *)gesturerecognizer shouldreceivetouch:(uitouch *)touch

{

//如果是 segment或scroll上的其他按钮,取消手势

if([nsstringfromclass(touch.view.superclass) isequaltostring:@"uicontrol"]){

return no;

}

//

return yes;

}

//

- (void)segmentvaluechanged:(uisegmentedcontrol *)segment {

//scroll 到底部

cgfloat offset = self.scroll.contentsize.height - self.insettableview.bounds.size.height-floatviewheight;

if (offset > 0)

{

self.scrolly = offset;

[self.scroll setcontentoffset:cgpointmake(0, offset) animated:yes];

}

//tableview到顶部

self.tabley = 0;

[self.insettableview setcontentoffset:cgpointmake(0, self.tabley) animated:yes];

}

- (void)tablescrollwithgesture:(yygesturerecognizer *)gesture{

cgfloat scrolly;

if (self.tablestarty != gesture.startpoint.y) {

scrolly = -(gesture.currentpoint.y-gesture.startpoint.y) ;

}else{

scrolly = -(gesture.currentpoint.y-gesture.lastpoint.y) ;

}

self.tablestarty = gesture.startpoint.y;

self.tabley += scrolly*movescale;

//为了显示底部超出屏幕的tableview那部分 滑动scrollview 此时tablewview已经滑动到了底部

if (self.tabley> self.insettableview.contentsize.height-self.insettableview.bounds.size.height){

self.scrolly += self.tabley-(self.insettableview.contentsize.height-self.insettableview.bounds.size.height);

//tablewview滑动到底部就不要滑了

self.tabley = self.insettableview.contentsize.height-self.insettableview.bounds.size.height;

//scrollview 滑动到了底部就不要滑动了

if (self.scrolly> self.scroll.contentsize.height-self.insettableview.bounds.size.height-floatviewheight){

self.scrolly = self.scroll.contentsize.height-self.insettableview.bounds.size.height-floatviewheight;

//如果scrollview意外的contentsize 小于自己的大小,scrollview就不要滑了

if (self.scrolly<0) {

self.scrolly = 0;

}

}

[self.scroll setcontentoffset:cgpointmake(0, self.scrolly) animated:yes];

//如果tablewview的cell过少或行高过少致使其contentsize 小于自己的大小,tableview就不要滑了

if (self.tabley<0) {

self.tabley = 0;

}

}

//如果滑到了tableview的最上部,停止滑动tablewview, 如果此时scrollview 没有在最上部就滑动scrollview到最上部

if (self.tabley<0){

self.scrolly += self.tabley;

//scroll已经在最上部了,scroll就不滑了

if (self.scrolly<0) {

self.scrolly = 0;

}

nslog(@"scroll %lf",self.scrolly);

[self.scroll setcontentoffset:cgpointmake(0, self.scrolly) animated:yes];

//停止滑动tablewview

self.tabley = 0;

}

nslog(@"table %lf",self.tabley);

[self.insettableview setcontentoffset:cgpointmake(0, self.tabley) animated:yes];

}

- (void)scrollscrollwithgesture:(yygesturerecognizer *)gesture{

cgfloat scrolly;

if (self.scrollstarty != gesture.startpoint.y) {

scrolly = -(gesture.currentpoint.y-gesture.startpoint.y) ;

}else{

scrolly = -(gesture.currentpoint.y-gesture.lastpoint.y) ;

}

self.scrollstarty = gesture.startpoint.y;

self.scrolly += scrolly*movescale;

//如果滑到了scroll的底部就不要滑了

if (self.scrolly> self.scroll.contentsize.height-self.insettableview.bounds.size.height-floatviewheight){

self.scrolly = self.scroll.contentsize.height-self.insettableview.bounds.size.height-floatviewheight;

//如果scrollview意外的contentsize 小于自己的大小,scrollview就不要滑了

if (self.scrolly<0) {

self.scrolly = 0;

}

}

//如果滑到了scroll顶部就不要滑了

if (self.scrolly<0){

self.scrolly = 0;

}

nslog(@"scroll %lf",self.scrolly);

[self.scroll setcontentoffset:cgpointmake(0, self.scrolly) animated:yes];

}

#pragma mark - 展示tableview的代理

- (cgfloat)tableview:(uitableview *)tableview heightforrowatindexpath:(nsindexpath *)indexpath {

return 70;

}

- (nsinteger)tableview:(uitableview *)tableview numberofrowsinsection:(nsinteger)section {

return 10;

}

- (uitableviewcell *)tableview:(uitableview *)tableview cellforrowatindexpath:(nsindexpath *)indexpath {

scrolltableviewcell * cell = [tableview dequeuereusablecellwithidentifier:@"scrolltableviewcell"];

if (!cell)

{

[tableview registernib:[uinib nibwithnibname:@"scrolltableviewcell" bundle:nil] forcellreuseidentifier:@"scrolltableviewcell"];

cell = [tableview dequeuereusablecellwithidentifier:@"scrolltableviewcell"];

}

cell.backgroundcolor = [uicolor clearcolor];

cell.selectionstyle = uitableviewcellselectionstylenone;

cell.titletext.text = [nsstring stringwithformat:@"\\t第%zd行",indexpath.row];

cell.detailtext.text = @"滑屏呀滑屏呀划呀";

cell.detailtext.textcolor = self.navigationcontroller.navigationbar.tintcolor;

cell.indexpath = indexpath;

cell.selectcellblock = ^(nsindexpath *indexpath) {

nsstring *tip = [nsstring stringwithformat:@"点击了第%ld组%ld行",indexpath.section,indexpath.row];;

[mbprogresshud showmessage:tip view:nil];

nslog(@"%@",tip);

};

return cell;

}

- (nsinteger)numberofsectionsintableview:(uitableview *)tableview{

return 3;

}

-(uiview *)tableview:(uitableview *)tableview viewforheaderinsection:(nsinteger)section{

uiview *v = [[uiview alloc]initwithframe:cgrectmake(0, 0, screenwidth, 50)];

v.backgroundcolor = [uicolor orangecolor];

uilabel *l = [[uilabel alloc]initwithframe:v.bounds];

l.text =[nsstring stringwithformat:@"tableview的组头%ld",section];

l.textcolor = [uicolor whitecolor];

l.textalignment = nstextalignmentcenter;

[v addsubview:l];

return v;

}

//组头高

-(cgfloat)tableview:(uitableview *)tableview heightforheaderinsection:(nsinteger)section{

return 50;

}

//这个方法不可用了,除非点击了cellcontenview之外的区域 只能同过加按钮的方式接受点击事件

-(void)tableview:(uitableview *)tableview didselectrowatindexpath:(nsindexpath *)indexpath{

nslog(@"点击了第%ld行",indexpath.row);

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持快网idc。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 ios scrollview嵌套tableview同向滑动的示例 https://www.kuaiidc.com/89923.html

相关文章

发表评论
暂无评论