为何带自定义视图的BarButtonItem设置固定尺寸仍因图片拉伸?
问题分析与解决方案
这个问题我做项目时也踩过坑!明明给UIButton设置了固定的frame = (0,0,32,32),但最终UIBarButtonItem的customView却被拉伸成了(0 0; 128 44),核心原因在于UIBarButtonItem对customView的尺寸调整逻辑,结合你用的128×128图片,具体原因如下:
为什么会出现这个情况?
- intrinsicContentSize的影响:UIButton的默认intrinsicContentSize是由其内部图片的原生尺寸决定的。你的图片是128×128,所以按钮的固有尺寸就变成了128×128。当你把它作为customView传给UIBarButtonItem时,系统会优先参考这个固有尺寸,而不是你手动设置的frame。
- 导航栏高度限制:导航栏的默认高度是44px,所以按钮的高度会被强制压缩到44px,这就是为什么你看到的frame高度是44,宽度却保留了图片的128px。
解决办法(按推荐程度排序)
方法1:用Auto Layout约束强制尺寸 + 调整图片显示模式(最推荐)
这种方式既保证按钮尺寸固定,又能让图片自适应按钮大小,不会变形:
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; UIImage *menuImage = [UIImage imageNamed:@"menubutton.png"]; // 保持图片原始渲染模式(避免被导航栏色调影响) [button setImage:[menuImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] forState:UIControlStateNormal]; // 设置图片的显示模式,让图片缩放到按钮尺寸内 button.imageView.contentMode = UIViewContentModeScaleAspectFit; // 添加Auto Layout约束,强制按钮宽高为32px [button.widthAnchor constraintEqualToConstant:32].active = YES; [button.heightAnchor constraintEqualToConstant:32].active = YES; // 添加点击事件 [button addTarget:self action:@selector(leftMenuButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; // 设置为左BarButtonItem self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
方法2:直接修改按钮的intrinsicContentSize
如果不想用Auto Layout,可以直接覆盖按钮的固有尺寸,让系统以此为基准调整:
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; [button setImage:[UIImage imageNamed:@"menubutton.png"] forState:UIControlStateNormal]; [button addTarget:self action:@selector(leftMenuButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; // 强制设置按钮的固有尺寸为32×32 button.intrinsicContentSize = CGSizeMake(32, 32); self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
注意:如果后续需要调整按钮尺寸,这种方式不如Auto Layout灵活,适合简单场景。
方法3:提前压缩图片尺寸
把menubutton.png提前压缩到32×32的尺寸,这样UIButton的intrinsicContentSize就会自动变成32×32,系统就不会拉伸按钮了。不过这种方式不够灵活,如果后续需要修改按钮大小,还得重新处理图片。
总结
优先选择方法1,Auto Layout的方式适配性更强,能应对不同尺寸的导航栏(比如iPhone横屏、大标题导航栏等场景),同时保证图片显示正常。
内容的提问来源于stack exchange,提问作者Prashant Tukadiya
相关产品推荐
相关产品推荐

