【iOS】AssistiveTouch热键按钮

AssistiveTouch热键按钮

介绍

  • 这是一个挂再界面上的控件,支持自由拖动 isPanMoview 通过这个属性进行设置
  • 这个按钮就是类似于苹果的AssistiveTouch热键按钮一样 可以保留在界面之上

使用

  • 在使用的时候,要注意的是你把他加在在了哪一个视图上,这会直接影响到使用的效果
  • 创建的时候,首先要注意的就是 setClickBlock 里面的事情 我们看到的效果 都是手动设置的
  • 我们往里面添加 的时候 要注意调用 [- addViewToHotView:] 这个方法来添加

代码

HotView.h

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

#import 



@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

你可能感兴趣的:(【iOS】AssistiveTouch热键按钮)