Swift中如何独立调整UIView的宽度与高度
实现UIView独立调整宽高的两种方案
原有的捏合手势默认按统一比例缩放,所以只能同时调整宽高,你可以根据需求选择以下任意一种方案实现独立调整:
方案1:改造捏合手势实现非等比缩放
双指横向拉伸仅调整宽度、纵向拉伸仅调整高度,斜向拉伸可同时独立调整宽高,无需额外添加UI元素:
第一步:添加状态存储属性
// 类内部添加属性,存储捏合初始状态 private var initialViewSize: CGSize = .zero private var initialTouchPoints: [CGPoint] = []
第二步:替换原有捏合手势处理方法
@objc func pinchRecognized(pinch: UIPinchGestureRecognizer) { guard let view = pinch.view else { return } switch pinch.state { case .began: // 记录捏合开始时的视图尺寸和两个触摸点坐标 initialViewSize = view.bounds.size initialTouchPoints = (0..<pinch.numberOfTouches).compactMap { pinch.location(ofTouch: $0, in: self.view) } case .changed: guard initialTouchPoints.count == 2 else { return } // 获取当前两个触摸点坐标 let currentTouchPoints = (0..<pinch.numberOfTouches).compactMap { pinch.location(ofTouch: $0, in: self.view) } guard currentTouchPoints.count == 2 else { return } // 分别计算X、Y轴的独立缩放比例 let initialXDiff = abs(initialTouchPoints[0].x - initialTouchPoints[1].x) let currentXDiff = abs(currentTouchPoints[0].x - currentTouchPoints[1].x) let scaleX = initialXDiff > 0 ? currentXDiff / initialXDiff : 1 let initialYDiff = abs(initialTouchPoints[0].y - initialTouchPoints[1].y) let currentYDiff = abs(currentTouchPoints[0].y - currentTouchPoints[1].y) let scaleY = initialYDiff > 0 ? currentYDiff / initialYDiff : 1 // 应用新尺寸,添加最小宽高限制避免缩到无法操作 view.bounds.size = CGSize( width: max(50, initialViewSize.width * scaleX), height: max(50, initialViewSize.height * scaleY) ) default: break } }
方案2:添加边缘拖拽锚点(操作更直观)
在视图右下角添加可拖拽的调整把手,用户拖动把手即可自由调整宽高,学习成本更低:
第一步:添加状态存储属性
// 类内部添加属性 private var originalSize: CGSize = .zero // 尺寸调整把手,可自定义样式 private var resizeHandle: UIView = { let view = UIView(frame: CGRect(x: 0, y: 0, width: 30, height: 30)) view.backgroundColor = .systemBlue view.layer.cornerRadius = 15 return view }()
第二步:修改手势添加方法
func addGestures() { // 原有拖动视图的代码保留 let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePan)) gestureRecognizer.delegate = self myView.addGestureRecognizer(gestureRecognizer) myView.isUserInteractionEnabled = true myView.isMultipleTouchEnabled = true // 添加尺寸调整把手 myView.addSubview(resizeHandle) resizeHandle.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ resizeHandle.trailingAnchor.constraint(equalTo: myView.trailingAnchor, constant: 10), resizeHandle.bottomAnchor.constraint(equalTo: myView.bottomAnchor, constant: 10), resizeHandle.widthAnchor.constraint(equalToConstant: 30), resizeHandle.heightAnchor.constraint(equalToConstant: 30) ]) // 给把手添加拖拽手势 let resizePan = UIPanGestureRecognizer(target: self, action: #selector(handleResizePan(_:))) resizeHandle.addGestureRecognizer(resizePan) // 原有等比捏合手势如果不需要可以直接删除,也可保留共存 // let pinchGesture = UIPinchGestureRecognizer(target: self, action:#selector(pinchRecognized(pinch:))) // pinchGesture.delegate = self // myView.addGestureRecognizer(pinchGesture) }
第三步:添加尺寸调整手势处理方法
@objc func handleResizePan(_ gesture: UIPanGestureRecognizer) { guard let resizeView = gesture.view, let targetView = resizeView.superview else { return } switch gesture.state { case .began: originalSize = targetView.bounds.size case .changed: let translation = gesture.translation(in: self.view) // 按拖拽偏移调整宽高,添加最小尺寸限制 let newWidth = max(50, originalSize.width + translation.x) let newHeight = max(50, originalSize.height + translation.y) targetView.bounds.size = CGSize(width: newWidth, height: newHeight) default: break } }
注意事项
- 尽量直接修改视图的
bounds.size属性实现尺寸调整,不要使用transform缩放,避免后续修改frame时出现坐标异常 - 两种方案可以共存,也可根据产品交互需求单独使用
- 最小宽高限制的数值可以根据业务需求自行修改
内容的提问来源于stack exchange,提问作者Abhishek Kumar
相关产品推荐
相关产品推荐

