This is my sixth day of the August Challenge

preface

View top choices about bringSubviewToFront and View.Layer. zPosition

  1. The bringSubviewToFront method needs to be called when the interface hierarchy is refreshed;

  2. Using the view.layer.zPosition method will not get the view click event

Application scenarios

1. For example, put the date control at the top of the window

2. Hover button (support drag)

I, bringSubviewToFront

  • Place the date control at the top of the window

PGDatePickManager kunnan.blog.csdn.net/article/det…

@implementation PGDatePickManager (ios12)

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
        NSArray *selStringsArray = @[@"viewWillLayoutSubviews"];
        
// @"reloadRowsAtIndexPaths:withRowAnimation:", @"deleteRowsAtIndexPaths:withRowAnimation:", @"insertRowsAtIndexPaths:withRowAnimation:"];
        
        [selStringsArray enumerateObjectsUsingBlock:^(NSString *selString, NSUInteger idx, BOOL *stop) {
            NSString *mySelString = [@"sd_" stringByAppendingString:selString];
            
            Method originalMethod = class_getInstanceMethod(self.NSSelectorFromString(selString));
            Method myMethod = class_getInstanceMethod(self.NSSelectorFromString(mySelString));
            method_exchangeImplementations(originalMethod, myMethod);
        }];
    });
}
- (void)sd_viewWillLayoutSubviews{
    
    [self sd_viewWillLayoutSubviews];
    
        [UIApplication.sharedApplication.delegate.window bringSubviewToFront:self.view.superview];

}

Copy the code
  • listTableView
 [self.superview.window addSubview:self.listTableView];
    /// Avoid being obscured by other subviews
    [self.superview.window bringSubviewToFront:self.listTableView];
    CGRect frame = CGRectMake(CGRectGetMinX(self.frame), CGRectGetMaxY(self.frame), CGRectGetWidth(self.frame), 0);

    // Convert coordinates

   CGRect convertRect=  [self.superview convertRect:frame toView:self.superview.window];

    [self.listTableView setFrame:convertRect];
Copy the code

II. Change the display order of the same Layer

  • self.view.layer.zPosition
   self.view.layer.zPosition = MAXFLOAT; 999

Copy the code

Case III: Hover button (support drag)

Lower order related requirements for hover button:

1. When there is a record of “Goods to be shipped”, the button of “One-click Delivery” will be displayed

2. When there is a record of “goods to be received”, it will show the “one-click agent” button. Click the one-click agent: the distribution record of goods to be shipped will be updated as “received”.

3.1 the principle

1. BringSubviewToFront 2. Add motion gestures that can be dragged 3

    // Add a move gesture that can be dragged
    self.panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(dragAction:)];
    self.panGestureRecognizer.minimumNumberOfTouches = 1;
    self.panGestureRecognizer.maximumNumberOfTouches = 1;
    self.panGestureRecognizer.delegate = self;
    [self addGestureRecognizer:self.panGestureRecognizer];

Copy the code

3.2 usage

@property (strong.nonatomic) KNFrontV *  orangeView;




@end

@implementation QCTRecordViewController

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    
    [self.view bringSubviewToFront:self.orangeView];
    
    
    [self.orangeView layoutIfNeeded];
    
    self.orangeView.layer.cornerRadius =self.orangeView.height *0.5;

}

- (KNFrontV *)orangeView{
    if (nil == _orangeView) {
        KNFrontV *tmpView = [[KNFrontV alloc] initWithFrame:CGRectMake(0.0 , kAdjustRatio(53), kAdjustRatio(53))];
        
        
        _orangeView = tmpView;
        [self.view addSubview:_orangeView];
        
        __weak __typeof__(self) weakSelf = self;
        tmpView.button.titleLabel.numberOfLines = 0;
        tmpView.button.titleLabel.textAlignment = NSTextAlignmentCenter;

                tmpView.button.titleLabel.font = [UIFont systemFontOfSize:15.0];
        [tmpView.button setTitle:@" One click \n delivery" forState:UIControlStateNormal];// Delivery purchase \n Number of stores
        
        tmpView.backgroundColor =  rgb(255.54.87);
        //
        // tmpView.layer.cornerRadius = 14; // layoutsubview
        
        // Set image display mode 1:
// tmpView.imageView.image = [UIImage imageNamed:@"icon_dayin"];
        // Set image display mode 2:
        // [logoView.button setBackgroundImage:[UIImage imageNamed:@"logo1024"] forState:UIControlStateNormal];
        
        
        
        [_orangeView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.size.mas_equalTo(CGSizeMake(kAdjustRatio(53), kAdjustRatio(53)));
            
            make.right.offset(kAdjustRatio(- 20));
            
            make.bottom.offset(kAdjustRatio(- 90.));
            
        }];
        
        
        tmpView.clickDragViewBlock = ^(KNFrontV *dragView){
            
            
            [weakSelf setupclickDragViewBlock];
                        
            
        };
                
    }
    return _orangeView;
}

- (void)setupclickDragViewBlock{
    
    
}

Copy the code
  • The definition of KNFrontV
//
// KNFrontV.h
// Housekeeper
//
// Created by mac on 2021/5/6.
/ / Copyright © 2021 https://kunnan.blog.csdn.net/ All rights reserved.
//

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

// Drag the direction of the view
typedef NS_ENUM(NSInteger, KNDragDirection) {
    KNDragDirectionAny,          /**< Any direction */
    KNDragDirectionHorizontal,   /**< horizontal direction */
    KNDragDirectionVertical,     /**< Vertical direction */
};


@interface KNFrontV : UIView


/** can drag, default is YES YES, can drag NO, can not drag */
@property (nonatomic.assign) BOOL dragEnable;

/** The default value is within the scope of the superview's frame. If this value is set, it will be within the scope of the superview's frame. If not, it will be within the scope of the superview's frame. Set frame to 0,0,0,0 to indicate that the scope of activity is the default superview frame. To disable activity, set dragEnable to NO */
@property (nonatomic.assign) CGRect freeRect;

/** The drag direction (default: any)
@property (nonatomic.assign) KNDragDirection dragDirection;

/** A UIImageView is lazy to load inside the contentView. Developers can also add custom controls to this view. Note: It is best not to use both the internal imageView and button */
@property (nonatomic.strong) UIImageView *imageView;
/** A UIButton is lazy inside the contentView. Developers can also add custom controls to this view. Note: It is best not to use both the internal imageView and the button */
@property (nonatomic.strong) UIButton *button;
IsKeepBounds = YES, it will stick to the bounds automatically, and is the closest bounds isKeepBounds = NO, it will not stick to the bounds, it is free, Follow your finger anywhere, but do not drag it out of the given range frame */
@property (nonatomic.assign) BOOL isKeepBounds;
/** Click the callback block */
@property (nonatomic.copy) void(^clickDragViewBlock)(KNFrontV *dragView);
/** Start dragging the callback block */
@property (nonatomic.copy) void(^beginDragBlock)(KNFrontV *dragView);
/** Drag callback block */
@property (nonatomic.copy) void(^duringDragBlock)(KNFrontV *dragView);
/** End drag callback block */
@property (nonatomic.copy) void(^endDragBlock)(KNFrontV *dragView);

@end

NS_ASSUME_NONNULL_END

Copy the code

KNFrontV complete implementation see CSDN, blog.csdn.net/z929118967/…

Or follow the public number: iOS reverse

3.3 the use ofNSPredicateDetermine if a “goods to be received” record exists

1. When there is a record of "goods to be shipped", the "one-button delivery" button will be displayed. Click the "one-button delivery" button to realize the distribution record of goods to be shipped, and all updates to the goods to be received. To achieve the distribution of goods, are updated as "received" my order exists "to receive" record, show "one button to receive" button click one button to receive: to achieve the distribution of goods, are updated as "received" */
- (void) updateorangeView{
    //
    
    if(! [self isShoworangeView]){
        self.orangeView.hidden = YES;
        
    }else{[self orangeView];
        
        self.orangeView.hidden = NO;
        
        [self.orangeView.button setTitle:self.orangeViewM.showStr forState:UIControlStateNormal];// Delivery purchase \n Number of stores}} - (BOOL)isShoworangeView{
    
    self.orangeViewM = [KNFrontVM new];
    
    
    if(self.model.isLowerOrder){/ / at a lower level
// 1. When there is a record of "Goods to be shipped", the button of "one-click delivery" will be displayed
        
        NSPredicate* predicate = [NSPredicate predicateWithFormat:@"receivingState == %@".@ "0"];

        
        NSArray *arFiltered = [  self.Detailmodels filteredArrayUsingPredicate:predicate];// Filter the maTemp array by certain conditions (specific date), that is, big data search.
        
        if(arFiltered.count>0) {self.orangeViewM.isShow = YES;
            
            self.orangeViewM.showStr = @" One click \n delivery";
            self.orangeViewM.type = ReceivingDelieverEnum4Deliever;
            
            return self.orangeViewM.isShow;


        }

        
// 2. When there is a record of "Goods to be received", the button of "One-click Collection" will be displayed

         predicate = [NSPredicate predicateWithFormat:@"receivingState == %@".@ "1"];
        
        
        
        
        

        arFiltered = [  self.Detailmodels filteredArrayUsingPredicate:predicate];//
        
        
        if(arFiltered.count>0) {self.orangeViewM.isShow = YES;
            
            self.orangeViewM.showStr = @" One key \ N to collect goods";
            self.orangeViewM.type = ReceivingDelieverEnum4ProReceiving; }}else{/ / at the corresponding level
        
// If there is a record of "Goods to be received", the "one click to receive" button will be displayed

        
        NSPredicate* predicate = [NSPredicate predicateWithFormat:@"receivingState == %@".@ "1"];
        
        
        
        
        

        NSArray *arFiltered = [  self.Detailmodels filteredArrayUsingPredicate:predicate];// Filter the maTemp array by certain conditions (specific date), that is, big data search.
        
        if(arFiltered.count>0) {self.orangeViewM.isShow = YES;
            
            self.orangeViewM.showStr = @" One click \n to receive goods";
            self.orangeViewM.type = ReceivingDelieverEnum4Receiving; }}return self.orangeViewM.isShow;
    
    
    
}


Copy the code

IV iOS view tops the app

  • IOS View top app: Adapted for date controls on iOS12 that are blocked by filtered views

This article uses pod ‘PGDatePicker’,’2.6.9’· as an example

Problem: Date view is blocked by filter view on iOS12

Idea: Use the runtime API to modify the internal implementation of the third-party SDK

Mp.weixin.qq.com/s/rT4Iu_Fb8…

see also

  • It is recommended to use[[UIApplication sharedApplication].delegate window]Access to the window

In performing didFinishLaunchingWithOptions: when the proxy method, called window makeKeyAndVisible] [self.; [UIApplication sharedApplication].keyWindow method can’t be used to get the delegate.window, but it can always be used to get the delegate.window.

  1. You are advised to use [[UIApplication sharedApplication]. Delegate window] to obtain the window

  2. Do not add code to a window, such as a popover, when keyWindow is nil.