zoukankan      html  css  js  c++  java
  • ios新手开发——toast提示和旋转图片加载框

    不知不觉自学ios已经四个月了,从OC语法到app开发,过程虽然枯燥无味,但是结果还是挺有成就感的,在此分享我的ios开发之路中的小小心得~废话不多说,先上我们今天要实现的效果图:

    有过一点做APP经验的都知道,提示框和等待加载框一直是APP首当其中的效果,ios不像android一样,自带toast和progressbarDialog,所以在做ios开发的时候,我首先想到了先封装这两个基础控件~当然网上的资源数不胜数,但是博主抱着一颗自主研究的精神,做出的效果也不错,也已适配了所有iphone型号和版本.望大家多多支持~

    YPXToastView实现

    接触过安卓开发的ios开发者可能对待toast这么个东西很不陌生,它主要是一种轻量级的提示,代替了复杂的对话框,有的显示在中间,有的显示在屏幕下方,当然,这些都是根据需求而来的.废话不多说,首先清理一下我们实现这个toast的一些必要思路:

    1.实现的基础控件------UILabel封装

    2.弹出的时间和透明度变化设置

    3.显示的位置调整

     一.UILabel的封装

    首先我们想要实现一下这个效果,首当其冲的肯定想到UILabel,那么接下来就是对UILabel的封装了,首先我们创建一文件继承UIlabel,然后写好要对外暴露的方法:

     1 @interface YPXToastView : UILabel
     2 
     3 {
     4     @public
     5     CGFloat screenWidth,screenHeight;
     6     int _corner;
     7     int _duration;
     8 }
     9 
    10 @property(assign,nonatomic)int corner;
    11 @property(assign,nonatomic)int duration;
    12 
    13 
    14 -(void)showToastViewWithText:(NSString *)text andDuration:(int)duration andParentView:(UIView *)parentView;
    15 
    16 -(void)showToastViewWithText:(NSString *)text andParentView:(UIView *)parentView;
    17 
    18 -(void)showToastViewWithText:(NSString *)text andDuration:(int)duration andCorner:(int)corner andParentView:(UIView *)parentView;
    19 
    20 +(void)showToastViewWithText:(NSString *)text andDuration:(int)duration andParentView:(UIView *)parentView;
    21 
    22 +(void)showToastViewWithText:(NSString *)text andParentView:(UIView *)parentView;
    23 
    24 +(void)showToastViewWithText:(NSString *)text andDuration:(int)duration andCorner:(int)corner andParentView:(UIView *)parentView;
    25 
    26 -(void)setBackgroundWithColor:(UIColor *)color;
    27 
    28 @end

    定义了四个全局变量,两个属性,分别制定了提示框的圆角和时间.方法中定义了三个类方法,和四个实例方法,主要是因为我们在使用时并不想实例化一次我们的提示框,所有的实例方法中抽出了三个类方法方便用户调用.

    下面我们来看内部主要方法实现:

     1  
     2 
     3 /**
     4  *  新建UI
     5  *
     6  *  @param str 要显示的文本
     7  */
     8 -(void)createUIByText:(NSString *)str{
     9     self.textAlignment = NSTextAlignmentCenter;
    10     self.backgroundColor = [UIColor colorWithRed:00 green:00 blue:00 alpha:0.5];
    11     self.alpha = 0.8;
    12     self.text=str;
    13     self.font = [UIFont systemFontOfSize:14];
    14     self.textColor=[UIColor whiteColor];
    15     NSDictionary *attributes = @{NSFontAttributeName:[UIFont systemFontOfSize:self.font.pointSize],};
    16     CGSize textSize = [self.text boundingRectWithSize:CGSizeMake(100, 100) options:NSStringDrawingTruncatesLastVisibleLine attributes:attributes context:nil].size;;
    17     self.frame=CGRectMake(screenWidth/2-(textSize.width*1.7)/2, screenHeight*0.5,textSize.width*1.7,
    18                                textSize.height*2);
    19     self.layer.cornerRadius = _corner;
    20     self.clipsToBounds = YES;
    21 }
    22 
    23 -(void)setBackgroundWithColor:(UIColor *)color{
    24     self.backgroundColor =color;
    25 }
    26 
    27 
    28 /**
    29  *  初始化测量数据
    30  */
    31 -(void)caculateSize{
    32     screenWidth=[UIScreen mainScreen].bounds.size.width;
    33     screenHeight=[UIScreen mainScreen].bounds.size.height;
    34 }

    方法一目了然,指定了UILabel的居中方式和背景,并设置属性让其宽度自适应,涉及到一些简单的frame计算,主要是定位于屏幕中间,宽度设为文本宽度的1.7倍,看起来比较适中.y点主要就是屏幕高度的一半,理应减去文本的高度的一半,但是博主在这偷个懒,并没有计算label的高度,所以就不赘述了~~

     二.弹出的时间和透明度变化设置

    原理很简单,就是设定了一个animateWithDuration的block回调,然后设置label的透明度和时间,具体实现如下:

    /**
     *  显示toast
     *
     *  @param parentView <#parentView description#>
     */
    -(void)showToastByParentView:(UIView *)parentView{
        [parentView addSubview:self];
        //animateWithDuration可以控制label显示持续时间
        [UIView animateWithDuration:_duration animations:^{
            self.alpha = 1.0;
        } completion:^(BOOL finished){
            [self removeFromSuperview];
        }];
    }

    默认时间为1秒,思路很清晰,先添加进我们的parentView中,然后指定时间后移除.

    到此,我们的YPXToastView已经全部完成,其实内部逻辑主要是对UILabel的定制,思路简单,但是对于ios开发之路的封装思想有很大的帮助.调用时只需要一行代码:

    [YPXToastView showToastViewWithText:@"已开启" andDuration:3 andCorner:5 andParentView:self.view];

    调用方便简洁,以后测试就不需要用NSLog了嘿嘿~

    YPXLoddingView实现

    相信在ios的开发中少不了加载等待框的开发,毕竟原生系统中貌似没有这样的对话框,我们在访问网络或者读取数据时可能需要给用户一个等待回馈,这里就用到了我们的等待加载.上面的gif中提供了两种等待加载框的样式,一种是自定义图片的旋转,顺时针或者逆时针,另一种是使用系统的UIActivityIndicatorView,使用大的加载Loadding.具体开发思路如下:

    1.继承UIView通过添加UIImageView和UILabel来组合实现

    2.控制UIImageView的旋转以及UIlabel的三个点的动态效果

    3.显示和隐藏

    一.UIView的封装

    通过效果我们可以一目了然的知道,实现这个控件至少需要一个UIImageView(或者UIActivityIndicatorView)和UILabel,一个提供加载图片,一个提供加载文本,组合方式为竖直方向,然后设置背景的透明度.具体.h文件如下:

    #import <UIKit/UIKit.h>
    
    @interface YPXLoaddingView : UIView
    
    {
        @public
        int num;
        CGFloat angle;
        BOOL isShowLoadding;
        UIImageView * imageView;
        UILabel * label;
        CGFloat width;
        CGFloat x;
        CGFloat y,screenWidth,screenHeight;
        UIView * _parentView;
        NSString * _text;
        NSTimer * _timer;
        UIActivityIndicatorView * _activityView;
        UIView * view;
    }
    
    @property(retain,nonatomic)NSTimer * timer;
    @property(copy,nonatomic) NSString * text;
    @property(retain,nonatomic) UIActivityIndicatorView * activityView;
    
    -(void)showLoaddingViewWithText:(NSString *) string;
    
    -(void)dismissLoaddingView;
    
    -(instancetype)initWithParentView:(UIView *) parentView;
    
    +(id)initWithParentView:(UIView *) parentView;
    
    -(BOOL)isShowing;
    
    -(void)showLoaddingView;
    
    -(void)showLoaddingViewWithStyle:(int)style;
    
    -(void)showLoaddingViewWithText:(NSString * )text andStyle:(int)style;
    
    @end

    定义了一些必要的属性,包括计时器和显示文本等,主要功能为show开头的方法,style应该是个枚举类型,但是博主目前还没有写过枚举类,所以直接引用0和1来指定使用图片还是系统的菊花加载.看完.h我们来看看具体的UIView代码实现:

     1  
     2 
     3 /**
     4  *  计算一些必要尺寸
     5  *
     6  *  @param parentView <#parentView description#>
     7  */
     8 -(void)caculatSizeWithTarget:(UIView *) parentView
     9 {
    10     screenWidth=[UIScreen mainScreen].bounds.size.width;
    11     screenHeight=[UIScreen mainScreen].bounds.size.height;
    12     width=screenWidth*0.3;
    13     x= screenWidth/2-width/2;
    14     y= screenHeight/2-width/2;
    15     angle=0;
    16     num=0;
    17     isShowLoadding=NO;
    18     _parentView=parentView;
    19     
    20 }
    21 
    22 /**
    23  *  创建loadding视图
    24  */
    25 -(void)creatLoaddingView
    26 {
    27     view=[[UIView alloc]init];
    28     view.frame=CGRectMake(0, 0, screenWidth, screenHeight);
    29     
    30     imageView=[[UIImageView alloc]init];
    31     imageView.frame=CGRectMake(width/2-width*0.5/2,15, width*0.5,width*0.4);
    32     imageView.clipsToBounds=YES;
    33     imageView.layer.rasterizationScale=[UIScreen mainScreen].scale;
    34     [imageView setImage:[UIImage imageNamed:@"loadding.png"]];
    35     
    36     _activityView=[[UIActivityIndicatorView alloc]initWithFrame:CGRectMake(width/2-width*0.55/2,15, width*0.55,width*0.45)];
    37     _activityView.activityIndicatorViewStyle=UIActivityIndicatorViewStyleWhiteLarge;
    38     
    39     
    40     label=[[UILabel alloc]init];
    41     label.textColor=[UIColor whiteColor];
    42     label.font=[UIFont systemFontOfSize:14];
    43     int y2=imageView.frame.size.height+(width-imageView.frame.size.height)/2;
    44     label.frame=CGRectMake(0,y2, width, 20);
    45     label.textAlignment=NSTextAlignmentCenter;
    46     
    47 }

    手动布局,我们指定了imageview和label的frame,通过一系列计算,把imageview设为UIView中上部,并留出四周的边距,看起来更亲切自然一点.label的位置根据imageview的frame来指定,这样就可以完成适配避免在不同屏幕上显示不同的问题.完场上述代码,一个初步的静态效果已经生成,剩下的就是添加动画;

    二.UIImageView旋转动画以及UILabel点点动态展示

    imageview的动画添加很简单,因为我们只是涉及一点点的旋转动画,其中并没有加速度变化,读者若是想要添加,可以自己尝试一下.旋转动画的实现方式有两种:

    一种是用animateWithDuration来动态的旋转一定角度,然后通过延时来改变旋转的速率,好处是简单,但是缺点也很明显,在5s中动画显得僵硬,并伴随着一点点的卡顿,如下是第一种动画方案的代码:

     1 /**
     2  *  开启loadding动画
     3  */
     4 - (void)startAnimation
     5 {
     6     if(isShowLoadding==YES){
     7         CGAffineTransform endAngle = CGAffineTransformMakeRotation(angle * (M_PI / -180.0f));
     8         [UIView animateWithDuration:0.03f delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
     9             imageView.transform =endAngle;
    10         } completion:^(BOOL finished) {
    11             if(angle==360){
    12                 angle=0;
    13             }
    14             if(angle==0||angle==360){
    15                 label.text=[_text stringByAppendingString:@"..."];
    16             }else if(angle==90){
    17                 label.text=_text;
    18             }else if(angle==180){
    19                 label.text=[_text stringByAppendingString:@"."];
    20             }else if(angle==270){
    21                 label.text=[_text stringByAppendingString:@".."];
    22             }
    23             angle += 10;
    24             
    25             [self startAnimation];
    26         }];
    27     }
    28     
    29 }

    通过改变imageview的角度来旋转图片的方式,使用block回调中的角度关系,我们可以动态的设置提示文本省略号的动态展示.因为实现效果有点卡顿,所以博主采用了第二种实现方式,代码如下:

     1 /**
     2  *  启动计数定时器
     3  */
     4 -(void)UpdateText
     5 {
     6     num++;
     7     if (num>4) {
     8         num=0;
     9     }
    10     if(num==0||num==4){
    11        label.text=[_text stringByAppendingString:@"..."];
    12     }else if(num==1){
    13        label.text=_text;
    14     }else if(num==2){
    15        label.text=[_text stringByAppendingString:@"."];
    16     }else if(num==3){
    17         label.text=[_text stringByAppendingString:@".."];
    18     }
    19 
    20 }
    21 
    22 /**
    23  *  给imageView添加动画
    24  *
    25  *  @param imageView imageview
    26  *
    27  *  @return imageview
    28  */
    29 + (UIImageView *)rotateImageView:(UIImageView *)imageView
    30 {
    31     CABasicAnimation *animation = [ CABasicAnimation
    32                                    animationWithKeyPath: @"transform" ];
    33     animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
    34     
    35     //围绕Z轴旋转,垂直与屏幕
    36     animation.toValue = [ NSValue valueWithCATransform3D:
    37                          CATransform3DMakeRotation(M_PI, 0.0, 0.0, 1.0) ];
    38     animation.duration = 0.5;
    39     //旋转效果累计,先转180度,接着再旋转180度,从而实现360旋转
    40     animation.cumulative = YES;
    41     animation.repeatCount = 10000;
    42     
    43     [imageView.layer addAnimation:animation forKey:nil];
    44     return imageView;
    45 }

    采用CABasicAnimation的动画效果可以达到动画流畅度的完美展示,优点就是增加了旋转性能,缺点就是没有像animateWithDuration那样有动画的回调,这样我们就没有办法动态的去改变label的提示文本,所以细心的读者会发现,博主前面的.h文件中已经申明了一个定时器,那么这个定时器的作用是用来干嘛的呢?我们通过启动定时器,来动态的刷新label的提示文本达到一种动态展示的效果,这种思路在安卓里也同样适用.

    完成了我们的图片旋转,基本上这个功能已经完成了百分之八十,剩下就是显示和隐藏了;

    三.显示和隐藏

    前面介绍.h文件申明的时候,已经把本控件的所有调用方法已经列出来了,其中包含了一系列的.show方法,因为loadding这种控件,我们可能需要对其状态进行判断,而且可能在网络请求中调用多次,为了不浪费内存,我们在这里提倡使用单例模式,并初始化一个Loadding在ViewDidLoad中.后期调用只需要show和dismiss即可,下面我们来看具体的show和dismiss的方法实现:

     1 /**
     2  *  显示loadding.默认文本为 "正在加载"
     3  */
     4 -(void)showLoaddingView
     5 {
     6     if(isShowLoadding==YES){
     7         return;
     8     }
     9     if(_text==nil||[_text isEqualToString:@""]){
    10         _text=@"正在加载";
    11     }
    12     label.text=_text;
    13     isShowLoadding=YES;
    14     angle=0;
    15     self.hidden=NO;
    16     [self addSubview:imageView];
    17     [self addSubview:label];
    18     [view addSubview:self];
    19     [_parentView addSubview:view];
    20     [YPXLoaddingView rotateImageView:imageView];
    21     _timer=[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(UpdateText) userInfo:nil repeats:YES];
    22 
    23 }
    24 
    25 -(void)showLoaddingViewWithStyle:(int)style
    26 {
    27     if(style==0){//菊花加载
    28         if(isShowLoadding==YES){
    29             return;
    30         }
    31         if(_text==nil||[_text isEqualToString:@""]){
    32 
    33              _text=@"正在加载";
    34          }
    35         label.text=_text;
    36         isShowLoadding=YES;
    37         angle=0;
    38         self.hidden=NO;
    39         [self addSubview:_activityView];
    40         [self addSubview:label];
    41         [imageView removeFromSuperview];
    42         [_activityView startAnimating];
    43         [view addSubview:self];
    44         [_parentView addSubview:view];
    45         _timer=[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(UpdateText) userInfo:nil repeats:YES];
    46 
    47     }else{//旋转图片加载
    48         [self showLoaddingView];
    49     }
    50 
    51 }
    52 
    53 /**
    54  *  显示loadding
    55  *
    56  *  @param string 显示的文本
    57  */
    58 -(void)showLoaddingViewWithText:(NSString *) string
    59 {
    60     _text=string;
    61     [self showLoaddingView];
    62 }
    63 
    64 
    65 -(void)showLoaddingViewWithText:(NSString *)text andStyle:(int)style{
    66     _text=text;
    67     [self showLoaddingViewWithStyle:style];
    68 }
    69  
    70 
    71 /**
    72  *  消失loadding
    73  */
    74 -(void)dismissLoaddingView
    75 {
    76     self.hidden=YES;
    77     isShowLoadding=NO;
    78     [_timer invalidate];
    79     [imageView.layer removeAllAnimations];
    80     [_activityView stopAnimating];
    81     [view removeFromSuperview];
    82 }

    总体来说show方法中就是单纯的控制了imageview和_activityView通过style来隐藏和显示,思路很简单,再次不做赘述.dismiss中只需要移除我们的view就好,非常简单,同时不要忘记stop我们的_activityView以及关闭定时器就好.

    致此,所有的代码实现已经完成,我们在需要调用的地方首先实例化一次,然后使用show和dismiss即可.

    总结

    ios开发总体来说还算顺风顺水,因为对安卓有一定的基础,学习oc等面向对象的语法不免要快一点,但是ios中对于控件的方法并不是很多,甚至某些安卓一行代码就能实现的功能,ios需要好多行,这就是一个语言的魅力所在,当然,在自学ios的过程中我会不断的通过写博客的方式来提升自己的水平,在新手开发道路中,希望我能雨你们同行,谢谢读者的支持~~大笑
     
     


    下载地址:http://download.csdn.net/detail/qq_16674697/9622230

    作者:yangpeixing

    QQ:313930500

    CSND地址:http://blog.csdn.net/qq_16674697/article/details/53172388

    转载请注明出处~谢谢~

  • 相关阅读:
    [LeetCode]题解(python):136-Single Number
    [LeetCode]题解(python):135-Candy
    [LeetCode]题解(python):134-Gas Station
    [LeetCode]题解(python):133-Clone Graph
    [LeetCode]题解(python):132-Palindrome Partitioning II
    [LeetCode]题解(python):131-Palindrome Partitioning
    [LeetCode]题解(python):130-Surrounded Regions
    [LeetCode]题解(python):129-Sum Root to Leaf Numbers
    [LeetCode]题解(python):128-Longest Consecutive Sequence
    [LeetCode]题解(python):127-Word Ladder
  • 原文地址:https://www.cnblogs.com/teamblog/p/yangpeixing.html
Copyright © 2011-2022 走看看