【iOS】AssistiveTouch熱鍵按鈕

AssistiveTouch熱鍵按鈕

介紹

  • 這是一個(gè)掛再界面上的控件,支持自由拖動(dòng) isPanMoview 通過這個(gè)屬性進(jìn)行設(shè)置
  • 這個(gè)按鈕就是類似于蘋果的AssistiveTouch熱鍵按鈕一樣 可以保留在界面之上

使用

  • 在使用的時(shí)候,要注意的是你把他加在在了哪一個(gè)視圖上,這會(huì)直接影響到使用的效果
  • 創(chuàng)建的時(shí)候,首先要注意的就是 setClickBlock 里面的事情 我們看到的效果 都是手動(dòng)設(shè)置的
  • 我們往里面添加 的時(shí)候 要注意調(diào)用 [- addViewToHotView:] 這個(gè)方法來添加

代碼

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;        // 點(diǎn)擊的時(shí)候調(diào)用的block

@property(nonatomic, assign) BOOL isPanMoview;                  // 是否支持拖動(dòng)(默認(rèn)為NO)
@property(nonatomic, assign) BOOL isRotate;                     // 點(diǎn)擊的時(shí)候是否hot要旋轉(zhuǎn)45°
@property(nonatomic, assign) CGFloat rotate;                    // 旋轉(zhuǎn)的度數(shù) (默認(rèn)為 45°)
@property(nonatomic, assign) CGFloat gapMax;                    // hot按鈕與添加的按鈕之間的間隙 (默認(rèn)為 20)
@property(nonatomic, assign) CGFloat gapMin;                    // 添加的按鈕之間的間隙 (默認(rèn)為 8)


/**
 *  創(chuàng)建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;


/**
 *  移動(dòng)hotView到某個(gè)位置
 *
 *  @param point 左上角的位置點(diǎn)
 */
- (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內(nèi)的條件應(yīng)該為,當(dāng)觸摸點(diǎn)point超出藍(lán)色部分,但在黃色部分時(shí)
    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;
}


////重寫該方法后可以讓超出父視圖范圍的子視圖響應(yīng)事件
//- (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



///////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////
/////////////// 以上為內(nèi)部內(nèi) 以方便做按鈕超出范圍的時(shí)候 可以有點(diǎn)擊事件
///////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////



@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;
}

// 開發(fā)者自由定義的按鈕之類的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;
}


// 拖轉(zhuǎn)手勢(shì)的處理事件
- (void)panGestureAction:(UIPanGestureRecognizer *)sender{
    
    if (!self.isPanMoview) {
        return ;
    }
    
    
    if(sender.state==UIGestureRecognizerStateBegan){
        netTranslation = sender.view.frame.origin;
        
    }
    
    //得到拖的過程中的xy坐標(biāo)
    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);

    
    //狀態(tài)結(jié)束,保存數(shù)據(jù)
    if(sender.state==UIGestureRecognizerStateEnded){
        [self makeViewInSuper:sender.view];
        
        self.orginFrame = sender.view.frame;
        netTranslation = self.orginFrame.origin;
    }
}




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

// 熱鍵的點(diǎn)擊事件
- (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];
        
    }
    
    // 設(shè)置點(diǎn)擊的時(shí)候 有旋轉(zhuǎn)的效果
    if (self.isRotate) //如果需要 就旋轉(zhuǎn)
    [UIView animateWithDuration:0.5 animations:^{
        
        if (self.hotPlace.selected) {
            self.hotPlace.transform = CGAffineTransformMakeRotation(self.rotate);
        }else{
            self.hotPlace.transform = CGAffineTransformIdentity;
        }
    }];
    
    // block的調(diào)用
    if (self.clickBlock) {
        self.clickBlock(self,sender);
    }
}


////判斷某個(gè)點(diǎn)在不在 某個(gè)視圖上
//+ (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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,940評(píng)論 25 709
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,190評(píng)論 4 61
  • 第二期羅偉思維導(dǎo)圖早讀會(huì) 時(shí)間:5月14日 完成:14/28(第14天/共28天) 主題:時(shí)間管理工具,紙,電子工...
    一天一世界閱讀 255評(píng)論 0 0
  • 辣椒媽媽 思維導(dǎo)圖 許多父母都抱怨自己的孩子整天無所事事,不喜歡學(xué)習(xí),只喜...
    辣椒媽媽育兒課堂閱讀 826評(píng)論 1 3
  • 這向陽的臉 陰影里都是滴落的外水 你一半的生命給予朝南的江山 一半的生命在云霧里轉(zhuǎn) 時(shí)間的大桶里裝滿健忘的酒 誰還...
    楊沐云舒閱讀 369評(píng)論 2 5

友情鏈接更多精彩內(nèi)容