如何正确添加和显示 UIView on tap

Posted

技术标签:

【中文标题】如何正确添加和显示 UIView on tap【英文标题】:How correct add and show UIView on tap 【发布时间】:2016-11-11 13:44:14 【问题描述】:

当我点击按钮时,我尝试显示复选标记(GitHub WVCheckMark)。这是代码,它仅在我第二次点击按钮时才起作用。

- (void)viewDidLoad 
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    mark = [[WVCheckMark alloc] init];//WithFrame:CGRectMake(50, 50, 100, 100)];
    mark.backgroundColor = [UIColor clearColor];

    //[mark setFrame:CGRectMake(100, 100, 100, 100)];
    //[self.view addSubview:mark];


- (IBAction) btnShow

    [mark setFrame:CGRectMake(100, 100, 100, 100)];
    [self.view addSubview:mark];
    [mark setNeedsDisplay];
    [mark updateConstraints];
    [mark setNeedsLayout];

    [mark start];

如果在 viewDidLoad 中使用 addSubview,这就是我想要的工作方式(点击并显示)。

调用这个方法没有帮助。

[mark setNeedsDisplay];
[mark updateConstraints];
[mark setNeedsLayout];

是否可以添加子视图并将其显示在一个代码位置?

完整代码

#import "ViewController.h"
#import "TestCheckmark-Swift.h"

@interface ViewController ()

@end

WVCheckMark *mark;

@implementation ViewController

- (void)viewDidLoad 
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    mark = [[WVCheckMark alloc] initWithFrame:CGRectMake(50, 50, 100, 100)];
    mark.backgroundColor = [UIColor clearColor];

    [mark setFrame:CGRectMake(100, 100, 100, 100)];
    //[self.view addSubview:mark];


- (IBAction) btnShow

    //[mark setFrame:CGRectMake(100, 100, 100, 100)];
    //[self.view addSubview:mark];
    [mark setNeedsDisplay];
    [mark updateConstraints];
    [mark setNeedsLayout];

    [mark start];


- (void)didReceiveMemoryWarning 
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.



@end

【问题讨论】:

btnShow 中调试。它被称为? (去掉三个 setNeed...updateCo...) 方法viewDidLoadviewWillAppearviewDidAppear是根据viewCont生命周期调用的,只要在viewDidAppear里面添加按钮,然后再应用任何代码。 @shallowThought 是的,当我第一次点击时调用 btnShow @vaibhav,是的,这个问题更多是为了了解 viewDidAppear 中发生了什么,并且可以在 btnShow 中这样做 我认为你声明标记的方式不正确,你能告诉我们那个代码吗? 【参考方案1】:

简答:OP 代码不需要在添加的视图上调用setNeedsDisplaysetNeedsLayoutupdateConstraints,但它确实需要在父视图上调用addSubview:,如[self.view addSubview:mark];

但更深入一点,看起来 GitHub 上的 WVCheckMark 是 UIView 的子类。这是一件好事,也很重要,因为这意味着我们可能可以指望一些从 UIView 继承的理想东西。

例如,.alpha 属性,这是一种改变可见性的好方法,而不会弄乱视图层次结构(添加和删除子视图)。 .alpha 的另一个优点是 -- 与 .hidden 不同 -- alpha 可以设置动画。

所以让我们在一个地方设置视图层次结构和框架。关键的想法 - 并且可能最混淆 OP 代码的想法 - 是调用addSubview:。懒惰地进行设置是确保我们在需要的时候只做一次的好方法。

- (WVCheckMark *)mark 
    WVCheckMark *mark = [self.view viewWithTag:64];  // 64 must be non-zero and unique amongst self.view subviews
    if (!mark) 
        mark = [[WVCheckMark alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
        mark.tag = 64;  // so we can find it later
        mark.backgroundColor = [UIColor clearColor];
        // start out invisible
        mark.alpha = 0.0;
        // important, addSubview, which is probably the main problem in the OP
        [self.view addSubview:mark];
    
    return mark;

现在,当您需要显示/隐藏该视图时,只需执行以下操作:

self.mark.alpha = 1.0;  // show
self.mark.alpha = 0.0;  // hide

由于该属性是可动画的,您可以像这样获得一点花哨的淡入淡出:

- (void)setMarkHidden:(BOOL)hidden animated:(BOOL)animated 
    NSTimeInterval duration = (animated)? 0.3 : 0.0;
    CGFloat alpha = (hidden)? 0.0 : 1.0;

    [UIView animateWithDuration:duration animations:^
        self.mark.alpha = alpha;
    ];

您可以丢弃所有其他与复选标记相关的代码,只需在按下按钮触发外观时执行此操作...

- (IBAction)pressed:(id)sender 
    [setMarkHidden:YES animated:YES];

【讨论】:

以上是关于如何正确添加和显示 UIView on tap的主要内容,如果未能解决你的问题,请参考以下文章

Swift - 如何将点击手势添加到 UIViews 数组?

为啥我的 UIView 中没有显示任何内容?

动态添加子视图 UIView 的正确方法

Runtime 实现 动态添加属性

如何将 circleView 进度添加到 UIView 扩展到所有 UIView?

Xamarin iOS Tap 事件通过最顶部的视图?