initial commit

This commit is contained in:
Caleb
2026-03-01 15:59:27 +08:00
commit a9e97d56cb
1426 changed files with 172367 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
//
// FUAlertController.h
//
// Created by 项林平 on 2019/6/21.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@class FUAlertController;
@interface FUAlertModel : NSObject
@property (nonatomic, copy) NSString *alertTitle;
@property (nonatomic, copy) NSString *alertMessage;
@property (nonatomic, assign) UIAlertControllerStyle preferredStyle;
- (instancetype) initWithTitle:(NSString *)title message:(NSString *)message style:(UIAlertControllerStyle)style;
@end
typedef void (^FUAlert)(FUAlertController *controller);
typedef FUAlertController * _Nonnull (^FUShowAlert)(UIViewController *controller);
typedef FUAlertController * _Nonnull (^FUActions)(NSArray<UIAlertAction *> *actions);
typedef FUAlertController * _Nullable (^FUSourceView)(UIView *sourceView);
@interface FUAlertController : UIAlertController
+ (FUAlertController *)makeAlert:(FUAlert)block alertModel:(FUAlertModel *)model;
/**
设置Actions
@return Self
*/
- (FUActions)actionItems;
/**
当设备为iPad时设置SourceView
@return Self
*/
- (FUSourceView)sourceView;
/**
显示Alert
@return Self
*/
- (FUShowAlert)showAlert;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,57 @@
//
// FUAlertController.m
//
// Created by on 2019/6/21.
//
#import "FUAlertController.h"
@implementation FUAlertModel
- (instancetype)initWithTitle:(NSString *)title message:(NSString *)message style:(UIAlertControllerStyle)style {
self = [super init];
if (self) {
self.alertTitle = title;
self.alertMessage = message;
self.preferredStyle = style;
}
return self;
}
@end
@implementation FUAlertController
+(FUAlertController *)makeAlert:(FUAlert)block alertModel:(FUAlertModel *)model {
FUAlertController *alert = [FUAlertController alertControllerWithTitle:model.alertTitle message:model.alertMessage preferredStyle:model.preferredStyle];
block(alert);
return alert;
}
- (FUActions)actionItems {
FUActions actionsBlock = ^(NSArray<UIAlertAction *> *actions) {
[actions enumerateObjectsUsingBlock:^(UIAlertAction * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[self addAction:obj];
}];
return self;
};
return actionsBlock;
}
- (FUShowAlert)showAlert {
FUShowAlert showBlock = ^(UIViewController *controller) {
[controller presentViewController:self animated:YES completion:nil];
return self;
};
return showBlock;
}
- (FUSourceView)sourceView {
FUSourceView sourceViewBlock = ^(UIView *sourceView) {
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && sourceView) {
self.popoverPresentationController.sourceView = sourceView;
self.popoverPresentationController.sourceRect = sourceView.bounds;
self.popoverPresentationController.permittedArrowDirections = UIPopoverArrowDirectionAny;
}
return self;
};
return sourceViewBlock;
}
@end

View File

@@ -0,0 +1,48 @@
//
// FUAlertManager.h
//
// Created by 项林平 on 2019/9/25.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface FUAlertManager : NSObject
/// Alert
/// @param titleString title
/// @param messageString message
/// @param cancelString 取消
/// @param confirmString 确定
/// @param viewController 控制器
/// @param confirm 确定闭包
/// @param cancel 取消闭包
+ (void)showAlertWithTitle:(nullable NSString *)titleString
message:(nullable NSString *)messageString
cancel:(nullable NSString *)cancelString
confirm:(nullable NSString *)confirmString
inController:(nullable UIViewController *)viewController
confirmHandler:(nullable void (^)(void))confirm
cancelHandler:(nullable void (^)(void))cancel;
/// ActionSheet
/// @param titleString title
/// @param messageString message
/// @param cancelString 取消
/// @param viewController 控制器
/// @param sourceView 设备为iPad时需要传入
/// @param actions 选项
/// @param actionHandler 选项闭包
+ (void)showActionSheetWithTitle:(nullable NSString *)titleString
message:(nullable NSString *)messageString
cancel:(nullable NSString *)cancelString
inController:(nullable UIViewController *)viewController
sourceView:(nullable UIView *)sourceView
actions:(NSArray<NSString *> *)actions
actionHandler:(nullable void (^)(NSInteger index))actionHandler;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,114 @@
//
// FUAlertManager.m
//
// Created by on 2019/9/25.
//
#import "FUAlertManager.h"
#import "FUAlertController.h"
@implementation FUAlertManager
+ (void)showAlertWithTitle:(NSString *)titleString
message:(NSString *)messageString
cancel:(NSString *)cancelString
confirm:(NSString *)confirmString
inController:(UIViewController *)viewController
confirmHandler:(void (^)(void))confirm
cancelHandler:(void (^)(void))cancel {
if (!cancelString && !confirmString) {
return;
}
FUAlertModel *alertModel = [[FUAlertModel alloc] initWithTitle:titleString message:messageString style:UIAlertControllerStyleAlert];
__block UIViewController *currentViewController = viewController;
[FUAlertController makeAlert:^(FUAlertController * _Nonnull controller) {
NSMutableArray *items = [[NSMutableArray alloc] init];
if (cancelString) {
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:cancelString style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
if (cancel) {
cancel();
}
}];
//Action
[cancelAction setValue:[UIColor colorWithRed:44/255.0 green:46/255.0 blue:48/255.0 alpha:1.0] forKey:@"titleTextColor"];
[items addObject:cancelAction];
}
if (confirmString) {
UIAlertAction *confirmAction = [UIAlertAction actionWithTitle:confirmString style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
if (confirm) {
confirm();
}
}];
[confirmAction setValue:[UIColor colorWithRed:103/255.f green:195/255.f blue:103/255.f alpha:1] forKey:@"titleTextColor"];
[items addObject:confirmAction];
}
if (!currentViewController) {
currentViewController = [self topViewController];
}
if (!currentViewController) {
NSLog(@"FUAlert: viewController can not be nil!");
return;
}
controller.actionItems(items).showAlert(currentViewController);
} alertModel:alertModel];
}
+ (void)showActionSheetWithTitle:(NSString *)titleString
message:(NSString *)messageString
cancel:(NSString *)cancelString
inController:(UIViewController *)viewController
sourceView:(UIView *)sourceView
actions:(NSArray<NSString *> *)actions
actionHandler:(void (^)(NSInteger))actionHandler {
if (actions.count == 0) {
return;
}
FUAlertModel *alertModel = [[FUAlertModel alloc] initWithTitle:titleString message:messageString style:UIAlertControllerStyleActionSheet];
__block UIViewController *currentViewController = viewController;
[FUAlertController makeAlert:^(FUAlertController * _Nonnull controller) {
NSMutableArray *items = [[NSMutableArray alloc] init];
if (cancelString) {
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:cancelString style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
}];
[items addObject:cancelAction];
}
[actions enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
UIAlertAction *alertAction = [UIAlertAction actionWithTitle:obj style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
if (actionHandler) {
actionHandler(idx);
}
}];
[items addObject:alertAction];
}];
if (!currentViewController) {
currentViewController = [self topViewController];
}
if (!currentViewController) {
NSLog(@"FUAlert: viewController can not be nil!");
return;
}
controller.actionItems(items).sourceView(sourceView).showAlert(currentViewController);
} alertModel:alertModel];
}
+ (UIViewController *)topViewController {
UIViewController *root = [UIApplication sharedApplication].delegate.window.rootViewController;
return [self currentViewControllerWithRootViewController:root];
}
+ (UIViewController *)currentViewControllerWithRootViewController:(UIViewController *)viewController {
if (viewController.presentedViewController) {
return [self currentViewControllerWithRootViewController:viewController.presentedViewController];
} else if ([viewController isKindOfClass:[UINavigationController class]]) {
UINavigationController *navigation = (UINavigationController *)viewController;
return [self currentViewControllerWithRootViewController:navigation.visibleViewController];
} else if ([viewController isKindOfClass:[UITabBarController class]]) {
UITabBarController *tabBar = (UITabBarController *)viewController;
return [self currentViewControllerWithRootViewController:tabBar.selectedViewController];
} else {
return viewController;
}
}
@end

View File

@@ -0,0 +1,25 @@
//
// FUCommonUIComponent.h
// FUCommonUIComponent
//
// Created by 项林平 on 2022/6/17.
//
#import <Foundation/Foundation.h>
#import "FUSegmentBar.h"
#import "FUTipHUD.h"
#import "FUInsetsLabel.h"
#import "FUSlider.h"
#import "FUItemsView.h"
#import "FUItemCell.h"
#import "FUSquareButton.h"
#import "FUAlertManager.h"
//! Project version number for FUCommonUIComponent.
FOUNDATION_EXPORT double FUCommonUIComponentVersionNumber;
//! Project version string for FUCommonUIComponent.
FOUNDATION_EXPORT const unsigned char FUCommonUIComponentVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <FUCommonUIComponent/PublicHeader.h>

View File

@@ -0,0 +1,20 @@
//
// FUCommonUIDefine.h
// FUCommonUIComponent
//
// Created by 项林平 on 2022/6/20.
//
#import <AVFoundation/AVFoundation.h>
#import <UIKit/UIKit.h>
#ifndef FUCommonUIDefine_h
#define FUCommonUIDefine_h
static inline UIImage * FUCommonUIImageNamed(NSString *name) {
NSString *path = [[NSBundle mainBundle] pathForResource:@"FUCommonUIComponent" ofType:@"framework" inDirectory:@"Frameworks"];
NSBundle *bundle = [NSBundle bundleWithPath:path];
return [UIImage imageNamed:name inBundle:bundle compatibleWithTraitCollection:nil];;
}
#endif /* FUCommonUIDefine_h */

View File

@@ -0,0 +1,18 @@
//
// FUInsetsLabel.h
// FUCommonUIComponent
//
// Created by 项林平 on 2022/6/20.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface FUInsetsLabel : UILabel
- (instancetype)initWithFrame:(CGRect)frame insets:(UIEdgeInsets)insets;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,48 @@
//
// FUInsetsLabel.m
// FUCommonUIComponent
//
// Created by on 2022/6/20.
//
#import "FUInsetsLabel.h"
@interface FUInsetsLabel ()
@property (nonatomic) UIEdgeInsets insets;
@end
@implementation FUInsetsLabel
- (instancetype)initWithFrame:(CGRect)frame {
return [self initWithFrame:frame insets:UIEdgeInsetsMake(8, 8, 8, 8)];
}
- (instancetype)initWithFrame:(CGRect)frame insets:(UIEdgeInsets)insets {
self = [super initWithFrame:frame];
if (self) {
self.insets = insets;
}
return self;
}
- (void)drawTextInRect:(CGRect)rect {
[super drawTextInRect:UIEdgeInsetsInsetRect(rect, self.insets)];
}
- (CGSize)sizeThatFits:(CGSize)size {
CGSize fitSize = [super sizeThatFits:size];
fitSize.width += self.insets.left + self.insets.right;
fitSize.height += self.insets.top + self.insets.bottom;
return fitSize;
}
- (CGSize)intrinsicContentSize {
CGSize contentSize = [super intrinsicContentSize];
contentSize.width += self.insets.left + self.insets.right;
contentSize.height += self.insets.top + self.insets.bottom;
return contentSize;
}
@end

View File

@@ -0,0 +1,20 @@
//
// FUItemCell.h
// FUCommonUIComponent
//
// Created by 项林平 on 2022/6/24.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface FUItemCell : UICollectionViewCell
@property (nonatomic, strong, readonly) UIImageView *imageView;
@property (nonatomic, strong, readonly) UIActivityIndicatorView *indicatorView;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,68 @@
//
// FUItemCell.m
// FUCommonUIComponent
//
// Created by on 2022/6/24.
//
#import "FUItemCell.h"
@interface FUItemCell ()
@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UIActivityIndicatorView *indicatorView;
@end
@implementation FUItemCell
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self.contentView addSubview:self.imageView];
NSLayoutConstraint *imageLeading = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0];
NSLayoutConstraint *imageTrailing = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0];
NSLayoutConstraint *imageTop = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
NSLayoutConstraint *imageBottom = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];
[self.contentView addConstraints:@[imageLeading, imageTrailing, imageTop, imageBottom]];
[self.contentView addSubview:self.indicatorView];
NSLayoutConstraint *centerYConstraint = [NSLayoutConstraint constraintWithItem:self.indicatorView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
NSLayoutConstraint *centerXConstraint = [NSLayoutConstraint constraintWithItem:self.indicatorView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
[self.contentView addConstraints:@[centerXConstraint, centerYConstraint]];
}
return self;
}
#pragma mark - Setters
- (void)setSelected:(BOOL)selected {
[super setSelected:selected];
self.imageView.layer.borderWidth = selected ? 3.f : 0;
self.imageView.layer.borderColor = selected ? [UIColor colorWithRed:103/255.f green:195/255.f blue:103/255.f alpha:1].CGColor : [UIColor clearColor].CGColor;
}
#pragma mark - Getters
- (UIImageView *)imageView {
if (!_imageView) {
_imageView = [[UIImageView alloc] init];
_imageView.translatesAutoresizingMaskIntoConstraints = NO;
_imageView.layer.masksToBounds = YES;
_imageView.layer.cornerRadius = 30.f;
}
return _imageView;
}
- (UIActivityIndicatorView *)indicatorView {
if (!_indicatorView) {
_indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
_indicatorView.hidden = YES;
_indicatorView.translatesAutoresizingMaskIntoConstraints = NO;
}
return _indicatorView;
}
@end

View File

@@ -0,0 +1,49 @@
//
// FUItemsView.h
// FUCommonUIComponent
//
// Created by 项林平 on 2022/6/24.
//
#import <UIKit/UIKit.h>
@class FUItemsView;
NS_ASSUME_NONNULL_BEGIN
@protocol FUItemsViewDelegate <NSObject>
@optional
- (void)itemsView:(FUItemsView *)itemsView didSelectItemAtIndex:(NSInteger)index;
@end
@interface FUItemsView : UIView
/// 数据源
/// @discussion 外部传入的icon名数组查找不到icon会展示空白
@property (nonatomic, copy) NSArray<NSString *> *items;
/// 当前选中索引
/// @discussion 默认为 -1-1为取消选中
@property (nonatomic, assign) NSInteger selectedIndex;
@property (nonatomic, weak) id<FUItemsViewDelegate> delegate;
/// 初始化
/// @param frame Frame
/// @param topSpacing 顶部预留空间默认为0
- (instancetype)initWithFrame:(CGRect)frame topSpacing:(CGFloat)topSpacing;
/// 开始当前选中项动画
/// @note 开始动画后无法选择其他项
- (void)startAnimation;
/// 结束当前选中项动画
/// @note 结束动画后可以继续选择其他项
- (void)stopAnimation;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,197 @@
//
// FUItemsView.m
// FUCommonUIComponent
//
// Created by on 2022/6/24.
//
#import "FUItemsView.h"
#import "FUItemCell.h"
static NSString * const kFUItemCellIdentifier = @"FUItemCell";
@interface FUItemsView ()<UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout>
@property (nonatomic, strong) UICollectionView *collectionView;
@property (nonatomic, assign) CGFloat collectionTopConstant;
@end
@implementation FUItemsView
#pragma mark - Initializer
- (instancetype)initWithFrame:(CGRect)frame topSpacing:(CGFloat)topSpacing {
self = [super initWithFrame:frame];
if (self) {
self.collectionTopConstant = topSpacing;
[self configureUI];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self configureUI];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if (self) {
[self configureUI];
}
return self;
}
#pragma mark - UI
- (void)configureUI {
self.backgroundColor = [UIColor clearColor];
UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:effect];
effectView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:effectView];
NSLayoutConstraint *effectLeading = [NSLayoutConstraint constraintWithItem:effectView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0];
NSLayoutConstraint *effectTrailing = [NSLayoutConstraint constraintWithItem:effectView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0];
NSLayoutConstraint *effectTop = [NSLayoutConstraint constraintWithItem:effectView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
NSLayoutConstraint *effectBottom = [NSLayoutConstraint constraintWithItem:effectView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];
[self addConstraints:@[effectLeading, effectTrailing, effectTop, effectBottom]];
[self addSubview:self.collectionView];
NSLayoutConstraint *leading = [NSLayoutConstraint constraintWithItem:self.collectionView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0];
NSLayoutConstraint *trailing = [NSLayoutConstraint constraintWithItem:self.collectionView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0];
NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:self.collectionView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1.0 constant:self.collectionTopConstant];
NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:self.collectionView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:84];
[self addConstraints:@[leading, trailing, top]];
[self.collectionView addConstraint:height];
_selectedIndex = -1;
}
#pragma mark - Instance methods
- (void)startAnimation {
if (_selectedIndex < 0 && _selectedIndex >= self.items.count) {
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
FUItemCell *selectedCell = (FUItemCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:self.selectedIndex inSection:0]];
if (selectedCell) {
[selectedCell.indicatorView startAnimating];
self.collectionView.userInteractionEnabled = NO;
}
});
}
- (void)stopAnimation {
if (_selectedIndex < 0 && _selectedIndex >= self.items.count) {
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
FUItemCell *selectedCell = (FUItemCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:self.selectedIndex inSection:0]];
if (selectedCell) {
[selectedCell.indicatorView stopAnimating];
self.collectionView.userInteractionEnabled = YES;
}
});
}
#pragma mark - Private methods
- (UIImage *)imageWithImageName:(NSString *)imageName {
UIImage *resultImage = [UIImage imageNamed:imageName];
if (!resultImage) {
NSString *path = [[NSBundle mainBundle] pathForResource:imageName ofType:@"png"];
resultImage = [UIImage imageWithContentsOfFile:path];
}
if (!resultImage) {
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.png", imageName]];
resultImage = [UIImage imageWithContentsOfFile:path];
}
return resultImage;
}
#pragma mark - Collection view data source
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return self.items.count;
}
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
FUItemCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kFUItemCellIdentifier forIndexPath:indexPath];
NSString *item = self.items[indexPath.item];
cell.imageView.image = [self imageWithImageName:item];
return cell;
}
#pragma mark - Collection view delegate
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.item == _selectedIndex) {
return;
}
_selectedIndex = indexPath.item;
if (self.delegate && [self.delegate respondsToSelector:@selector(itemsView:didSelectItemAtIndex:)]) {
[self.delegate itemsView:self didSelectItemAtIndex:indexPath.item];
}
}
#pragma mark - Collection view delegate flow layout
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(60, 60);
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
return UIEdgeInsetsMake(12, 16, 12, 16);
}
#pragma mark - Setters
- (void)setItems:(NSArray<NSString *> *)items {
_items = items;
dispatch_async(dispatch_get_main_queue(), ^{
[self.collectionView reloadData];
});
}
- (void)setSelectedIndex:(NSInteger)selectedIndex {
if (selectedIndex < 0 || selectedIndex >= self.items.count) {
return;
}
_selectedIndex = selectedIndex;
dispatch_async(dispatch_get_main_queue(), ^{
[self.collectionView selectItemAtIndexPath:[NSIndexPath indexPathForItem:selectedIndex inSection:0] animated:NO scrollPosition:UICollectionViewScrollPositionNone];
if (self.delegate && [self.delegate respondsToSelector:@selector(itemsView:didSelectItemAtIndex:)]) {
[self.delegate itemsView:self didSelectItemAtIndex:selectedIndex];
}
});
}
#pragma mark - Getters
- (UICollectionView *)collectionView {
if (!_collectionView) {
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:flowLayout];
_collectionView.backgroundColor = [UIColor clearColor];
_collectionView.showsHorizontalScrollIndicator = NO;
_collectionView.translatesAutoresizingMaskIntoConstraints = NO;
_collectionView.dataSource = self;
_collectionView.delegate = self;
[_collectionView registerClass:[FUItemCell class] forCellWithReuseIdentifier:kFUItemCellIdentifier];
}
return _collectionView;
}
@end

View File

@@ -0,0 +1,77 @@
//
// FUSegmentBar.h
// FULiveDemo
//
// Created by 项林平 on 2021/9/26.
// Copyright © 2021 FaceUnity. All rights reserved.
//
#import <UIKit/UIKit.h>
@class FUSegmentBar;
NS_ASSUME_NONNULL_BEGIN
@protocol FUSegmentBarDelegate <NSObject>
- (void)segmentBar:(FUSegmentBar *)segmentBar didSelectItemAtIndex:(NSUInteger)index;
@optional
- (BOOL)segmentBar:(FUSegmentBar *)segmentBar shouldSelectItemAtIndex:(NSInteger)index;
- (BOOL)segmentBar:(FUSegmentBar *)segmentBar shouldDisableItemAtIndex:(NSInteger)index;
@end
@interface FUSegmentBarConfigurations : NSObject
/// 普通颜色
@property (nonatomic, strong) UIColor *normalTitleColor;
/// 选中状态颜色
@property (nonatomic, strong) UIColor *selectedTitleColor;
/// 无法选中状态颜色
@property (nonatomic, strong) UIColor *disabledTitleColor;
/// 字体
@property (nonatomic, strong) UIFont *titleFont;
@end
@interface FUSegmentBar : UIView
@property (nonatomic, weak) id<FUSegmentBarDelegate> delegate;
/// 当前选中项索引
/// @discussion 默认为-1-1为取消选中
@property (nonatomic, assign, readonly) NSInteger selectedIndex;
/// Unavailable initializer
+ (instancetype)new NS_UNAVAILABLE;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
/// 初始化
/// @param frame frame
/// @param titles SegmentsTitle数组
/// @param configuration 配置信息
- (instancetype)initWithFrame:(CGRect)frame titles:(NSArray<NSString *> *)titles configuration:(nullable FUSegmentBarConfigurations *)configuration;
/// 选中指定索引项
/// @param index 索引
- (void)selectItemAtIndex:(NSInteger)index;
- (void)refresh;
@end
@interface FUSegmentsBarCell : UICollectionViewCell
@property (nonatomic, strong) UILabel *segmentTitleLabel;
@property (nonatomic, strong) UIColor *segmentNormalTitleColor;
@property (nonatomic, strong) UIColor *segmentSelectedTitleColor;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,237 @@
//
// FUSegmentBar.m
// FULiveDemo
//
// Created by on 2021/9/26.
// Copyright © 2021 FaceUnity. All rights reserved.
//
#import "FUSegmentBar.h"
@interface FUSegmentBar ()
@property (nonatomic, assign) NSInteger selectedIndex;
@end
@implementation FUSegmentBarConfigurations
- (instancetype)init {
self = [super init];
if (self) {
// /
self.selectedTitleColor = [UIColor colorWithRed:103/255.0f green:195/255.0f blue:103/255.0f alpha:1.0];
self.normalTitleColor = [UIColor whiteColor];
self.disabledTitleColor = [UIColor colorWithWhite:1 alpha:0.6];
self.titleFont = [UIFont systemFontOfSize:13];
}
return self;
}
@end
static NSString * const kFUSegmentCellIdentifierKey = @"FUSegmentCellIdentifier";
@interface FUSegmentBar ()<UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout>
@property (nonatomic, strong) UICollectionView *collectionView;
@property (nonatomic, strong) FUSegmentBarConfigurations *configuration;
@property (nonatomic, strong) NSMutableArray *titles;
/// cell
@property (nonatomic, copy) NSArray *itemWidths;
@end
@implementation FUSegmentBar
#pragma mark - Initializer
- (instancetype)initWithFrame:(CGRect)frame titles:(NSArray<NSString *> *)titles configuration:(FUSegmentBarConfigurations *)configuration {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor colorWithRed:5/255.0 green:15/255.0 blue:20/255.0 alpha:1.0];
self.titles = [titles mutableCopy];
self.configuration = configuration;
if (!self.configuration) {
self.configuration = [[FUSegmentBarConfigurations alloc] init];
}
//
NSMutableArray *tempWidths = [NSMutableArray arrayWithCapacity:self.titles.count];
if (self.titles.count < 7) {
//
CGFloat width = CGRectGetWidth(frame) / self.titles.count * 1.0;
for (NSInteger i = 0; i < self.titles.count; i++) {
[tempWidths addObject:@(width)];
}
} else {
//
for (NSString *title in self.titles) {
CGSize nameSize = [title sizeWithAttributes:@{NSFontAttributeName : self.configuration.titleFont}];
[tempWidths addObject:@(nameSize.width + 20)];
}
}
self.itemWidths = [tempWidths copy];
_selectedIndex = -1;
[self addSubview:self.collectionView];
}
return self;
}
#pragma mark - Instance methods
- (void)selectItemAtIndex:(NSInteger)index {
NSInteger count = self.titles.count;
if (index >= count) {
return;
}
if (self.selectedIndex == index) {
//
if (self.delegate && [self.delegate respondsToSelector:@selector(segmentBar:didSelectItemAtIndex:)]) {
[self.delegate segmentBar:self didSelectItemAtIndex:index];
}
return;
}
if (index == -1) {
//
[self.collectionView deselectItemAtIndexPath:[NSIndexPath indexPathForItem:self.selectedIndex inSection:0] animated:NO];
self.selectedIndex = -1;
} else {
//
[self.collectionView selectItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0] animated:YES scrollPosition:UICollectionViewScrollPositionCenteredHorizontally];
if (self.delegate && [self.delegate respondsToSelector:@selector(segmentBar:didSelectItemAtIndex:)]) {
[self.delegate segmentBar:self didSelectItemAtIndex:index];
}
self.selectedIndex = index;
}
}
- (void)refresh {
dispatch_async(dispatch_get_main_queue(), ^{
[self.collectionView reloadData];
if (self.selectedIndex >= 0) {
[self.collectionView selectItemAtIndexPath:[NSIndexPath indexPathForItem:self.selectedIndex inSection:0] animated:NO scrollPosition:UICollectionViewScrollPositionNone];
}
});
}
#pragma mark - Collection view data source
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return self.titles.count;
}
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
FUSegmentsBarCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kFUSegmentCellIdentifierKey forIndexPath:indexPath];
cell.segmentTitleLabel.text = self.titles[indexPath.item];
cell.segmentTitleLabel.font = self.configuration.titleFont;
cell.segmentNormalTitleColor = self.configuration.normalTitleColor;
cell.segmentSelectedTitleColor = self.configuration.selectedTitleColor;
if (self.delegate && [self.delegate respondsToSelector:@selector(segmentBar:shouldDisableItemAtIndex:)]) {
if ([self.delegate segmentBar:self shouldDisableItemAtIndex:indexPath.item]) {
cell.segmentTitleLabel.textColor = self.configuration.disabledTitleColor;
}
}
return cell;
}
#pragma mark - Collection view delegate
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
_selectedIndex = indexPath.item;
if (self.delegate && [self.delegate respondsToSelector:@selector(segmentBar:didSelectItemAtIndex:)]) {
[self.delegate segmentBar:self didSelectItemAtIndex:indexPath.item];
}
}
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {
if (self.delegate && [self.delegate respondsToSelector:@selector(segmentBar:shouldSelectItemAtIndex:)]) {
return [self.delegate segmentBar:self shouldSelectItemAtIndex:indexPath.item];
}
return YES;
}
#pragma mark - Collection view delegate flow layout
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake([self.itemWidths[indexPath.item] floatValue], CGRectGetHeight(collectionView.frame));
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsZero;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
return 0;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
return 0;
}
#pragma mark - Getters
- (UICollectionView *)collectionView {
if (!_collectionView) {
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.frame), 49.f) collectionViewLayout:flowLayout];
_collectionView.backgroundColor = [UIColor clearColor];
_collectionView.showsHorizontalScrollIndicator = NO;
_collectionView.showsVerticalScrollIndicator = NO;
_collectionView.dataSource = self;
_collectionView.delegate = self;
[_collectionView registerClass:[FUSegmentsBarCell class] forCellWithReuseIdentifier:kFUSegmentCellIdentifierKey];
}
return _collectionView;
}
@end
@implementation FUSegmentsBarCell
#pragma mark - Initializer
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor clearColor];
[self.contentView addSubview:self.segmentTitleLabel];
NSLayoutConstraint *titleLabelCenterX = [NSLayoutConstraint constraintWithItem:self.segmentTitleLabel attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
NSLayoutConstraint *titleLabelCenterY = [NSLayoutConstraint constraintWithItem:self.segmentTitleLabel attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
[self.contentView addConstraints:@[titleLabelCenterX, titleLabelCenterY]];
}
return self;
}
#pragma mark - Setters
- (void)setSelected:(BOOL)selected {
[super setSelected:selected];
if (selected) {
self.segmentTitleLabel.textColor = self.segmentSelectedTitleColor ? self.segmentSelectedTitleColor : [UIColor colorWithRed:103/255.0f green:195/255.0f blue:103/255.0f alpha:1.0];
} else {
self.segmentTitleLabel.textColor = self.segmentNormalTitleColor ? self.segmentNormalTitleColor : [UIColor whiteColor];
}
}
#pragma mark - Getters
- (UILabel *)segmentTitleLabel {
if (!_segmentTitleLabel) {
_segmentTitleLabel = [[UILabel alloc] initWithFrame:self.contentView.bounds];
_segmentTitleLabel.textColor = [UIColor whiteColor];
_segmentTitleLabel.font = [UIFont systemFontOfSize:13];
_segmentTitleLabel.textAlignment = NSTextAlignmentCenter;
_segmentTitleLabel.translatesAutoresizingMaskIntoConstraints = NO;
}
return _segmentTitleLabel;
}
@end

View File

@@ -0,0 +1,16 @@
//
// FUSlider.h
// FUAPIDemoBar
//
// Created by L on 2018/6/27.
// Copyright © 2018年 L. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface FUSlider : UISlider
/// 零点是否在中间默认为NO
@property (nonatomic, assign, getter=isBidirection) BOOL bidirection;
@end

View File

@@ -0,0 +1,147 @@
//
// FUSlider.m
// FUAPIDemoBar
//
// Created by L on 2018/6/27.
// Copyright © 2018 L. All rights reserved.
//
#import "FUSlider.h"
#import "FUCommonUIDefine.h"
@interface FUSlider ()
///
@property (nonatomic, strong) UILabel *tipLabel;
///
@property (nonatomic, strong) UIImageView *tipBackgroundImageView;
///
@property (nonatomic, strong) UIView *trackView;
/// 线
@property (nonatomic, strong) UIView *middleLine;
@end
@implementation FUSlider
- (void)awakeFromNib {
[super awakeFromNib];
[self configureUI];
}
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self configureUI];
}
return self;
}
- (UIView *)sliderTrackBackView {
return self.subviews.firstObject;
}
- (void)configureUI {
[self setThumbImage:FUCommonUIImageNamed(@"slider_dot") forState:UIControlStateNormal];
[self setMaximumTrackTintColor:[UIColor whiteColor]];
[self setMinimumTrackTintColor:[UIColor colorWithRed:103/255.0 green:195/255.0 blue:103/255.0 alpha:1]];
[self addSubview:self.tipBackgroundImageView];
[self addSubview:self.tipLabel];
[self.sliderTrackBackView addSubview:self.trackView];
[self addSubview:self.middleLine];
}
-(void)layoutSubviews {
[super layoutSubviews];
if (!self.trackView.hidden) {
[self.sliderTrackBackView insertSubview:self.trackView atIndex:self.subviews.count-2];
// [self bringSubviewToFront:self.trackView];
}
if (!self.middleLine.hidden) {
self.middleLine.frame = CGRectMake(CGRectGetWidth(self.bounds)/2.0 - 1, CGRectGetHeight(self.bounds)/2.0 - 4, 2, 8);
}
[self setValue:self.value animated:NO];
}
- (void)setBidirection:(BOOL)bidirection {
_bidirection = bidirection;
if (bidirection) {
self.middleLine.hidden = NO;
self.trackView.hidden = NO;
[self setMinimumTrackTintColor:[UIColor whiteColor]];
} else {
self.middleLine.hidden = YES;
self.trackView.hidden = YES;
[self setMinimumTrackTintColor:[UIColor colorWithRed:103/255.0 green:195/255.0 blue:103/255.0 alpha:1]];
}
}
- (void)setValue:(float)value animated:(BOOL)animated {
[super setValue:value animated:animated];
if (_bidirection) {
self.tipLabel.text = [NSString stringWithFormat:@"%d",(int)(value * 100 - 50)];
CGFloat currentValue = value - 0.5;
CGFloat width = currentValue * CGRectGetWidth(self.bounds);
if (width < 0 ) {
width = -width;
}
CGFloat originX = currentValue > 0 ? CGRectGetWidth(self.bounds) / 2.0 : CGRectGetWidth(self.bounds) / 2.0 - width;
self.trackView.frame = CGRectMake(originX, CGRectGetHeight(self.frame)/2.0 - 2, width, 4.0);
} else {
self.tipLabel.text = [NSString stringWithFormat:@"%d",(int)(value * 100)];
}
CGFloat x = value * (self.frame.size.width - 16) - self.tipLabel.frame.size.width * 0.5 + 8;
CGRect frame = self.tipLabel.frame;
frame.origin.x = x;
self.tipBackgroundImageView.frame = frame;
self.tipLabel.frame = frame;
self.tipLabel.hidden = !self.isTouchInside;
self.tipBackgroundImageView.hidden = !self.isTouchInside;
}
#pragma mark - Getters
- (UIImageView *)tipBackgroundImageView {
if (!_tipBackgroundImageView) {
UIImage *bgImage = FUCommonUIImageNamed(@"slider_tip_background");
_tipBackgroundImageView = [[UIImageView alloc] initWithImage:bgImage];
_tipBackgroundImageView.frame = CGRectMake(0, -bgImage.size.height, bgImage.size.width, bgImage.size.height);
_tipBackgroundImageView.hidden = YES;
}
return _tipBackgroundImageView;
}
- (UILabel *)tipLabel {
if (!_tipLabel) {
_tipLabel = [[UILabel alloc] initWithFrame:self.tipBackgroundImageView.frame];
_tipLabel.textColor = [UIColor whiteColor];
_tipLabel.font = [UIFont systemFontOfSize:10 weight:UIFontWeightMedium];
_tipLabel.textAlignment = NSTextAlignmentCenter;
_tipLabel.hidden = YES;
}
return _tipLabel;
}
- (UIView *)trackView {
if (!_trackView) {
_trackView = [[UIView alloc] init];
_trackView.backgroundColor = [UIColor colorWithRed:103/255.f green:195/255.f blue:103/255.f alpha:1];
_trackView.hidden = YES;
}
return _trackView;
}
- (UIView *)middleLine {
if (!_middleLine) {
_middleLine = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetWidth(self.bounds)/2.0 - 1, CGRectGetHeight(self.bounds)/2.0 - 4, 2, 8)];
_middleLine.backgroundColor = [UIColor whiteColor];
_middleLine.layer.masksToBounds = YES;
_middleLine.layer.cornerRadius = 1.0;
_middleLine.hidden = YES;
}
return _middleLine;
}
@end

View File

@@ -0,0 +1,15 @@
//
// FUSquareButton.h
// FULive
//
// Created by 孙慕 on 2018/8/28.
// Copyright © 2018年 L. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface FUSquareButton : UIButton
- (instancetype)initWithFrame:(CGRect)frame interval:(float)interval;
@end

View File

@@ -0,0 +1,63 @@
//
// FUSquareButton.m
// FULive
//
// Created by on 2018/8/28.
// Copyright © 2018 L. All rights reserved.
//
#import "FUSquareButton.h"
@interface FUSquareButton()
@property(nonatomic,assign) float interval;
@end
@implementation FUSquareButton
- (instancetype)initWithFrame:(CGRect)frame interval:(float)interval{
if (self = [super initWithFrame:frame]) {
_interval = interval;
self.titleLabel.textAlignment = NSTextAlignmentCenter;
self.titleLabel.font = [UIFont systemFontOfSize:14];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
_interval = 8;
self.titleLabel.textAlignment = NSTextAlignmentCenter;
self.titleLabel.font = [UIFont systemFontOfSize:14];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
_interval = 8;
self.titleLabel.textAlignment = NSTextAlignmentCenter;
self.titleLabel.font = [UIFont systemFontOfSize:14];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
CGRect frame = self.imageView.bounds;
CGRect frame1 = self.titleLabel.frame;
self.imageView.frame = frame;
CGPoint center = self.imageView.center;
center.x = self.frame.size.width * 0.5;
self.imageView.center = center;
frame1.origin.x = 0;
frame1.origin.y = CGRectGetMaxY(self.imageView.frame) + _interval;
frame1.size.height = 14;
frame1.size.width = self.bounds.size.width;;
self.titleLabel.frame = frame1;
}
@end

View File

@@ -0,0 +1,37 @@
//
// FUTipHUD.h
// FULiveDemo
//
// Created by 项林平 on 2021/4/12.
// Copyright © 2021 FaceUnity. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSUInteger, FUTipHUDPosition) {
FUTipHUDPositionTop,
FUTipHUDPositionCenter
};
NS_ASSUME_NONNULL_BEGIN
@interface FUTipHUD : NSObject
/// 文字提示默认3秒后自动消失
/// @param tipsString 文字
+ (void)showTips:(NSString *)tipsString;
/// 文字提示
/// @param tipsString 文字
/// @param delay 自动消失时间,单位: 秒
+ (void)showTips:(NSString *)tipsString dismissWithDelay:(NSTimeInterval)delay;
/// 文字提示
/// @param tipsString 文字
/// @param delay 自动消失时间,单位: 秒
/// @param position 显示位置默认为FUTipHUDPositionTop
+ (void)showTips:(NSString *)tipsString dismissWithDelay:(NSTimeInterval)delay position:(FUTipHUDPosition)position;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,72 @@
//
// FUTipHUD.m
// FULiveDemo
//
// Created by on 2021/4/12.
// Copyright © 2021 FaceUnity. All rights reserved.
//
#import "FUTipHUD.h"
#import "FUInsetsLabel.h"
@implementation FUTipHUD
+ (void)showTips:(NSString *)tipsString {
[self showTips:tipsString dismissWithDelay:3];
}
+ (void)showTips:(NSString *)tipsString dismissWithDelay:(NSTimeInterval)delay {
[self showTips:tipsString dismissWithDelay:delay position:FUTipHUDPositionTop];
}
+ (void)showTips:(NSString *)tipsString dismissWithDelay:(NSTimeInterval)delay position:(FUTipHUDPosition)position {
UIWindow *window = [UIApplication sharedApplication].delegate.window;
// label
NSArray<UIView *> *views = window.subviews;
[views enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj isMemberOfClass:[FUInsetsLabel class]]) {
[obj removeFromSuperview];
obj = nil;
}
}];
__block FUInsetsLabel *tipLabel = [[FUInsetsLabel alloc] initWithFrame:CGRectZero insets:UIEdgeInsetsMake(8, 20, 8, 20)];
tipLabel.backgroundColor = [UIColor colorWithRed:5/255.0 green:15/255.0 blue:20/255.0 alpha:0.74];
tipLabel.textColor = [UIColor whiteColor];
tipLabel.font = [UIFont systemFontOfSize:13];
tipLabel.numberOfLines = 0;
tipLabel.layer.masksToBounds = YES;
tipLabel.layer.cornerRadius = 4;
tipLabel.translatesAutoresizingMaskIntoConstraints = NO;
tipLabel.text = tipsString;
[window addSubview:tipLabel];
if (position == FUTipHUDPositionTop) {
CGFloat topConstant = 0;
if (@available(iOS 11.0, *)) {
topConstant = window.safeAreaInsets.top;
}
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:tipLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:window attribute:NSLayoutAttributeTop multiplier:1 constant:84 + topConstant];
[window addConstraint:topConstraint];
} else {
NSLayoutConstraint *centerYConstraint = [NSLayoutConstraint constraintWithItem:tipLabel attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:window attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
[window addConstraint:centerYConstraint];
}
CGFloat windowWidth = CGRectGetWidth(window.bounds);
NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:tipLabel attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationLessThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:windowWidth - 40];
NSLayoutConstraint *centerXConstraint = [NSLayoutConstraint constraintWithItem:tipLabel attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:window attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
[window addConstraint:centerXConstraint];
[tipLabel addConstraint:widthConstraint];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[UIView animateWithDuration:0.3 animations:^{
tipLabel.alpha = 0;
} completion:^(BOOL finished) {
[tipLabel removeFromSuperview];
tipLabel = nil;
}];
});
}
@end

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "slider_dot.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "slider_dot@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "slider_dot@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "slider_tip_background.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "slider_tip_background@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "slider_tip_background@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}