IOS 文本滾動標籤效果(Objc/Swift)

實現效果

QQ20200521-200338-HD.gif

  • 實現原理:動畫改變文本的y座標,同時使用把移出父佈局的視圖立即移到父視圖的下方,使用一個臨時UIView來交替上下兩個視圖,達到利用的效果
  • 實現核心代碼如下:
    Object-c版本:
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

typedef void(^OnClickListener)(NSString* title);

@interface ScrollLabel : UILabel
@property(nonatomic,strong) UIView* parentView;
@property(nonatomic,strong) UIButton* upLabel;
@property(nonatomic,strong) UIButton* bottomLabel;
@property(nonatomic,copy) OnClickListener listener;

-(void) setTargetView:(UIView*) parentView withTitleArray:(NSMutableArray*)array;

-(void) setOnClickListener:(OnClickListener)listener;

-(void) start;

-(void) stop;

@end

NS_ASSUME_NONNULL_END

.m文件:

#import "ScrollLabel.h"
#import "UIView+Resize.h"

@interface  ScrollLabel()
@property(nonatomic,strong)NSMutableArray* titleArray;
@property(nonatomic,strong)NSTimer *timer;
@property(nonatomic,assign)NSInteger index;

@end

@implementation ScrollLabel

-(instancetype) init{
   if (self = [super init]) {
       
   }
   return self;
}

-(void) setTargetView:(UIView*) parentView withTitleArray:(NSMutableArray*)array{
   if (!parentView || !array || array.count == 0) {
       return;
   }
   self.titleArray = array;
   self.parentView = parentView;
   self.index = 0;
   
   self.upLabel = [[UIButton alloc] init];
   self.upLabel.backgroundColor = [UIColor greenColor];
   self.upLabel.tag = 21;
   [self.upLabel addTarget:self action:@selector(onClick:) forControlEvents:UIControlEventTouchUpInside];
   [self.upLabel setTitle:[array objectAtIndex:self.index] forState:UIControlStateNormal];
   self.upLabel.frame = CGRectMake(0, 0, parentView.frame.size.width,parentView.frame.size.height);
   self.index ++;
   
   self.bottomLabel = [[UIButton alloc] init];
   self.bottomLabel.tag = 22;
   [self.bottomLabel addTarget:self action:@selector(onClick:) forControlEvents:UIControlEventTouchUpInside];

   self.bottomLabel.frame = CGRectMake(0, self.upLabel.frame.size.height, parentView.frame.size.width,parentView.frame.size.height);
   [self.bottomLabel setTitle:[array objectAtIndex:self.index] forState:UIControlStateNormal];
   self.bottomLabel.backgroundColor = [UIColor brownColor];
   
   [self.parentView addSubview:self.upLabel];
   [self.parentView addSubview:self.bottomLabel];
   
}

-(void) onClick:(UIButton*) button{
   switch (button.tag) {
       case 21:
       case 22:
           if (self.listener) {
               self.listener(button.titleLabel.text);
           }
           break;
           
       default:
           break;
   }
}
-(void) setOnClickListener:(OnClickListener)listener{
   self.listener = listener;
}


-(void) start{
   if(self.titleArray.count == 1){
       return;
   }
   
   if (!self.timer) {
       self.timer = [NSTimer timerWithTimeInterval:3 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
       [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode];
   }
  
}
-(void) timerAction{
   [UIView transitionWithView:self.upLabel duration:2 * 0.5 options:UIViewAnimationOptionCurveEaseInOut animations:^{
       self.upLabel.tx_bottom = 0;
       [UIView transitionWithView:self.upLabel duration:2 * 0.5 options:UIViewAnimationOptionCurveEaseInOut animations:^{
           self.bottomLabel.tx_y = 0;
       } completion:^(BOOL finished) {
           self.upLabel.tx_y = self.parentView.tx_height;
           UIButton *tempLabel = self.upLabel;
           self.upLabel = self.bottomLabel;
           self.bottomLabel = tempLabel;
           self.index ++;
           NSString* title = [self.titleArray objectAtIndex:self.index % self.titleArray.count];
           [tempLabel setTitle:title forState:UIControlStateNormal];
       }];
   } completion:^(BOOL finished){
   }];
   
}

-(void) stop{
   if(self.timer){
       [self.timer invalidate];
       self.timer = nil;
   }
}

@end

分類文件:


#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface UIView (Resize)

/** 設置x值 */
@property (assign, nonatomic) CGFloat tx_x;
/** 設置y值 */
@property (assign, nonatomic) CGFloat tx_y;
/** 設置width */
@property (assign, nonatomic) CGFloat tx_width;
/** 設置height */
@property (assign, nonatomic) CGFloat tx_height;
/** 設置size */
@property (assign, nonatomic) CGSize  tx_size;
/** 設置origin */
@property (assign, nonatomic) CGPoint tx_origin;
/** 設置center */
@property (assign, nonatomic) CGPoint tx_center;
/** 設置center.x */
@property (assign, nonatomic) CGFloat tx_centerX;
/** 設置center.y */
@property (assign, nonatomic) CGFloat tx_centerY;
/** 設置bottom */
@property (assign, nonatomic) CGFloat tx_bottom;

@end




#import "UIView+Resize.h"

@implementation UIView (Resize)

- (CGFloat)tx_x {
    return self.frame.origin.x;
}

- (void)setTx_x:(CGFloat)tx_x {
    CGRect frame = self.frame;
    frame.origin.x = tx_x;
    self.frame = frame;
}

- (CGFloat)tx_y {
    return self.frame.origin.y;
}

- (void)setTx_y:(CGFloat)tx_y {
    CGRect frame = self.frame;
    frame.origin.y = tx_y;
    self.frame = frame;
}

- (CGFloat)tx_width {
    return self.frame.size.width;
}

- (void)setTx_width:(CGFloat)tx_width {
    CGRect frame = self.frame;
    frame.size.width = tx_width;
    self.frame = frame;
}

- (CGFloat)tx_height {
    return self.frame.size.height;
}

- (void)setTx_height:(CGFloat)tx_height {
    CGRect frame = self.frame;
    frame.size.height = tx_height;
    self.frame = frame;
}

- (CGSize)tx_size {
    return self.frame.size;
}

- (void)setTx_size:(CGSize)tx_size {
    CGRect frame = self.frame;
    frame.size = tx_size;
    self.frame = frame;
}

- (CGPoint)tx_origin {
    return self.frame.origin;
}

- (void)setTx_origin:(CGPoint)tx_origin {
    CGRect frame = self.frame;
    frame.origin = tx_origin;
    self.frame = frame;
}

- (CGPoint)tx_center {
    return self.center;
}

- (void)setTx_center:(CGPoint)tx_center {
    self.center = tx_center;
}

- (CGFloat)tx_centerX {
    return self.center.x;
}

- (void)setTx_centerX:(CGFloat)tx_centerX {
    CGPoint center = self.center;
    center.x = tx_centerX;
    self.center = center;
}

- (CGFloat)tx_centerY {
    return self.center.y;
}

- (void)setTx_centerY:(CGFloat)tx_centerY {
    CGPoint center = self.center;
    center.y = tx_centerY;
    self.center = center;
}

- (CGFloat)tx_bottom {
    return CGRectGetMaxY(self.frame);
}

- (void)setTx_bottom:(CGFloat)tx_bottom {
    CGRect frame = self.frame;
    frame.origin.y = tx_bottom - frame.size.height;
    self.frame = frame;
}


@end

  • 測試代碼:
self.textView2 = [[UIView alloc] initWithFrame:CGRectMake(30, 160, 240, 40)];
    self.textView2.backgroundColor = [UIColor grayColor];
    self.textView2.clipsToBounds = true;
    [self.view addSubview:self.textView2];
    
    self.scrollLabel = [[ScrollLabel alloc] init];
    NSMutableArray* array = [NSMutableArray arrayWithArray:self.texts];
    [self.scrollLabel setTargetView:self.textView2 withTitleArray:array];
    [self.scrollLabel setOnClickListener:^(NSString* title){
        NSLog(@"91--------:%@",title);
    }];
  • swift 文件:
import UIKit

class ScrollLabel: UIView {

    lazy var parentView : UIView = UIView.init();
    lazy var upLabel : UIButton = UIButton.init();
    lazy var bottom : UIButton = UIButton.init();
    lazy var titleArray:NSMutableArray = NSMutableArray.init();
    var index:NSInteger = 0;
    lazy var timer:Timer? = Timer.init()
    
    override init(frame: CGRect) {
        super.init(frame:frame)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    public func setTarget(_ parentView:UIView, withTitleArray array:NSMutableArray) ->Void {
        self.parentView = parentView
        self.titleArray = array
        
        self.upLabel.backgroundColor = UIColor.green;
        self.upLabel.tag = 21;
        self.upLabel.addTarget(self, action: #selector(onClickListener(btn:)), for:.touchUpInside)
        self.upLabel.setTitle(self.titleArray.object(at: self.index) as? String, for:.normal)
        self.upLabel.frame = CGRect.init(x: 0, y: 0, width: parentView.frame.size.width, height: parentView.frame.size.height)
    
        self.index += 1
       self.bottom.backgroundColor = UIColor.brown;
       self.bottom.tag = 22;
       self.bottom.addTarget(self, action: #selector(onClickListener(btn:)), for:.touchUpInside)
        self.bottom.setTitle(self.titleArray.object(at: self.index) as? String, for:.normal)
       self.bottom.frame = CGRect.init(x: 0, y: parentView.frame.size.height, width: parentView.frame.size.width, height: parentView.frame.size.height)
        
        parentView.addSubview(self.upLabel)
        parentView.addSubview(self.bottom)
    }
    
    
    @objc func onClickListener(btn : UIButton?)  {
        switch btn?.tag {
        case 21,22:
            NSLog("----")
            break;
        default:
            break;
        }
    }
    
    public func start() -> Void {
        if self.titleArray.count == 1 {
            return;
        }
        if self.timer == nil {
            
            self.timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(onFire), userInfo: nil, repeats: true);
                
            self.timer?.fire()
        }
        
        
    }
    
    @objc func onFire() -> Void {
        
        UIView.transition(with: self.upLabel, duration: 2 * 0.5, options: .curveEaseInOut, animations: {
            self.upLabel.tx_bottom = 0
            
            UIView.transition(with: self.upLabel, duration: 2 * 0.5, options: .curveEaseInOut, animations: {
                           
                           self.bottom.y = 0;
                           
                       }, completion: {_ in
                           self.upLabel.y = self.parentView.height;
                           let tempLabel = self.upLabel;
                           self.upLabel = self.bottom;
                           self.bottom = tempLabel;
                           self.index += 1;
                           let title = self.titleArray.object(at: self.index % self.titleArray.count) as? String
                           tempLabel.setTitle(title, for:.normal)
                       })
            
            
        }, completion: {_ in
        
        })
        
    }
    
    public func stop(){
        if(self.timer != nil){
            self.timer!.invalidate()
            self.timer = nil;
        }
        
    }
    
}

//UIView 的分類
extension UIView {
    // .x
    public var x: CGFloat {
        get {
            return self.frame.origin.x
        }
        set {
            var rect = self.frame
            rect.origin.x = newValue
            self.frame = rect
        }
    }
    
    // .y
    public var y: CGFloat {
        get {
            return self.frame.origin.y
        }
        set {
            var rect = self.frame
            rect.origin.y = newValue
            self.frame = rect
        }
    }
    
    // .maxX
    public var maxX: CGFloat {
        get {
            return self.frame.maxX
        }
    }
    
    // .maxY
    public var maxY: CGFloat {
        get {
            return self.frame.maxY
        }
    }
    
    // .centerX
    public var centerX: CGFloat {
        get {
            return self.center.x
        }
        set {
            self.center = CGPoint(x: newValue, y: self.center.y)
        }
    }
    
    // .centerY
    public var centerY: CGFloat {
        get {
            return self.center.y
        }
        set {
            self.center = CGPoint(x: self.center.x, y: newValue)
        }
    }
    
    // .width
    public var width: CGFloat {
        get {
            return self.frame.size.width
        }
        set {
            var rect = self.frame
            rect.size.width = newValue
            self.frame = rect
        }
    }
    
    // .height
    public var height: CGFloat {
        get {
            return self.frame.size.height
        }
        set {
            var rect = self.frame
            rect.size.height = newValue
            self.frame = rect
        }
    }
    
    public var tx_bottom:CGFloat{
        get {
            return self.frame.size.height
        }
        set {
            var rect = self.frame
            rect.origin.y = newValue - rect.size.height
            self.frame = rect
        }
    }
}

  • 測試例子
import UIKit


class ViewController: UIViewController {
    
    var scrollLabel:ScrollLabel?
    lazy var upLabel : UIButton = UIButton.init();

    override func viewDidLoad() {
        super.viewDidLoad()
        
        
        self.upLabel.backgroundColor = UIColor.green;
       self.upLabel.tag = 21;
       self.upLabel.addTarget(self, action: #selector(onClickListener(btn:)), for:.touchUpInside)
       self.upLabel.setTitle("start", for:.normal)
       self.upLabel.frame = CGRect.init(x: 10, y: 50, width: 100, height: 50)
        self.view.addSubview(upLabel)
        
        let parentView : UIView = UIView.init(frame: CGRect.init(x: 50, y: 160, width: 180, height: 40))
        self.view.addSubview(parentView)
        parentView.backgroundColor = UIColor.blue
        parentView.clipsToBounds = true
        
        let array:NSMutableArray = NSMutableArray.init(objects: "香辣肉絲","聽你講個故事","聽你唱首歌",
        "高考","大學","工作","生活")
        
        scrollLabel = ScrollLabel();
        scrollLabel?.setTarget(parentView, withTitleArray: array)
        
        
    }
    
    @objc func onClickListener(btn : UIButton?)  {
           switch btn?.tag {
           case 21,22:
            scrollLabel?.start()
               break;
           default:
               break;
           }
       }


}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章