Swift中如何根据内容自动调整XIB自定义InfoWindow的宽度
解决自定义Map InfoWindow宽度自适应内容的问题
我之前也踩过这个坑——地图的InfoWindow本质是把你的自定义View渲染成快照展示,所以单纯在Storyboard/XIB里调约束经常达不到预期效果,得结合代码让视图正确计算自适应尺寸。给你整理几个关键步骤:
第一步:调整XIB里的约束和控件设置
先确保你的XIB布局是支持自适应的:
- 删掉
MapInfoWindow本身的固定宽高约束,让子视图的约束来决定它的尺寸; - 给
titleInfo和adressInfo设置约束:leading、trailing分别贴紧父视图的内边距(比如设8pt的左右padding),top和bottom也设置合适的垂直间距(比如上下各12pt,两个label之间8pt); - 把两个label的
numberOfLines设为0,lineBreakMode选择Word Wrap,这样文本会自动换行,撑开视图宽度。
第二步:修改MapInfoWindow类代码
在你的MapInfoWindow类里,添加内容配置方法并重写intrinsic尺寸计算:
public protocol nonPaidDelegate: class { func didTapMapsSelectButton() } class MapInfoWindow: UIView { @IBOutlet weak var titleInfo: UILabel! @IBOutlet weak var adressInfo: UILabel! @IBOutlet weak var selectButton: UIButton! // 补全按钮IBOutlet weak var delegate: nonPaidDelegate? // 添加配置方法,设置内容后强制布局 func configure(with title: String, address: String) { titleInfo.text = title adressInfo.text = address // 强制触发布局,让视图计算正确的尺寸 layoutIfNeeded() // 刷新intrinsic尺寸,让系统重新计算 invalidateIntrinsicContentSize() } // 重写intrinsicContentSize,返回自适应的尺寸 override var intrinsicContentSize: CGSize { // 用系统布局计算压缩后的合适尺寸 let fittingSize = systemLayoutSizeFitting(UIView.layoutFittingCompressedSize) // 给最小宽度设个下限,避免内容太少时视图过窄 return CGSize(width: max(fittingSize.width, 200), height: fittingSize.height) } @IBAction func selectButtonTapped(_ sender: UIButton) { delegate?.didTapMapsSelectButton() } }
第三步:在地图代理方法里正确返回InfoWindow
在你的地图ViewController的markerInfoWindow代理方法中,先配置内容再返回视图,确保返回前视图已经完成布局:
func mapView(_ mapView: GMSMapView, markerInfoWindow marker: GMSMarker) -> UIView? { guard let infoWindow = Bundle.main.loadNibNamed("MapInfoWindow", owner: self, options: nil)?.first as? MapInfoWindow else { return nil } // 绑定代理(如果需要的话) infoWindow.delegate = self // 配置标题和地址 infoWindow.configure(with: marker.title ?? "", address: marker.snippet ?? "") // 可选:如果还是尺寸不对,手动设置frame let fittingSize = infoWindow.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize) infoWindow.frame = CGRect(x: 0, y: 0, width: fittingSize.width, height: fittingSize.height) return infoWindow }
额外注意点
- 如果你用的是Apple Maps而不是Google Maps,逻辑是一样的,只是代理方法换成
mapView(_:viewFor:); - 检查XIB里
MapInfoWindow的Autoresizing Mask,确保没有固定宽度的设置(可以勾选Flexible Width); - 如果你的InfoWindow里有图片等其他控件,也要给它们设置正确的约束,避免破坏自适应布局。
内容的提问来源于stack exchange,提问作者Panagiotis Goutzianas
相关产品推荐
相关产品推荐

