【问题标题】:Making a button persistent across all view controllers使按钮在所有视图控制器中持久化
【发布时间】:2013-07-19 11:12:30
【问题描述】:

我想在我的应用程序的右下角有一个永久按钮。在所有视图转换期间,按钮应保持静态。我无法决定将按钮添加到哪个视图。我知道该按钮应该存储在 AppDelegate 中,但我不知道将它添加到除窗口之外的其他视图是否有意义。将它添加到窗口的一个缺点是,当后台运行应用程序(即电话)时,添加的状态栏填充将向下推窗口。一般来说,将它添加到窗口似乎是一个 hacky 解决方案——有什么想法吗?

【问题讨论】:

  • 如果您发现任何问题,请发布解决方案。我遇到了同样的情况。
  • “在所有视图转换期间,按钮应保持静止”是什么意思?这是否意味着即使从视图发生过渡,按钮也不应该移动?或者按钮应该在转换之前和之后的位置相同。
  • @D-Nice,你有解决办法吗???

标签: ios uiview uiviewcontroller uiwindow


【解决方案1】:

是的,将它添加到 UIWindow 会非常麻烦和挑剔。

故事板

如果您使用 Storyboards 和 iOS 5.0 及更高版本,您应该能够使用容器视图并执行以下操作:

这是另一张图,展示了第一个 View Controller 的结构,相当简单:

左侧的视图控制器有一个容器,然后是一个将按钮放在其顶部的视图。该容器指示导航控制器(直接在右侧)应该出现在其自身中,这种关系由=([])=> 箭头(正式称为embed segue)表示。最后,导航控制器将其根视图控制器定义到右侧。

总而言之,第一个视图控制器在容器视图中煎饼,按钮在顶部,所以里面发生的一切都必须让按钮在顶部。

使用 childViewControllers

又名。 “我讨厌故事板和小狗”模式

使用与 Storyboard 版本类似的结构,您可以创建带有按钮的基本视图控制器,然后在下面添加将成为应用程序新“根”的视图。

为了清楚起见,我们将持有按钮的视图控制器称为FakeRootViewController,而实际上,该视图控制器将成为应用程序的根:RootViewController。所有后续的视图控制器甚至都不知道FakeRootViewController 在其他所有人之上。

FakeRootViewController.m

// The "real" root
#import "RootViewController.h"

// Call once after the view has been set up (either through nib or coded).
- (void)setupRootViewController
{
    // Instantiate what will become the new root
    RootViewController *root = [[RootViewController alloc] <#initWith...#>];

    // Create the Navigation Controller
    UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:root];

    // Add its view beneath all ours (including the button we made)
    [self addChildViewController:nav];
    [self.view insertSubview:nav.view atIndex:0];
    [nav didMoveToParentViewController:self];
}

AppDelegate.m

#import "FakeRootViewController.h"

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    FakeRootViewController *fakeRoot = [[FakeRootViewController alloc] <#initWith...#>];

    self.window.rootViewController = fakeRoot;
    [self.window makeKeyAndVisible];

    return YES;
}

这样,您可以享受在窗口上插入按钮的所有好处,而不会感到内疚和“我真的应该成为一名程序员吗?”它引起的。

【讨论】:

  • 我没有使用故事板或界面构建器——所有的 ui 代码都是以编程方式添加的。我很难理解图像背后的原理。是否有一个包含按钮的容器 UIView 以及所有其他内容的子视图?
  • @D-Nice 我添加了另一张图片来更好地解释它,如果我可以用childViewControllers写一个全代码示例,我会更新
  • 我喜欢这个概念。我已经实现了它,但按照我的理解,导航栏应该继续由RootViewController. 管理关于如何做到这一点的任何想法?谢谢!
  • 我不明白你在问什么,你想让FakeRootViewController 处理导航栏吗?
  • 所以现在我在 AppDelegate 中创建 FakeRootViewController,然后使用 self.navigationController = [[UINavigationController alloc] initWithRootViewController:fakeRoot];self.window.rootViewController = self.navigationController; 跟进它,我得到了按钮覆盖,但后来我失去了导航栏配置它RootViewController. 我试图弄清楚如何维护我在RootViewController 开始的原始导航栏,并且只保留FakeRootViewController 的按钮覆盖
【解决方案2】:

您可能有 1 个主“根”视图控制器,而所有其他视图控制器都可能是子视图控制器,它们的视图作为子视图。然后他们将拥有自己的内容,并且按钮将位于“根”视图控制器中。但这看起来就像把它放在窗口一样粗略和hacky,而且可能不太方便。

【讨论】:

    【解决方案3】:

    我使用这个按钮:

    @interface UIPopUpButton : UIImageView <UIPopoverControllerDelegate, UIActionSheetDelegate>
    {
        UIPopoverController* popoverController;
        Class popoverClass;
    }
    
    - (id) initWithPoint: (CGPoint) point;
    - (void) touchesBegan: (NSSet*) touches
                withEvent: (UIEvent*) event;
    
    + (id) buttonAtPoint: (CGPoint) point;
    + (id) buttonAtOriginalPoint;
    + (void) unhighlight;
    + (void) bringButtonToFront;
    
    @property (nonatomic, retain) UIPopoverController* popoverController;
    @property (nonatomic, assign) Class popoverClass;
    
    @end
    
    
    #import "UIPopUpButton.h"
    
    @implementation UIPopUpButton
    
    static UIPopUpButton* button = nil;
    static CGPoint originalPoint;
    
    @synthesize popoverClass;
    @synthesize popoverController;
    
    + (id) buttonAtPoint: (CGPoint) point
    {
        if (button == nil)
        {
            button = [[UIPopUpButton alloc] initWithPoint: point];
            originalPoint = point;
            button.popoverClass = [UIPopoverController class];
        }
        else
        {
            button.frame = CGRectMake(point.x, point.y, button.frame.size.width, button.frame.size.height);
        }
    
        return button;
    }
    
    + (id) buttonAtOriginalPoint
    {
        return [self buttonAtPoint: originalPoint];
    }
    
    + (void) unhighlight
    {
        button.highlighted = NO;
    }
    
    + (void) bringButtonToFront
    {
        [[UIApplication sharedApplication].keyWindow addSubview: [self buttonAtOriginalPoint]];
    }
    
    - (id) initWithPoint: (CGPoint) point
    {
        UIImage* image1 = [UIImage imageNamed: @"topbutton.png"];
        UIImage* image2 = [UIImage imageNamed: @"topbutton.png"];
    
        if ((self = [super initWithImage: image1
                        highlightedImage: image2]))
        {
            self.userInteractionEnabled = YES;
            self.frame = CGRectMake(point.x, point.y, self.frame.size.width, self.frame.size.height);
            self.multipleTouchEnabled = NO;
        }
    
        return self;
    }
    
    - (BOOL) isAppCurrStatus
    {
        return ([DevToolsClientController sharedInstance].statusOfRootViewController == FrontEndApplication);
    }
    
    - (void) touchesBegan: (NSSet*) touches withEvent: (UIEvent*) event
    {
        UITouch* touch = [touches anyObject];
    
        if(touch.view == self)
        {
            if (self.popoverController == nil)
            {
                if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
                {
                    UIActionSheet* actionSheet = [[UIActionSheet alloc] initWithTitle: @"Please choice operation:"
                                                                             delegate: self
                                                                    cancelButtonTitle: nil
                                                               destructiveButtonTitle: nil
                                                                    otherButtonTitles: nil];
                    [actionSheet addButtonWithTitle: @"Cancel"];
                    actionSheet.cancelButtonIndex = 0;
                    [actionSheet addButtonWithTitle: @"Button 1"];
    
                    actionSheet.actionSheetStyle = UIActionSheetStyleDefault;
                    [actionSheet setTag: 0];
                    [actionSheet setDelegate: self];
                    [actionSheet showInView: [self superview]];
                    [actionSheet release];
                    [actions release];
                }
                else
                {
                    PopoverMenuController* contentViewController = [[PopoverMenuController alloc] init];
                    self.popoverController = [[UIPopoverController alloc] initWithContentViewController: contentViewController];
                    popoverController.delegate = self;
                    [popoverController presentPopoverFromRect: CGRectMake(10.0f, 10.0f, 5.0f, 5.0f)
                                                       inView: self
                                     permittedArrowDirections: UIPopoverArrowDirectionAny
                                                     animated: YES];
                    contentViewController.popoverController = self.popoverController;
                    [contentViewController reloadData];
                }
            }
            else
            {
                [self.popoverController dismissPopoverAnimated:YES];
                self.popoverController = nil;
            }
        }
    
        [super touchesBegan: touches withEvent: event];
    }
    
    
    
    #pragma mark UIActionSheetDelegate implementation
    
    -(void) actionSheet: (UIActionSheet*) actionSheet clickedButtonAtIndex: (NSInteger) buttonIndex
    {
        NSNumber* indexAction = [[NSNumber alloc] initWithInt: buttonIndex - 1];
    
    }
    
    - (void) runAction: (NSNumber*) indexAction
    {
        [DevToolsPopoverMenuController runAction: [indexAction integerValue]];
    }
    
    #pragma mark -
    #pragma mark UIPopoverControllerDelegate implementation
    
    - (void) popoverControllerDidDismissPopover: (UIPopoverController*) thePopoverController
    {
        if (self.popoverController != nil)
        {
            self.popoverController = nil;
        }
    }
    
    - (BOOL) popoverControllerShouldDismissPopover: (UIPopoverController*) thePopoverController
    {
        //The popover is automatically dismissed if you click outside it, unless you return NO here
        return YES;
    }
    
    @end
    

    呼叫:

         [UIPopUpButton bringButtonToFront];
    

    我的按钮总是在顶部。

    【讨论】:

      【解决方案4】:

      尝试继承 UIViewController 类并使用按钮制作自己的类

      【讨论】:

        【解决方案5】:

        创建一个包含按钮的单例对象,以便所有视图控制器都可以引用它并将其添加到他们的子视图或直接将其添加到窗口。

        SomeClass.h
        @property (nonatomic) UIButton *yourButton;
        +(SomeClass*)sharedSomeClass;
        
        
        SomeClass.m
        
        @synthesize yourButton = _yourButton;
        
        -(id)init
        {
        self = [super init];
        if(self)
        {
         _yourButton = [UIButton new];
        //Other settings you want for your button
        }
        return self;
        }
        
        +(SomeClass)sharedSomeClass
        {
         static SomeClass *sharedSomeClass;
         if (!sharedSomeClass)
          sharedSomeClass = [[super allocWithZone:nil]init];
        
           return sharedSomeClass;
        }
        
        +(void)allocWithZone:(NSZone*)zone
        {
         return [self sharedSomeClass];
        }
        

        如果你喜欢,你可以像这样直接访问窗口:

        UIWindow *mainwindow = [[[UIApplication sharedApplication]delegate]window];
        

        将 SomeClass.h 导入您的视图控制器,并从任何地方访问按钮

        #import "SomeClass.h"
        
        SomeClass *someClass = [SomeClass sharedSomeclass];
        UIButton *localButton = someClass.yourButton;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-05-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-02-22
          相关资源
          最近更新 更多