6

フェイスブックのようなサイドメニューのあるアプリを作りました。それ自体にビューを追加するルートビューコントローラーがあります。ユーザーが「メニュー」ボタンを押すと、ビューがスライドしてメニューが表示されます。

私の問題は、ビューが最初にロードされたときに、 UINavBar が本来よりも約 20 ピクセル程度低いように見えることです。(下の画像は、モーダル水平反転であるため、中心が少しずれて見えます)

ここに画像の説明を入力

その後、自動的に調整され、モーダル遷移が完了するとステータス バーのすぐ下に移動します。

ここに画像の説明を入力

これは、「メニュー」ボタンを押したときに何が起こるかのスクリーンショットです。トップビューを右にスライドします

ここに画像の説明を入力

上の画像でわかるように、左矢印と右矢印のフレームの背景を赤に設定して、クリック可能/タップ可能な領域がどこにあるかを確認できるようにしています。青い線を描いた別の画像があり、青い線以上をクリックすると右矢印がトリガーされません。左側の同じ一般領域をクリックすると、メニュー ボタンがトリガーされます。シミュレーターとモバイル デバイスの両方でこれを再現できます (そのため、ボタンを太く指しているわけではありません)。

ここに画像の説明を入力

ナビゲーションバーが想定よりも低くロードされているため、iPhoneはまだその位置にあると考えているため、UIButtonフレーム内をクリックすると、メニューがトリガーされ、矢印セレクターがトリガーされないようです。矢印の真ん中を直接タップすると、矢印セレクターがトリガーされますが、画像のほんの少し外側では、矢印セレクターはトリガーされません。

これが私のRootViewControllerviewDidLoadです

AppointmentViewController *appointmentViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"AppointmentViewController"];
NSLog(@"B: %@",NSStringFromCGRect(appointmentViewController.view.frame));
self.navController = [[UINavigationController alloc] initWithRootViewController:appointmentViewController];
NSLog(@"B2: %@",NSStringFromCGRect(appointmentViewController.view.frame));
NSLog(@"Nav Bounds: %@",NSStringFromCGRect(self.navController.view.frame));
NSLog(@"Bounds: %@",NSStringFromCGRect(self.contentView.bounds));
self.navController.view.frame = self.contentView.bounds;
NSLog(@"Nav Bounds2: %@",NSStringFromCGRect(self.navController.view.frame));
[self addShadowToMenu];
[self.contentView addSubview:self.navController.view];

RootViewController ログ

2012-04-30 12:24:44.533 My-App[19929:fb03] B: {{0, 20}, {320, 460}}
2012-04-30 12:24:44.535 My-App[19929:fb03] B2: {{0, 20}, {320, 460}}
2012-04-30 12:24:44.535 My-App[19929:fb03] Nav Bounds: {{0, 0}, {320, 480}}
2012-04-30 12:24:44.535 My-App[19929:fb03] Bounds: {{0, 0}, {320, 460}}
2012-04-30 12:24:44.535 My-App[19929:fb03] Nav Bounds2: {{0, 0}, {320, 460}}

AppointmentViewController

self.title = [dataObj.preferences objectForKey:@"appts_name_plural"];
self.navigationItem.title = self.title;
dayView = [[APCalendarDayView alloc] initWithCalendarView:(APCalendarView *)self];
APListView = [self.storyboard instantiateViewControllerWithIdentifier:@"AppointmentListView"];
APListView.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];


SideMenuView *myDelegate = [[SideMenuView alloc] init];
[self setSideMenuDelegate:myDelegate];
//set the delegate's currentViewController property so that we can add a subview to this View. 
[sideMenuDelegate setCurrentViewController:self];

UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *today = [[UIBarButtonItem alloc] initWithTitle:@"Today" style:UIBarButtonItemStyleBordered target:nil action:@selector(todayPressed)];
NSArray *appointmentNavigationItems = [[NSArray alloc] initWithObjects:@"Day",@"List",@"Month", nil];
navcontrol = [[UISegmentedControl alloc] initWithItems:appointmentNavigationItems];
[navcontrol setSegmentedControlStyle:UISegmentedControlStyleBar];
[navcontrol addTarget:self action:@selector(appointmentNavigationClicked:) forControlEvents:UIControlEventValueChanged];
[navcontrol setSelectedSegmentIndex:0];
UIBarButtonItem *segmentItems = [[UIBarButtonItem alloc] initWithCustomView:navcontrol];

NSArray *items = [NSArray arrayWithObjects:today,flexSpace,segmentItems, flexSpace, nil];
[appointmentToolbar setItems:items animated:NO];
[appointmentToolbar setAutoresizesSubviews:YES];


[[self.view superview] addSubview:myDelegate.view];
[self setViewSizeOffset:(appointmentToolbar.bounds.size.height)];

カレンダーDayView

- (void)addSubviewsToHeaderView:(UIView *)headerView
{
    const CGFloat kChangeMonthButtonWidth = 46.0f;
    const CGFloat kChangeMonthButtonHeight = 44.0f;
    const CGFloat kMonthLabelWidth = 215.0f;
    const CGFloat kHeaderVerticalAdjust = 7.f;

    // Header background gradient
    UIImageView *backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Kal.bundle/kal_grid_background.png"]];
    CGRect imageFrame = headerView.frame;
    imageFrame.origin = CGPointZero;
    backgroundView.frame = imageFrame;
    [headerView addSubview:backgroundView];
    [backgroundView setAutoresizesSubviews:YES];
    [backgroundView setAutoresizingMask:UIViewAutoresizingFlexibleWidth];

    // Create the previous month button on the left side of the view
    CGRect previousMonthButtonFrame = CGRectMake(self.left, 0, kChangeMonthButtonWidth, kChangeMonthButtonHeight);
    UIButton *previousMonthButton = [[UIButton alloc] initWithFrame:previousMonthButtonFrame];
    [previousMonthButton setBackgroundColor:[UIColor redColor]];
    [previousMonthButton setImage:[UIImage imageNamed:@"Kal.bundle/kal_left_arrow.png"] forState:UIControlStateNormal];
    previousMonthButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
    previousMonthButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
    [previousMonthButton addTarget:self action:@selector(showPreviousDay) forControlEvents:UIControlEventTouchUpInside];
    //[previousMonthButton setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin];
    [headerView addSubview:previousMonthButton];

    // Draw the selected month name centered and at the top of the view
    CGRect monthLabelFrame = CGRectMake((self.frame.size.width/2.0f) - (kMonthLabelWidth/2.0f), kHeaderVerticalAdjust, kMonthLabelWidth, kMonthLabelHeight);
    headerTitleLabel = [[UILabel alloc] initWithFrame:monthLabelFrame];
    headerTitleLabel.backgroundColor = [UIColor clearColor];
    headerTitleLabel.font = [UIFont boldSystemFontOfSize:22.f];
    headerTitleLabel.textAlignment = UITextAlignmentCenter;
    headerTitleLabel.textColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"Kal.bundle/kal_header_text_fill.png"]];
    headerTitleLabel.shadowColor = [UIColor whiteColor];
    headerTitleLabel.shadowOffset = CGSizeMake(0.f, 1.f);
    //[self setHeaderTitleText:[logic selectedMonthNameAndYear]];

    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"E, MMM dd, yyyy"];   
    headerTitleLabel.text = [dateFormatter stringFromDate:dataObj.activeDate];
    [headerView addSubview:headerTitleLabel];

    // Create the next month button on the right side of the view
    CGRect nextMonthButtonFrame = CGRectMake(self.frame.size.width - kChangeMonthButtonWidth, 0, kChangeMonthButtonWidth, kChangeMonthButtonHeight);
    UIButton *nextMonthButton = [[UIButton alloc] initWithFrame:nextMonthButtonFrame];
    nextMonthButton.frame = nextMonthButtonFrame;
    [nextMonthButton setImage:[UIImage imageNamed:@"Kal.bundle/kal_right_arrow.png"] forState:UIControlStateNormal];
    [nextMonthButton setBackgroundColor:[UIColor redColor]];
    nextMonthButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
    nextMonthButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
    [nextMonthButton addTarget:self action:@selector(showFollowingDay) forControlEvents:UIControlEventTouchUpInside];
    //[nextMonthButton setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
    [headerView addSubview:nextMonthButton];
}

UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0.f, 0.f, self.frame.size.width, kHeaderHeight)];
    headerView.backgroundColor = [UIColor grayColor];
    [self addSubviewsToHeaderView:headerView];
    [headerView setAutoresizesSubviews:YES];
    [headerView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
    [self addSubview:headerView];
    [self bringSubviewToFront:headerView];

さらに下に移動するheaderViewと、赤い領域の任意の場所を選択して、矢印セレクターをトリガーできます。ただし、Apple のカレンダーと一致させ、ナビゲーション バーのすぐ下に配置したいと考えています。

ナビゲーション バーが上部のheaderViewタップをブロックしている理由を知っている人はいますか? 明確にするために、ブロックされている headerView の部分は、青い線の下から上にあります。赤い背景のUIButtonにはフレームに関連付けられたアクションがあるため、イベントをトリガーする必要がありますが、ナビゲーション バーが の半分UIButtonをタップの受信からブロックしているように見えます。

4

1 に答える 1

1

この動作は、UIWindow がナビゲーション バー フレームと一致するタッチを伝播していないという事実によるものです。この動作をオーバーライドする唯一の方法は、UIWindow をサブクラス化し、hitTest: メソッドをオーバーライドすることです。これにより、このエリアでのタッチを検出し、適切なレスポンダーに転送できます。

これは、画面上の任意の場所のタッチに応答するカスタムUIWindowサブクラスを示すサンプル プロジェクトです。

于 2012-04-30T20:40:41.920 に答える