zoukankan      html  css  js  c++  java
  • iOS开发——项目篇—高仿百思不得姐 05——发布界面、发表文字界面、重识 bounds、frame、scrollView

    加号界面(发布模块)

    一、点击加号modal出发布模块,创建控件,布局控件
    1)使用xib加载view,如果在viewDidLoad创建控件并设置frame 那么self.view 的宽高 拿到的是xib的大小

    2)如果在viewDidLayouSubviews布局子控件 那么self.view 的宽高 拿到的是屏幕的宽高(这里不推荐 最好在设置frame时 直接用屏幕宽高设置frame)

    3)创建按钮,自定义按钮,布局按钮

    - (instancetype)initWithFrame:(CGRect)frame
    {
        if (self = [super initWithFrame:frame]) {
            self.titleLabel.textAlignment = NSTextAlignmentCenter;
            self.titleLabel.font = [UIFont systemFontOfSize:15];
            [self setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        }
        return self;
    }
    
    - (void)layoutSubviews
    {
        [super layoutSubviews];
        
        self.imageView.y = 0;
        self.imageView.centerX = self.width * 0.5;
        
        self.titleLabel.width = self.width;
        self.titleLabel.y = CGRectGetMaxY(self.imageView.frame);
        self.titleLabel.x = 0;
        self.titleLabel.height = self.height - self.titleLabel.y;
    }

    二、添加动画
    1)Core Animation
    利用苹果自带的动画方法
    动画只能作用在CALayer
    无法监听到动画的中间值(frame值并不能改变 只是个假象)

    2)pop
    facebook出品的动画框架
    动画能作用在任何对象
    能监听到动画的中间值(真正的修改frame值)

            // 动画
            POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPViewFrame];
            anim.fromValue = [NSValue valueWithCGRect:CGRectMake(buttonX, buttonY - CHGScreenH, buttonW, buttonH)];
            anim.toValue = [NSValue valueWithCGRect:CGRectMake(buttonX, buttonY, buttonW, buttonH)];
            anim.springSpeed = 10;
            anim.springBounciness = 10;
            // CACurrentMediaTime()获得的是当前时间
            anim.beginTime = CACurrentMediaTime() + [self.times[i] doubleValue];
            [button pop_addAnimation:anim forKey:nil];

    3)示例程序
    poping
    LeamCube
    github中搜索Animation

    三、动画细节
    1、 弹出动画(使用pop)
    代码优化


    2、退出动画
    禁止用户的交互等小细节

        // 禁止交互
        self.view.userInteractionEnabled = NO;

    点击按钮、取消按钮、屏幕三种不同情况

    四、modal发段子等子控制器
    1)选择正确的控制器去modal 选择的控制器不能是已经消亡的,一般用窗口的根控制器(此处根控制器为tabbarVC)
    2)将跳转(发段子等功能)封装到一个block内,区分点击按钮、取消按钮、屏幕三种不同情况下有不同功能,也就是说点击按钮(发段子、发视频等)才需要有跳转的功能,其他两个不需要

    #pragma mark - 退出动画
    - (void)exit:(void (^)())task
    {
        // 禁止交互
        self.view.userInteractionEnabled = NO;
        
        // 让按钮执行动画
        for (int i = 0; i < self.buttons.count; i++) {
            CHGPublishButton *button = self.buttons[i];
            
            POPBasicAnimation *anim = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerPositionY];
            anim.toValue = @(button.layer.position.y + CHGScreenH);
            // CACurrentMediaTime()获得的是当前时间
            anim.beginTime = CACurrentMediaTime() + [self.times[i] doubleValue];
            [button.layer pop_addAnimation:anim forKey:nil];
        }
        
        
        // 让标题执行动画
        POPBasicAnimation *anim = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerPositionY];
        anim.toValue = @(self.sloganView.layer.position.y + CHGScreenH);
        // CACurrentMediaTime()获得的是当前时间
        anim.beginTime = CACurrentMediaTime() + [self.times.lastObject doubleValue];
        
        CHGWeakSelf;
        [anim setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
            [weakSelf dismissViewControllerAnimated:NO completion:nil];
            
            // 可能会做其他事情
    //        if (task) task();
            !task ? : task();
        }];
        [self.sloganView.layer pop_addAnimation:anim forKey:nil];
    }

    三种不同情况

    #pragma mark - 点击
    - (void)buttonClick:(XMGPublishButton *)button
    {
        [self exit:^{
            // 按钮索引
            NSUInteger index = [self.buttons indexOfObject:button];
            switch (index) {
                case 2: { // 发段子
                    // 弹出发段子控制器
                    CHGPostWordViewController *postWord = [[CHGPostWordViewController alloc] init];
                    [self.view.window.rootViewController presentViewController:[[CHGNavigationController alloc] initWithRootViewController:postWord] animated:YES completion:nil];
                    break;
                }
                    
                case 0:
                    XMGLog(@"发视屏");
                    break;
                    
                case 1:
                    XMGLog(@"发图片");
                    break;
                    
                default:
                    XMGLog(@"其它");
                    break;
            }
        }];
    }
    
    - (IBAction)cancel {
        [self exit:nil];
    }
    
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        [self exit:nil];
    }

    五、发段子界面
    1)textView 默认会换行,但是没有占位文字,需自定义,封装成工具类、小框架
    2)自定义带占位文字的textView
    方法一 drawRect 画在一个矩形框内

    .h

    #import <UIKit/UIKit.h>
    
    @interface CHGPlaceholderTextView : UITextView
    /** 占位文字 */
    @property (nonatomic, copy) NSString *placeholder;
    /** 占位文字颜色 */
    @property (nonatomic, strong) UIColor *placeholderColor;
    @end

    .m

    #import "CHGPlaceholderTextView.h"
    
    @implementation CHGPlaceholderTextView
    
    - (instancetype)initWithFrame:(CGRect)frame
    {
        if (self = [super initWithFrame:frame]) {
            
            self.font = [UIFont systemFontOfSize:17];
            
            self.textColor = [UIColor blackColor];
            
            self.placeholderColor = [UIColor grayColor];
            
            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChange:) name:UITextViewTextDidChangeNotification object:self];
            
        }
        return self;
    }
    
    - (void)textDidChange:(NSNotification *)note
    {
        // 会重新调用drawRect:方法
        [self setNeedsDisplay];
    }
    
    - (void)dealloc
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
    
    
    - (void)drawRect:(CGRect)rect {
        
        // 如果有文字,就直接返回,不需要画占位文字
        //    if (self.text.length || self.attributedText.length) return;
        if (self.hasText) return;
        
        // 属性
        NSMutableDictionary *attrs = [NSMutableDictionary dictionary];
        attrs[NSFontAttributeName] = self.font;
        attrs[NSForegroundColorAttributeName] = self.placeholderColor;
        
        rect.origin.x = 5;
        rect.origin.y = 8;
        rect.size.width -= 2 * rect.origin.x;
        
        [self.placeholder drawInRect:rect withAttributes:attrs];
        
    }
    
    // 若是不写  进入发表界面 占位文字不能随textView上下滚动
    - (void)layoutSubviews
    {
        [super layoutSubviews];
        
        [self setNeedsDisplay];
    }
    
    #pragma mark - setter
    
    - (void)setPlaceholderColor:(UIColor *)placeholderColor
    {
        _placeholderColor = placeholderColor;
        [self setNeedsDisplay];
    }
    
    - (void)setPlaceholder:(NSString *)placeholder
    {
        _placeholder = placeholder;
        [self setNeedsDisplay];
    }
    
    - (void)setFont:(UIFont *)font
    {
        [super setFont:font];
        [self setNeedsDisplay];
    }
    
    - (void)setText:(NSString *)text
    {
        [super setText:text];
        [self setNeedsDisplay];
    }
    
    
    - (void)setAttributedText:(NSAttributedString *)attributedText
    {
        [super setAttributedText:attributedText];
        [self setNeedsDisplay];
    }
    
    @end

    方法二 添加label

    .h

    #import <UIKit/UIKit.h>
    
    @interface CHGPlaceholderTextView2 : UITextView
    /** 占位文字 */
    @property (nonatomic, copy) NSString *placeholder;
    /** 占位文字颜色 */
    @property (nonatomic, strong) UIColor *placeholderColor;
    @end

    .m

    #import "CHGPlaceholderTextView2.h"
    
    
    @interface CHGPlaceholderTextView2 ()
    
    /** 占位文字label */
    @property (nonatomic, weak) UILabel *placeholderLabel;
    
    @end
    
    @implementation CHGPlaceholderTextView2
    
    - (instancetype)initWithFrame:(CGRect)frame
    {
        if (self = [super initWithFrame:frame]) {
            // 创建label
            UILabel *placeholderLabel = [[UILabel alloc] init];
            placeholderLabel.numberOfLines = 0;
            [self addSubview:placeholderLabel];
            self.placeholderLabel = placeholderLabel;
            
            // 设置默认字体
            self.font = [UIFont systemFontOfSize:15];
            
            // 设置默认颜色
            self.placeholderColor = [UIColor grayColor];
            
            // 使用通知监听文字改变
            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChange:) name:UITextViewTextDidChangeNotification object:self];
        }
        return self;
    }
    
    - (void)textDidChange:(NSNotification *)note
    {
        self.placeholderLabel.hidden = self.hasText;
    }
    
    - (void)dealloc
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
    
    - (void)layoutSubviews
    {
        [super layoutSubviews];
        
        self.placeholderLabel.x = 5;
        self.placeholderLabel.y = 8;
        self.placeholderLabel.width = self.width - 2 * self.placeholderLabel.x;
        [self.placeholderLabel sizeToFit];
    }
    
    #pragma mark - setter
    - (void)setPlaceholder:(NSString *)placeholder
    {
        _placeholder = [placeholder copy];
        
        self.placeholderLabel.text = placeholder;
        [self.placeholderLabel sizeToFit];
        //    [self setNeedsLayout];
    }
    
    - (void)setPlaceholderColor:(UIColor *)placeholderColor
    {
        _placeholderColor = placeholderColor;
        
        self.placeholderLabel.textColor = placeholderColor;
    }
    
    - (void)setFont:(UIFont *)font
    {
        [super setFont:font];
        
        self.placeholderLabel.font = font;
        [self.placeholderLabel sizeToFit];
        //    [self setNeedsLayout];
    }
    
    - (void)setText:(NSString *)text
    {
        [super setText:text];
        
        self.placeholderLabel.hidden = self.hasText;
    }
    
    - (void)setAttributedText:(NSAttributedString *)attributedText
    {
        [super setAttributedText:attributedText];
        
        self.placeholderLabel.hidden = self.hasText;
    }
    
    @end

    3)如何去除占位文字
    代理(不推荐)
    通知 (参考上面代码)
    4)设置占位文字颜色、字体、大小、普通内容、富文本内容、frame等属性
    默认的情况下
    重新设置的情况下(重写这五个属性的set方法,再重绘或者重新计算,frame重写layoutsubviews)
    5)拖拽时取消编辑,退出键盘
    设置竖直方向允许拖动,实现拖拽的代理方法控制退出键盘
    6)设置导航栏的属性 字体颜色等(layouIfNeeded强制刷新,可解决因为设置属性而影响到状态)

    六、三种刷新控件的方法

     // 重新刷新自己和子控件的所有内容(状态、尺寸)
     [tempView layoutIfNeeded];
     // 重新调用tempView的layoutSubviews(重新排布子控件的frame)
     [tempView setNeedsLayout];
     // 重新调用tempView的drawRect:方法(重新绘制tempView里面的内容,一般不包括子控件)
     [tempView setNeedsDisplay];

    七、重识bounds、scrollView

    1)bounds

    bounds 指的是控件矩形框的位置和尺寸
    bounds 是以自己内容(内部的子控件)的左上角为坐标原点


    y = 正数 子控件会往上
    y = 负数 子控件会往下

    2)frame

    frame 指的是控件矩形框的位置和尺寸
    frame 是以自己父控件的左上角为坐标原点

    3)bounds和frame的对比

    以下图为例子

    用绿色表示矩形框bounds(圈圈为坐标原点)

    用红色表示矩形框frame

    4)scrollView textView

    当控制器中有超过两个scrollView(或textView)时,那么系统会在第一个添加的scrollView(或textView)顶部添加一定的偏移量,若有导航控制器,偏移64,若没有,偏移20

    self.automaticallyAdjustsScrollViewInsets = NO;
        
    // 当你有超过1个scrollView的时候,建议你设置self.automaticallyAdjustsScrollViewInsets = NO;,然后自己根据需要去调整scrollView的inset

    5)scrollView常用的属性

        scrollView.contentSize; // 滚动范围(内容的尺寸)

        scrollView.contentInset; // 内边距

        scrollView.frame; // 以父控件内容的左上角为坐标原点,scrollView矩形框的位置和尺寸

        scrollView.bounds; // 以自己内容的左上角为坐标原点,scrollView矩形框的位置和尺寸

        scrollView.contentOffset; // 偏移量(scrollView.bounds.origin)

    将来的你会感谢今天如此努力的你! 版权声明:本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    解决UITableView中Cell重用机制导致内容出错的方法总结
    Hdu 1052 Tian Ji -- The Horse Racing
    Hdu 1009 FatMouse' Trade
    hdu 2037 今年暑假不AC
    hdu 1559 最大子矩阵
    hdu 1004 Let the Balloon Rise
    Hdu 1214 圆桌会议
    Hdu 1081 To The Max
    Hdu 2845 Beans
    Hdu 2955 Robberies 0/1背包
  • 原文地址:https://www.cnblogs.com/chglog/p/4798180.html
Copyright © 2011-2022 走看看