AssistiveTouch熱鍵按鈕

weixin_34037977發表於2016-07-20

AssistiveTouch熱鍵按鈕

介紹

  • 這是一個掛再介面上的控制元件,支援自由拖動 isPanMoview 通過這個屬性進行設定
  • 這個按鈕就是類似於蘋果的AssistiveTouch熱鍵按鈕一樣 可以保留在介面之上

使用

  • 在使用的時候,要注意的是你把他加在在了哪一個檢視上,這會直接影響到使用的效果
  • 建立的時候,首先要注意的就是 setClickBlock 裡面的事情 我們看到的效果 都是手動設定的
  • 我們往裡面新增 的時候 要注意呼叫 [- addViewToHotView:] 這個方法來新增

程式碼

HotView.h

//
//  HotView.h
//  TouGuApp
//
//  Created by tianshikechuang on 16/7/14.
//  Copyright © 2016年 tianshikechuang. All rights reserved.
//

#import <UIKit/UIKit.h>



@class HotView;
typedef void(^HotViewDidClick)(HotView * hotView,UIButton * button);




@interface HotView : UIView

@property(nonatomic, strong) HotViewDidClick clickBlock;        // 點選的時候呼叫的block

@property(nonatomic, assign) BOOL isPanMoview;                  // 是否支援拖動(預設為NO)
@property(nonatomic, assign) BOOL isRotate;                     // 點選的時候是否hot要旋轉45°
@property(nonatomic, assign) CGFloat rotate;                    // 旋轉的度數 (預設為 45°)
@property(nonatomic, assign) CGFloat gapMax;                    // hot按鈕與新增的按鈕之間的間隙 (預設為 20)
@property(nonatomic, assign) CGFloat gapMin;                    // 新增的按鈕之間的間隙 (預設為 8)


/**
 *  建立HotView
 *
 *  @param frame HotView的大小 位置
 *
 *  @return hotView
 */
+ (instancetype)hotViewWithFrame:(CGRect)frame;



+ (HotView *)showHotViewInView:(UIView *)view withFrame:(CGRect)frame;
+ (HotView *)showHotViewInkeyWindowTopWithFrame:(CGRect)frame;
+ (HotView *)showHotViewInVCTop:(UIViewController *)VC withFrame:(CGRect)frame;


/**
 *  移動hotView到某個位置
 *
 *  @param point 左上角的位置點
 */
- (void)moveHotViewTo:(CGPoint)point;



/**
 *  給展開的HotView新增檢視
 *
 *  @param View 要新增的檢視/Button
 */
- (void)addViewToHotView:(UIView *)button;



/**
 *  熱鍵圖片
 *
 *  @param image 熱鍵的背景圖片
 */
- (void)hotViewImage:(UIImage *)image;


@end

HotView.m

//
//  HotView.m
//  TouGuApp
//
//  Created by tianshikechuang on 16/7/14.
//  Copyright © 2016年 tianshikechuang. All rights reserved.
//

#import "HotView.h"


@interface OutRangeView : UIView

@end

@implementation OutRangeView


@end

@interface OutRangeButton : UIButton

@end

@implementation OutRangeButton


- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
    //if內的條件應該為,當觸控點point超出藍色部分,但在黃色部分時
    if (CGRectContainsPoint(self.bounds, point)){
        return YES;
    }else{
        for (UIView  * view in self.subviews) {
            if ([view isKindOfClass:[OutRangeView class]] && CGRectContainsPoint(view.bounds, [self convertPoint:point toView:view])){
                   return YES;
            }
        }
        
    }
    return NO;
}


////重寫該方法後可以讓超出父檢視範圍的子檢視響應事件
//- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
//    UIView *view = [super hitTest:point withEvent:event];
//    if (view == nil) {
//        for (UIView *subView in self.contentView.subviews) {
//            CGPoint tp = [subView convertPoint:point fromView:self.contentView];
//            if (CGRectContainsPoint(subView.bounds, tp)) {
//                view = subView;
//            }
//        }
//    }
//
//    return view;
//}

@end



///////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////
/////////////// 以上為內部內 以方便做按鈕超出範圍的時候 可以有點選事件
///////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////



@interface HotView ()

{
    CGPoint netTranslation;
}
@property(nonatomic, strong) OutRangeButton * hotButton;

@property(nonatomic, strong) UIButton * hotPlace;
@property(nonatomic, strong) UIView * contentView;


@property(nonatomic, assign) CGRect orginFrame;
@property(nonatomic, assign) CGRect screenFrame;

@property(nonatomic, assign) CGRect contentMinFrame;
@property(nonatomic, assign) CGRect contentMaxFrame;


@property(nonatomic, strong) UIPanGestureRecognizer * panGesture;
@property(nonatomic, strong) NSMutableArray * otherButs;


@end




@implementation HotView



+ (HotView *)showHotViewInkeyWindowTopWithFrame:(CGRect)frame{
    UIView * view = [UIApplication sharedApplication].keyWindow;
    return [self showHotViewInView:view withFrame:frame];
}


+ (HotView *)showHotViewInVCTop:(UIViewController *)VC withFrame:(CGRect)frame{
    UIView * view;
    if (VC.tabBarController) {
        view = VC.tabBarController.view;
    }else if (VC.navigationController){
        view = VC.navigationController.view;
    }else{
        view = VC.view;
    }
    return [self showHotViewInView:view withFrame:frame];
}


+ (HotView *)showHotViewInView:(UIView *)view withFrame:(CGRect)frame{
    HotView * hot = [HotView hotViewWithFrame:frame];
    [view addSubview:hot];
    return hot;
}


+ (instancetype)hotViewWithFrame:(CGRect)frame{
    return [[self alloc] initWithFrame:frame];
}





- (void)moveHotViewTo:(CGPoint)point{
    CGRect frame = self.frame;
    frame.origin = point;
    self.frame = frame;
    self.orginFrame = frame;
}

- (void)addViewToHotView:(UIView *)button{
    
    [self.otherButs addObject:button];
}

- (void)hotViewImage:(UIImage *)image{

    self.hotPlace = [[UIButton alloc] initWithFrame:self.hotButton.bounds];
    self.hotPlace.userInteractionEnabled = NO;
    [self.hotButton addSubview:self.hotPlace];
    [self.hotPlace setBackgroundImage:image forState:UIControlStateNormal];
}



- (instancetype)initWithFrame:(CGRect)frame{
    
    if (self = [super initWithFrame:frame]) {
        self.orginFrame = frame;
        self.screenFrame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
        CGFloat wdith = frame.size.width;
        self.contentMaxFrame = CGRectMake(0, -wdith, frame.size.width, wdith);
        self.contentMinFrame = CGRectMake(0, 0, frame.size.width, 0);
        
        self.gapMax = 20;
        self.gapMin = 8;
        self.isRotate = YES;
        self.rotate = M_PI_4;
        
        [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction)]];
        
        [self addSubview:self.hotButton];
        
        [self addGestureRecognizer:self.panGesture];
        
        self.otherButs = [NSMutableArray array];
    }
    return self;
}

- (OutRangeButton *)hotButton{
    
    if (!_hotButton) {
        _hotButton = [[OutRangeButton alloc] initWithFrame:self.bounds];
        _hotButton.backgroundColor = [UIColor colorWithRed:0.5 green:0.5 blue:0.50 alpha:0.5];
        _hotButton.layer.cornerRadius = self.bounds.size.width/2;
        _hotButton.layer.borderColor = [UIColor colorWithRed:0.8 green:0.8 blue:0.8 alpha:0.8].CGColor;
        _hotButton.layer.borderWidth = 5;
        [_hotButton addTarget:self action:@selector(hotButtonAction:) forControlEvents:UIControlEventTouchUpInside];
        
        self.contentView = [[OutRangeView alloc] initWithFrame:self.contentMinFrame];
//        self.contentView.backgroundColor = [UIColor grayColor];
        self.contentView.clipsToBounds = YES;
        [_hotButton addSubview:self.contentView];
 
    }
    return _hotButton;
}

// 開發者自由定義的按鈕之類的frame
- (void)layoutContentViews{
    
    
    __block CGFloat height;
    __block CGFloat width;
    [self.otherButs enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        
        UIView * view = obj;
        CGRect viewFrame = view.frame;
        
        if (idx == 0) {
            height = 0.001;
            width = viewFrame.size.width;
        }
        
        viewFrame.origin = CGPointMake(0, height);
        viewFrame.size = CGSizeMake(width, viewFrame.size.height);
        view.frame = viewFrame;
        height = height + viewFrame.size.height + self.gapMin;
        
        if ([obj isKindOfClass:[UIControl class]]) {
            [(UIControl *)view addTarget:self action:@selector(tapAction) forControlEvents:UIControlEventTouchUpInside];
        }else{
            [view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction)]];
        }
        
        [self.contentView addSubview:view];
        
    }];
    
    CGRect frame = self.contentMaxFrame;
    CGFloat orginW = self.orginFrame.size.width;
    frame.size = CGSizeMake(width, height + self.gapMin);
    frame.origin = CGPointMake((orginW - width)/2.0, - frame.size.height);
    self.contentMaxFrame = frame;
    self.contentView.frame = frame;
    
    
}


// 定死了的按鈕之類的frame
//- (void)layoutContentViews{
//    
//    int count = (int)self.otherButs.count;
//    CGRect frame = self.contentMaxFrame;
//    frame.size = CGSizeMake(frame.size.width, (frame.size.width + 10 )* count + 30);
//    frame.origin = CGPointMake(frame.origin.x, - frame.size.height);
//    self.contentMaxFrame = frame;
//    self.contentView.frame = frame;
//
//    CGSize equlSize = CGSizeMake(frame.size.width, frame.size.width);
//    [self.otherButs enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
//        
//        UIView * view = obj;
//        CGRect viewFrame;
//        viewFrame.origin = CGPointMake(0, idx * (equlSize.width + 10));
//        viewFrame.size = equlSize;
//        view.frame = viewFrame;
//        [view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction)]];
//        [self.contentView addSubview:view];
//        
//    }];
//    
//    
//}


- (UIPanGestureRecognizer *)panGesture{
    if (!_panGesture) {
        _panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureAction:)];
    }
    return _panGesture;
}


// 拖轉手勢的處理事件
- (void)panGestureAction:(UIPanGestureRecognizer *)sender{
    
    if (!self.isPanMoview) {
        return ;
    }
    
    
    if(sender.state==UIGestureRecognizerStateBegan){
        netTranslation = sender.view.frame.origin;
        
    }
    
    //得到拖的過程中的xy座標
    CGPoint translation=[sender translationInView:sender.view.superview];
    
    
    CGFloat x = translation.x + netTranslation.x;
    CGFloat y = translation.y + netTranslation.y;
    CGFloat w = self.orginFrame.size.width;
    CGFloat h = self.orginFrame.size.height;
    
    //平移圖片CGAffineTransformMakeTranslation
    sender.view.frame = CGRectMake(x, y , w, h);

    
    //狀態結束,儲存資料
    if(sender.state==UIGestureRecognizerStateEnded){
        [self makeViewInSuper:sender.view];
        
        self.orginFrame = sender.view.frame;
        netTranslation = self.orginFrame.origin;
    }
}




// 接觸到空白地方 就縮小到熱鍵
- (void)tapAction{
    [self hotButtonAction:self.hotButton];
}

// 熱鍵的點選事件
- (void)hotButtonAction:(UIButton *)sender{
    
    sender.selected = !sender.selected;
    self.hotPlace.selected = sender.selected;
    netTranslation = self.orginFrame.origin;
    
    if(sender.selected){
        
        [UIView animateWithDuration:0.3 animations:^{
            self.frame = self.screenFrame;
            self.hotButton.frame = self.orginFrame;
            self.contentView.frame = self.contentMaxFrame;
        }];
        
        [self layoutContentViews];
        
        [self removeGestureRecognizer:self.panGesture];
        [self.hotButton addGestureRecognizer:self.panGesture];
    }else{
        
        
        [UIView animateWithDuration:0.3 animations:^{
            self.contentView.frame = self.contentMinFrame;
            self.frame = self.orginFrame;
            self.hotButton.frame = self.bounds;
            [self setBackgroundColor:[UIColor clearColor]];
            
        } completion:^(BOOL finished) {
           
            [self.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
        }];
        
        [self addGestureRecognizer:self.panGesture];
        [self.hotButton removeGestureRecognizer:self.panGesture];
        
    }
    
    // 設定點選的時候 有旋轉的效果
    if (self.isRotate) //如果需要 就旋轉
    [UIView animateWithDuration:0.5 animations:^{
        
        if (self.hotPlace.selected) {
            self.hotPlace.transform = CGAffineTransformMakeRotation(self.rotate);
        }else{
            self.hotPlace.transform = CGAffineTransformIdentity;
        }
    }];
    
    // block的呼叫
    if (self.clickBlock) {
        self.clickBlock(self,sender);
    }
}


////判斷某個點在不在 某個檢視上
//+ (BOOL)point:(CGPoint)point isInView:(UIView *)view{
//    
//    
//    CGFloat x = point.x;
//    CGFloat y = point.y;
//    CGFloat w = view.frame.size.width;
//    CGFloat h = view.frame.size.height;
//
//    BOOL isOn = NO;
//    if (x > 0 && y > 0 && x < w && y < h) {
//        isOn = YES;
//    }
//    return isOn;
//}



- (void)makeViewInSuper:(UIView *)view{
    
    CGFloat x = view.frame.origin.x;
    CGFloat y = view.frame.origin.y;
    CGFloat w = view.frame.size.width;
    CGFloat h = view.frame.size.height;
    
    if (x < 0 && y < 0) {
        [UIView animateWithDuration:0.5 animations:^{
            view.frame = CGRectMake(5, 5 , w, h);
        }];
    }else if (x + w > view.superview.bounds.size.width && y + h > view.superview.bounds.size.height){
        
        [UIView animateWithDuration:0.5 animations:^{
            view.frame = CGRectMake(view.superview.bounds.size.width - w - 5, view.superview.bounds.size.height - h -5 , w, h);
        }];
        
    }else if (x < 0 && y + h > view.superview.bounds.size.height) {
        [UIView animateWithDuration:0.5 animations:^{
            view.frame = CGRectMake(5, view.superview.bounds.size.height - h -5 , w, h);
        }];
    }else if (x + w > view.superview.bounds.size.width && y < 0){
        
        [UIView animateWithDuration:0.5 animations:^{
            view.frame = CGRectMake(view.superview.bounds.size.width - w - 5, 5, w, h);
        }];
        
    }else if (x < 0) {
        [UIView animateWithDuration:0.5 animations:^{
            view.frame = CGRectMake(5, y , w, h);
        }];
        
    }else if (x + w > view.superview.bounds.size.width){
        
        [UIView animateWithDuration:0.5 animations:^{
            view.frame = CGRectMake(view.superview.bounds.size.width - w - 5, y, w, h);
        }];
        
    }else if (y < 0 ) {
        [UIView animateWithDuration:0.5 animations:^{
            view.frame = CGRectMake(x, 5 , w, h);
        }];
    }else if (y + h > view.superview.bounds.size.height){
        [UIView animateWithDuration:0.5 animations:^{
            view.frame = CGRectMake(x, view.superview.bounds.size.height - h -5 , w, h);
        }];
    }
    

}

@end

相關文章