求助:在UIViewController中实现可水平调整的拆分面板分隔条
嘿,刚好我之前做过类似的需求,给你分享两个实用的实现方案,应该能完美解决你的问题!
方案一:用Auto Layout约束实现(首推,适配性拉满)
这是苹果官方推荐的做法,能轻松适配各种屏幕尺寸和旋转场景,和你在Android里用布局参数调整的思路异曲同工。
步骤拆解:
先在父
UIViewController里准备三个核心视图:- 顶部的
WKWebView - 中间的分隔条(一个普通
UIView就行,设置成灰色、高度6pt左右,让用户一眼能看出可拖动) - 底部的
UITableView(如果非要用UITableViewController,直接把它的view作为子视图加进来就行)
记得把三个视图的translatesAutoresizingMaskIntoConstraints都设为NO,交给Auto Layout管理。
- 顶部的
先给视图们加基础约束:
- 顶部WebView:和父视图的top、leading、trailing对齐
- 分隔条:和父视图leading、trailing对齐,顶部贴WebView的底部,高度固定6pt
- 底部TableView:和父视图leading、trailing、bottom对齐,顶部贴分隔条的底部
给分隔条加拖动手势,动态改约束:
关键是给WebView加一个可变的高度约束,拖动时更新这个约束值就行。举个OC代码例子:
// 先定义属性 @property (nonatomic, strong) NSLayoutConstraint *webViewHeightConstraint; @property (nonatomic, assign) CGFloat initialDragY; // 添加拖动手势 UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleSeparatorPan:)]; [self.separatorView addGestureRecognizer:panGesture]; // 手势处理方法 - (void)handleSeparatorPan:(UIPanGestureRecognizer *)gesture { CGPoint translation = [gesture translationInView:self.view]; if (gesture.state == UIGestureRecognizerStateBegan) { // 记录拖动开始时WebView的高度 self.initialDragY = self.webViewHeightConstraint.constant; } else if (gesture.state == UIGestureRecognizerStateChanged) { // 计算新高度,同时限制最小/最大值(防止拖到完全看不见) CGFloat newHeight = self.initialDragY + translation.y; newHeight = MAX(100, MIN(newHeight, self.view.bounds.size.height - 100)); self.webViewHeightConstraint.constant = newHeight; } }Swift版本也差不多:
var webViewHeightConstraint: NSLayoutConstraint! var initialDragY: CGFloat = 0 // 添加手势 let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handleSeparatorPan(_:))) separatorView.addGestureRecognizer(panGesture) @objc func handleSeparatorPan(_ gesture: UIPanGestureRecognizer) { let translation = gesture.translation(in: view) switch gesture.state { case .began: initialDragY = webViewHeightConstraint.constant case .changed: var newHeight = initialDragY + translation.y newHeight = max(100, min(newHeight, view.bounds.height - 100)) webViewHeightConstraint.constant = newHeight default: break } }
方案二:直接修改Frame实现(简单场景快速搞定)
如果你的页面不需要适配复杂场景,直接改frame也是个快速方案,缺点是屏幕旋转时需要额外处理布局。
步骤很简单:
- 初始化时给三个视图设置好初始frame:
WebView占上半屏,分隔条在中间,TableView占下半屏。 - 同样给分隔条加拖动手势,拖动时实时更新三个视图的frame:
- (void)handleSeparatorPan:(UIPanGestureRecognizer *)gesture { CGPoint translation = [gesture translationInView:self.view]; CGRect separatorFrame = self.separatorView.frame; if (gesture.state == UIGestureRecognizerStateBegan) { self.initialDragY = separatorFrame.origin.y; } else if (gesture.state == UIGestureRecognizerStateChanged) { CGFloat newSeparatorY = self.initialDragY + translation.y; // 限制拖动范围 newSeparatorY = MAX(100, MIN(newSeparatorY, self.view.bounds.size.height - 100)); // 更新三个视图的frame self.separatorView.frame = CGRectMake(0, newSeparatorY, self.view.bounds.size.width, 6); self.topWebView.frame = CGRectMake(0, 0, self.view.bounds.size.width, newSeparatorY); self.bottomTableView.frame = CGRectMake(0, newSeparatorY + 6, self.view.bounds.size.width, self.view.bounds.size.height - newSeparatorY - 6); // 重置手势偏移,避免累计误差 [gesture setTranslation:CGPointZero inView:self.view]; } }
额外小提示
- 给分隔条加个小样式,比如阴影或者边框,让用户明确知道这是可拖动的元素
- 一定要设置最小高度限制,不然很容易把WebView或TableView拖到完全看不见
- 如果用
UITableViewController,记得把它的view添加到父视图后,调用addChildViewController和didMoveToParentViewController,保证生命周期正常
内容的提问来源于stack exchange,提问作者NickPR
相关产品推荐
相关产品推荐

