有没有办法在UITabBar
中找到特定UITabBarItem
的框架?获取特定标签栏项目的框架
具体而言,我想创建一个图像“落入”其中一个选项卡的动画,类似于例如。删除邮件中的电子邮件或在iTunes应用程序中购买曲目。所以我需要动画的目标坐标。
据我所知,没有公共的API来获得坐标,但会喜欢错误的。简而言之,我将不得不使用给定选项卡的索引相对于选项卡栏框架来猜测坐标。
有没有办法在UITabBar
中找到特定UITabBarItem
的框架?获取特定标签栏项目的框架
具体而言,我想创建一个图像“落入”其中一个选项卡的动画,类似于例如。删除邮件中的电子邮件或在iTunes应用程序中购买曲目。所以我需要动画的目标坐标。
据我所知,没有公共的API来获得坐标,但会喜欢错误的。简而言之,我将不得不使用给定选项卡的索引相对于选项卡栏框架来猜测坐标。
与UITabBar中的标签栏项目相关联的子视图属于UITabBarButton类。通过记录中的UITabBar一样的子视图有两个选项卡:
for (UIView* view in self.tabBar.subviews)
{
NSLog(view.description);
}
你:
<_UITabBarBackgroundView: 0x6a91e00; frame = (0 0; 320 49); opaque = NO; autoresize = W; userInteractionEnabled = NO; layer = <CALayer: 0x6a91e90>> - (null)
<UITabBarButton: 0x6a8d900; frame = (2 1; 156 48); opaque = NO; layer = <CALayer: 0x6a8db10>>
<UITabBarButton: 0x6a91b70; frame = (162 1; 156 48); opaque = NO; layer = <CALayer: 0x6a8db40>>
在此基础上的解决方案是一种微不足道的。我写了尝试这一点的方法如下:
+ (CGRect)frameForTabInTabBar:(UITabBar*)tabBar withIndex:(NSUInteger)index
{
NSUInteger currentTabIndex = 0;
for (UIView* subView in tabBar.subviews)
{
if ([subView isKindOfClass:NSClassFromString(@"UITabBarButton")])
{
if (currentTabIndex == index)
return subView.frame;
else
currentTabIndex++;
}
}
NSAssert(NO, @"Index is out of bounds");
return CGRectNull;
}
应当指出的是,UITabBar的结构(子视图)和类UITabBarButton本身不属于公共API的一部分,所以理论上它可以改变在任何新的iOS版本中没有事先通知。尽管如此,它们不太可能会改变这些细节,并且它适用于iOS 5-6和以前的版本。
+ 1为iPad,但此解决方案不适用于iPhone/iPod。这给出了错误的坐标。 – iLearner 2013-04-29 14:36:56
适用于iPhone的iOS 9.2相当不错。我用''''UIControl'''(@Greg Combs建议)作为一种子视图类比较。 – rafalkitta 2016-03-16 15:04:25
伊姆雷的实施失踪了几个重要的细节。
所以我改变了他的代码一点点,我想出了这个:
+ (CGRect)frameForTabInTabBar:(UITabBar*)tabBar withIndex:(NSUInteger)index
{
NSMutableArray *tabBarItems = [NSMutableArray arrayWithCapacity:[tabBar.items count]];
for (UIView *view in tabBar.subviews) {
if ([view isKindOfClass:NSClassFromString(@"UITabBarButton")] && [view respondsToSelector:@selector(frame)]) {
// check for the selector -frame to prevent crashes in the very unlikely case that in the future
// objects thar don't implement -frame can be subViews of an UIView
[tabBarItems addObject:view];
}
}
if ([tabBarItems count] == 0) {
// no tabBarItems means either no UITabBarButtons were in the subView, or none responded to -frame
// return CGRectZero to indicate that we couldn't figure out the frame
return CGRectZero;
}
// sort by origin.x of the frame because the items are not necessarily in the correct order
[tabBarItems sortUsingComparator:^NSComparisonResult(UIView *view1, UIView *view2) {
if (view1.frame.origin.x < view2.frame.origin.x) {
return NSOrderedAscending;
}
if (view1.frame.origin.x > view2.frame.origin.x) {
return NSOrderedDescending;
}
NSAssert(NO, @"%@ and %@ share the same origin.x. This should never happen and indicates a substantial change in the framework that renders this method useless.", view1, view2);
return NSOrderedSame;
}];
CGRect frame = CGRectZero;
if (index < [tabBarItems count]) {
// viewController is in a regular tab
UIView *tabView = tabBarItems[index];
if ([tabView respondsToSelector:@selector(frame)]) {
frame = tabView.frame;
}
}
else {
// our target viewController is inside the "more" tab
UIView *tabView = [tabBarItems lastObject];
if ([tabView respondsToSelector:@selector(frame)]) {
frame = tabView.frame;
}
}
return frame;
}
工程就像一个魅力! – Tafkadasoh 2013-08-20 15:54:30
鉴于UITabBarButton是一个私人iOS类,Apple的AppStore审查过程变得更加彻底,我认为谨慎的做法是根本不要任何对该类的引用 - 即使通过NSClassFromString()。但它是一个UIControl子类,所有UIControls都实现 - (CGRect)框架。所以你可以通过以下方式消除一堆条件: 'if([view isKindOfClass:[UIControl class]]) [tabBarItems addObject:view];' – 2013-09-16 22:32:29
这似乎在旋转设备后返回不正确的结果。我从肖像旋转到风景,但它返回肖像值。当我从风景旋转到肖像时,它会返回风景值。我在'viewDidLayoutSubviews'中运行这段代码。 有什么想法? – BFeher 2014-10-06 08:04:12
我将添加对我来说,我简单的UITabBarController场景什么工作,一切都是合法的,但它有一个前提该物品间隔相等。在iOS7下,它返回一个UITabBarButton的实例,但是如果你将它用作UIView *,你真的不在乎它是什么,并且你没有明确指出类。返回的视图的框架是你要找的框架:
-(UIView*)viewForTabBarItemAtIndex:(NSInteger)index {
CGRect tabBarRect = self.tabBarController.tabBar.frame;
NSInteger buttonCount = self.tabBarController.tabBar.items.count;
CGFloat containingWidth = tabBarRect.size.width/buttonCount;
CGFloat originX = containingWidth * index ;
CGRect containingRect = CGRectMake(originX, 0, containingWidth, self.tabBarController.tabBar.frame.size.height);
CGPoint center = CGPointMake(CGRectGetMidX(containingRect), CGRectGetMidY(containingRect));
return [ self.tabBarController.tabBar hitTest:center withEvent:nil ];
}
它的作用是计算在按钮所在的UITabBar的矩形,认为这一矩形的中心,并在此挖掘出的观点通过hitTest:withEvent点。
很棒的发现!这比黑客呃更少。 – brynbodayle 2014-07-09 21:09:26
它不适用于iPad,因为每个项目的宽度不等于tabbar分隔项目数量的宽度 – ZYiOS 2014-08-22 10:50:08
选项卡栏按钮是启用了用户交互的唯一子视图。检查此而不是UITabBarButton,以避免违反隐藏的API。
for (UIView* view in self.tabBar.subviews)
{
if([view isUserInteractionEnabled])
{
[myMutableArray addObject:view];
}
}
一旦在数组中,根据原点x对它进行排序,并且您将有按其真实顺序的标签栏按钮。
另一种可能,但草率的解决办法是以下几点:
guard let view = self.tabBarVC?.tabBar.items?[0].valueForKey("view") as? UIView else
{
return
}
let frame = view.frame
在雨燕4.0:
private func frameForTabAtIndex(index: Int) -> CGRect {
var frames = view.subviews.flatMap { (view:UIView) -> CGRect? in
if let view = view as? UIControl {
return view.frame
}
return nil
}
frames.sort { $0.origin.x < $1.origin.x }
if frames.count > index {
return frames[index]
}
return frames.last ?? CGRect.zero
}
这对iPhone很好,但似乎在iPad上工作不正确。在iPad上,项目(或至少 - 图像)放置在中心,同时返回等宽的帧。 – KlimczakM 2016-10-10 10:36:12
@KlimczakM这应该返回实际项目的框架 - 如果你知道图像大小,你可以在'flatMap'调用中创建CGRects,给定大小,以'view.center'为中心? – buildsucceeded 2016-10-18 12:44:18
你不需要任何私有API,只需使用UITabbar财产itemWidth
和itemSpacing
。设置这两个值一样以下:
NSInteger tabBar.itemSpacing = 10; tabBar.itemWidth = ([UIScreen mainScreen].bounds.size.width - self.tabBarController.tabBar.itemSpacing * (itemsCount - 1)) /itemsCount;
注意该问题不会影响使用UITabBarItem图像和标题的大小或位置。
然后你就可以得到ith
项目的中心x像以下:
CGFloat itemCenterX = (tabBar.itemWidth + tabBar.itemSpacing) * ith + tabBar.itemWidth/2;
斯威夫特+ iOS的11
private func frameForTabAtIndex(index: Int) -> CGRect {
guard let tabBarSubviews = tabBarController?.tabBar.subviews else {
return CGRect.zero
}
var allItems = [UIView]()
for tabBarItem in tabBarSubviews {
if tabBarItem.isKind(of: NSClassFromString("UITabBarButton")!) {
allItems.append(tabBarItem)
}
}
let item = allItems[index]
return item.superview!.convert(item.frame, to: view)
}
喂,你有没有发现在swift..If此解决方案是的,那么你可以请帮助我.. – Rahul 2017-04-18 12:20:56