简体   繁体   English

设备旋转后的iOS按钮点击区域

[英]iOS button tap area after device rotation

I'm having trouble with a couple of buttons after rotation. 旋转后,我在使用几个按钮时遇到麻烦。 When in portrait mode, the buttons are stacked at the bottom of the screen. 在纵向模式下,按钮堆叠在屏幕底部。 When in landscape, they are moved and resized to be side-by-side at the bottom of the screen. 在横向时,它们会移动并调整大小以在屏幕底部并排放置。 This all works great and the buttons behave correctly. 所有这些都很好用,并且按钮行为正确。 However, if the phone is then rotated back to portrait, the buttons' tap area is wrong - only the left 1/3 of the buttons is tappable. 但是,如果随后将手机旋转回纵向,则按钮的点击区域不正确-仅可以敲击按钮的左1/3。

Here's the code that does the rotation. 这是进行旋转的代码。 (I call it within viewWillAppear as well, so it always gets executed when the view is shown, in case the view is already in landscape.) I've put the buttons in their own inner view. (我也在viewWillAppear中调用它,因此,如果视图已经在横向,则总是在显示视图时执行它。)我已将按钮放在其自己的内部视图中。

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
                            duration:(NSTimeInterval)duration {


// determine our dimensions based on orientation
CGRect mainRect = [[UIScreen mainScreen] bounds];
CGFloat maxWidthHeight = MAX(mainRect.size.width, mainRect.size.height);
CGFloat minWidthHeight = MIN(mainRect.size.width, mainRect.size.height);
CGFloat _windowWidth = (UIDeviceOrientationIsPortrait(toInterfaceOrientation)) ? minWidthHeight : maxWidthHeight;


// get the current sizes of the things we are moving
CGRect saveRect = self.viewButtons.frame;
CGRect addLocRect = self.buttonAddLocation.frame;
CGRect connectRect = self.buttonConnect.frame;    

// This will be set below in one of the if-else branches
CGFloat buttonWidth = 0;

// determine the offset from the left/right based on device and orientation
int offset = 0;
if ([self isIphone]) {
    offset = (UIDeviceOrientationIsPortrait(toInterfaceOrientation)) ? OFFSET_LEFT_PORTRAIT_IPHONE : OFFSET_LEFT_LANDSCAPE_IPHONE;
} else {
    offset = (UIDeviceOrientationIsPortrait(toInterfaceOrientation)) ? OFFSET_LEFT_PORTRAIT_IPAD : OFFSET_LEFT_LANDSCAPE_IPAD;
}

// change the size & location of the button frame to just the button height to maximize the area for the location list
// no matter what orientation, the button frame will fill the bottom of the screen
saveRect.size.width = _windowWidth - 2*offset;
saveRect.origin.x = offset;

// for Landscape, move the buttons to side-by-side at the bottom of the window
if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) {

    // size & move the buttons to fit side-by-side
    buttonWidth = (saveRect.size.width)*.4;

    addLocRect.origin.x += offset;
    addLocRect.origin.y = saveRect.size.height - addLocRect.size.height ;

    connectRect.origin.x = saveRect.size.width - buttonWidth - offset;
    connectRect.origin.y = saveRect.size.height - connectRect.size.height;

} else { // Portrait

    // move the buttons down to the bottom of the frame, stacked
    // size the buttons to be fully across the screen
    buttonWidth = saveRect.size.width;

    addLocRect.origin.y = 0 ; // at the top of the button view
    addLocRect.origin.x = 0;
    connectRect.origin.y = saveRect.size.height - connectRect.size.height;
    connectRect.origin.x = 0;

}

connectRect.size.width = buttonWidth;
addLocRect.size.width = buttonWidth;
self.buttonAddLocation.frame = addLocRect;
self.buttonConnect.frame = connectRect;
self.viewButtons.frame = saveRect;
}

I added some logging to determine what's going on with the frames and bounds at the end of the rotation: 我添加了一些日志记录来确定旋转结束时帧和边界的状况:

 NSLog(@"Post rotation:");
 NSLog(@"AddLocation bounds: w=%f, h=%f, x=%f, y=%f", self.buttonAddLocation.frame.size.width, self.buttonAddLocation.frame.size.height,
      self.buttonAddLocation.frame.origin.x, self.buttonAddLocation.frame.origin.y);
 NSLog(@"AddLocation frame: w=%f, h=%f, x=%f, y=%f", self.buttonAddLocation.bounds.size.width, self.buttonAddLocation.bounds.size.height,
      self.buttonAddLocation.bounds.origin.x, self.buttonAddLocation.bounds.origin.y);

 NSLog(@"viewButtons bounds: w=%f, h=%f, x=%f, y=%f", self.viewButtons.frame.size.width, self.viewButtons.frame.size.height,
      self.viewButtons.frame.origin.x, self.viewButtons.frame.origin.y);
 NSLog(@"viewButtons frame: w=%f, h=%f, x=%f, y=%f", self.viewButtons.bounds.size.width, self.viewButtons.bounds.size.height,
      self.viewButtons.bounds.origin.x, self.viewButtons.bounds.origin.y);

Which resulted in: 结果是:

Post rotation: (NOTE: Portrait, initial appearance)
AddLocation bounds: w=272.000000, h=55.000000, x=0.000000, y=0.000000
AddLocation frame: w=272.000000, h=55.000000, x=0.000000, y=0.000000
viewButtons bounds: w=272.000000, h=120.000000, x=24.000000, y=374.000000
viewButtons frame: w=272.000000, h=120.000000, x=0.000000, y=374.000000
Post rotation: (NOTE: rotate to Landscape)
AddLocation bounds: w=217.600006, h=55.000000, x=12.000000, y=65.000000
AddLocation frame: w=217.600006, h=55.000000, x=0.000000, y=0.000000
viewButtons bounds: w=544.000000, h=120.000000,  x=12.000000, y=374.000000
viewButtons frame: w=544.000000, h=120.000000, x=0.000000, y=374.000000
Post rotation: (NOTE: back to Portrait)
AddLocation bounds: w=272.000000, h=55.000000, x=0.000000, y=0.000000
AddLocation frame: w=272.000000, h=55.000000, x=0.000000, y=0.000000
viewButtons bounds: w=272.000000, h=120.000000, x=24.000000, y=138.000000
viewButtons frame: w=272.000000, h=120.000000, x=0.000000, y=374.000000

The only difference I see from the initial to final is the viewButtons bounds origin.y, but if I try setting that, things get messed up - the buttons suddenly appear at the top of the screen. 我看到的从开始到结束的唯一区别是viewButtons界限origin.y,但是如果我尝试进行设置,事情就会搞砸了-按钮突然出现在屏幕顶部。 The button bounds are wide enough. 按钮边界足够宽。

What am I missing? 我想念什么?

UPDATED: I was missing the fact that I'd set up struts and a spring in IB for the enclosing view, which was fighting with the code I had setting the frame of the view. 更新:我错过了在IB中为封闭视图设置支柱和弹簧的事实,这与我设置视图框架的代码发生了冲突。 I removed the code to set the frame, letting IB do the work, and fiddled with the offsets for the buttons. 我删除了设置框架的代码,让IB完成工作,并摆弄了按钮的偏移量。 Not the prettiest solution, but I need to release it. 不是最漂亮的解决方案,但我需要发布它。

Moving your buttons shouldn't result in the modification of the "tappable" area of your button. 移动按钮不应导致修改按钮的“可敲击”区域。 The only reason that I can think that would cause something like this to occur are: 我认为会导致这种情况发生的唯一原因是:

  1. You have a transparent view covering parts of your buttons after rotation. 旋转后,您有一个透明的视图覆盖了部分按钮。 If you do have transparent views, make their background color red and see what happens after rotation. 如果确实具有透明视图,请将其背景颜色设为红色,然后查看旋转后会发生什么。

  2. If your buttons aren't children of the main view, turn on the "Clips Subviews" setting in the xib file or turn on the clipsToBounds property in code of the parent view of the button. 如果您的按钮不是主视图的子级,请在xib文件中打开“ Clips Subviews”设置,或在按钮的父视图的代码中打开clipsToBounds属性。 If your buttons are clipped during rotation, this could be another reason for your issue. 如果您的按钮在旋转过程中被夹住,这可能是造成您问题的另一个原因。

Let me know if any of this helps. 让我知道这是否有帮助。

This is not really an explanation for why you are getting that behavior but you will probably have better luck subclassing UIView, putting the layout code in there, and then using the UIView subclass in your view controller. 这并不是真正解释为什么会出现这种行为,但是运气更好的是可以继承UIView,将布局代码放在其中,然后在视图控制器中使用UIView子类可能会更好。 I animate buttons a quite a bit in my own app and subclassing UIView has led to the smallest amount of head scratching with regard to rotation. 我在自己的应用程序中对按钮进行了很多动画处理,子类化UIView导致旋转时头部刮擦的次数最少。

… Your viewButtons.origin.y issue may be related to how you get the screen dimensions. …您的viewButtons.origin.y问题可能与如何获取屏幕尺寸有关。 Maybe. 也许。 Try this 尝试这个

UIView *rootView = [[[UIApplication sharedApplication] keyWindow] 
                                   rootViewController].view;
CGRect originalFrame = [[UIScreen mainScreen] bounds];
CGRect adjustedFrame = [rootView convertRect:originalFrame fromView:nil];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM