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,35 @@
//
// FUBeautyFilterView.h
// FUBeautyComponent
//
// Created by 项林平 on 2022/6/21.
//
#import <UIKit/UIKit.h>
#import "FUBeautyFilterViewModel.h"
NS_ASSUME_NONNULL_BEGIN
@protocol FUBeautyFilterViewDelegate <NSObject>
/// 滤镜变化
- (void)beautyFilterViewDidChangeFilter:(NSString *)name;
@end
@interface FUBeautyFilterView : UIView
@property (nonatomic, weak) id<FUBeautyFilterViewDelegate> delegate;
- (instancetype)initWithFrame:(CGRect)frame viewModel:(FUBeautyFilterViewModel *)viewModel;
@end
@interface FUBeautyFilterCell : UICollectionViewCell
@property (nonatomic, strong, readonly) UIImageView *imageView;
@property (nonatomic, strong, readonly) UILabel *textLabel;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,201 @@
//
// FUBeautyFilterView.m
// FUBeautyComponent
//
// Created by on 2022/6/21.
//
#import "FUBeautyFilterView.h"
#import "FUBeautyDefine.h"
#import <FUCommonUIComponent/FUSlider.h>
static NSString * const kFUBeautyFilterCellIdentifier = @"FUBeautyFilterCell";
@interface FUBeautyFilterView ()<UICollectionViewDataSource, UICollectionViewDelegate>
@property (nonatomic, strong) FUSlider *filterSlider;
@property (nonatomic, strong) UICollectionView *filterCollectionView;
@property (nonatomic, strong) FUBeautyFilterViewModel *viewModel;
@end
@implementation FUBeautyFilterView
#pragma mark - Initializer
- (instancetype)initWithFrame:(CGRect)frame {
return [self initWithFrame:frame viewModel:[[FUBeautyFilterViewModel alloc] init]];
}
- (instancetype)initWithFrame:(CGRect)frame viewModel:(FUBeautyFilterViewModel *)viewModel {
self = [super initWithFrame:frame];
if (self) {
self.viewModel = viewModel;
[self configureUI];
}
return self;
}
#pragma mark - UI
- (void)configureUI {
UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:effect];
effectView.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame));
[self addSubview:effectView];
[self addSubview:self.filterSlider];
[self addSubview:self.filterCollectionView];
NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:self.filterCollectionView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1 constant:0];
NSLayoutConstraint *leading = [NSLayoutConstraint constraintWithItem:self.filterCollectionView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1 constant:0];
NSLayoutConstraint *trailing = [NSLayoutConstraint constraintWithItem:self.filterCollectionView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTrailing multiplier:1 constant:0];
NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:self.filterCollectionView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:98];
[self addConstraints:@[bottom, leading, trailing]];
[self.filterCollectionView addConstraint:height];
//
[self.filterCollectionView selectItemAtIndexPath:[NSIndexPath indexPathForItem:self.viewModel.selectedIndex inSection:0] animated:YES scrollPosition:UICollectionViewScrollPositionCenteredHorizontally];
self.filterSlider.hidden = self.viewModel.selectedIndex < 1;
if (!self.filterSlider.hidden) {
self.filterSlider.value = self.viewModel.beautyFilters[self.viewModel.selectedIndex].filterLevel;
}
}
#pragma mark - Event response
- (void)sliderValueChanged {
[self.viewModel setFilterValue:self.filterSlider.value];
}
#pragma mark - Collection view data source
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return self.viewModel.beautyFilters.count;
}
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
FUBeautyFilterCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kFUBeautyFilterCellIdentifier forIndexPath:indexPath];
FUBeautyFilterModel *filter = self.viewModel.beautyFilters[indexPath.item];
cell.imageView.image = [UIImage imageNamed:filter.filterName];
cell.textLabel.text = FUBeautyStringWithKey(filter.filterName);
return cell;
}
#pragma mark - Collection view delegate
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
if (self.viewModel.selectedIndex == indexPath.item) {
return;
}
self.filterSlider.hidden = indexPath.item < 1;
if (!self.filterSlider.hidden) {
self.filterSlider.value = self.viewModel.beautyFilters[indexPath.item].filterLevel;
}
self.viewModel.selectedIndex = indexPath.item;
if (self.delegate && [self.delegate respondsToSelector:@selector(beautyFilterViewDidChangeFilter:)]) {
[self.delegate beautyFilterViewDidChangeFilter:FUBeautyStringWithKey(self.viewModel.beautyFilters[indexPath.item].filterName)];
}
}
#pragma mark - Getters
- (FUSlider *)filterSlider {
if (!_filterSlider) {
_filterSlider = [[FUSlider alloc] initWithFrame:CGRectMake(56, 16, CGRectGetWidth(self.frame) - 112, 30)];
_filterSlider.bidirection = NO;
_filterSlider.hidden = YES;
[_filterSlider addTarget:self action:@selector(sliderValueChanged) forControlEvents:UIControlEventValueChanged];
}
return _filterSlider;
}
- (UICollectionView *)filterCollectionView {
if (!_filterCollectionView) {
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
layout.itemSize = CGSizeMake(54, 70);
layout.minimumLineSpacing = 16;
layout.minimumInteritemSpacing = 50;
layout.sectionInset = UIEdgeInsetsMake(16, 18, 10, 18);
_filterCollectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
_filterCollectionView.translatesAutoresizingMaskIntoConstraints = NO;
_filterCollectionView.backgroundColor = [UIColor clearColor];
_filterCollectionView.showsHorizontalScrollIndicator = NO;
_filterCollectionView.dataSource = self;
_filterCollectionView.delegate = self;
[_filterCollectionView registerClass:[FUBeautyFilterCell class] forCellWithReuseIdentifier:kFUBeautyFilterCellIdentifier];
}
return _filterCollectionView;
}
- (FUBeautyFilterViewModel *)viewModel {
if (!_viewModel) {
_viewModel = [[FUBeautyFilterViewModel alloc] init];
}
return _viewModel;
}
@end
@interface FUBeautyFilterCell ()
@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UILabel *textLabel;
@end
@implementation FUBeautyFilterCell
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self.contentView addSubview:self.imageView];
NSLayoutConstraint *imageTop = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1 constant:0];
NSLayoutConstraint *imageLeading = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeading multiplier:1 constant:0];
NSLayoutConstraint *imageTrailing = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTrailing multiplier:1 constant:0];
NSLayoutConstraint *imageHeight = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.imageView attribute:NSLayoutAttributeWidth multiplier:1 constant:0];
[self.contentView addConstraints:@[imageTop, imageLeading, imageTrailing]];
[self.imageView addConstraint:imageHeight];
[self.contentView addSubview:self.textLabel];
NSLayoutConstraint *textTop = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.imageView attribute:NSLayoutAttributeBottom multiplier:1 constant:2];
NSLayoutConstraint *textLeading = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeading multiplier:1 constant:0];
NSLayoutConstraint *textTrailing = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTrailing multiplier:1 constant:0];
[self.contentView addConstraints:@[textTop, textLeading, textTrailing]];
}
return self;
}
- (void)setSelected:(BOOL)selected {
[super setSelected:selected];
self.imageView.layer.borderWidth = selected ? 2 : 0;
self.imageView.layer.borderColor = selected ? [UIColor colorWithRed:103/255.0 green:195/255.0 blue:103/255.0 alpha:1].CGColor : [UIColor clearColor].CGColor;
self.textLabel.textColor = selected ? [UIColor colorWithRed:103/255.0 green:195/255.0 blue:103/255.0 alpha:1] : [UIColor whiteColor];
}
- (UIImageView *)imageView {
if (!_imageView) {
_imageView = [[UIImageView alloc] init];
_imageView.translatesAutoresizingMaskIntoConstraints = NO;
_imageView.layer.masksToBounds = YES;
_imageView.layer.cornerRadius = 3.f;
}
return _imageView;
}
- (UILabel *)textLabel {
if (!_textLabel) {
_textLabel = [[UILabel alloc] init];
_textLabel.textColor = [UIColor whiteColor];
_textLabel.font = [UIFont systemFontOfSize:14];
_textLabel.textAlignment = NSTextAlignmentCenter;
_textLabel.adjustsFontSizeToFitWidth = YES;
_textLabel.translatesAutoresizingMaskIntoConstraints = NO;
}
return _textLabel;
}
@end

View File

@@ -0,0 +1,37 @@
//
// FUBeautyShapeView.h
// FUBeautyComponent
//
// Created by 项林平 on 2022/7/8.
//
#import <UIKit/UIKit.h>
#import "FUBeautyShapeViewModel.h"
NS_ASSUME_NONNULL_BEGIN
@interface FUBeautyShapeView : UIView
- (instancetype)initWithFrame:(CGRect)frame viewModel:(FUBeautyShapeViewModel *)viewModel;
@end
@interface FUBeautyShapeCell : UICollectionViewCell
@property (nonatomic, strong, readonly) UIImageView *imageView;
@property (nonatomic, strong, readonly) UILabel *textLabel;
/// 是否允许选择
@property (nonatomic, assign) BOOL disabled;
@property (nonatomic, assign) BOOL defaultInMiddle;
@property (nonatomic, assign) double currentValue;
@property (nonatomic, assign) double defaultValue;
@property (nonatomic, copy) NSString *imageName;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,299 @@
//
// FUBeautyShapeView.m
// FUBeautyComponent
//
// Created by on 2022/7/8.
//
#import "FUBeautyShapeView.h"
#import "FUBeautyDefine.h"
#import <FUCommonUIComponent/FUCommonUIComponent.h>
static NSString * const kFUBeautyShapeCellIdentifier = @"FUBeautyShapeCell";
@interface FUBeautyShapeView ()<UICollectionViewDataSource, UICollectionViewDelegate>
@property (nonatomic, strong) UICollectionView *shapeCollectionView;
///
@property (nonatomic, strong) FUSlider *slider;
///
@property (nonatomic, strong) FUSquareButton *recoverButton;
@property (nonatomic, strong) FUBeautyShapeViewModel *viewModel;
@end
@implementation FUBeautyShapeView
#pragma mark - Initializer
- (instancetype)initWithFrame:(CGRect)frame {
return [self initWithFrame:frame viewModel:[[FUBeautyShapeViewModel alloc] init]];
}
- (instancetype)initWithFrame:(CGRect)frame viewModel:(FUBeautyShapeViewModel *)viewModel {
self = [super initWithFrame:frame];
if (self) {
self.viewModel = viewModel;
[self configureUI];
[self refreshSubviews];
[self collectionView:self.shapeCollectionView didSelectItemAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
}
return self;
}
#pragma mark - UI
- (void)configureUI {
UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:effect];
effectView.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame));
[self addSubview:effectView];
[self addSubview:self.slider];
[self addSubview:self.recoverButton];
NSLayoutConstraint *recoverLeadingConstraint = [NSLayoutConstraint constraintWithItem:self.recoverButton attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1 constant:17];
NSLayoutConstraint *recoverBottomConstraint = [NSLayoutConstraint constraintWithItem:self.recoverButton attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1 constant:-6];
NSLayoutConstraint *recoverWidthConstraint = [NSLayoutConstraint constraintWithItem:self.recoverButton attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:44];
NSLayoutConstraint *recoverHeightConstraint = [NSLayoutConstraint constraintWithItem:self.recoverButton attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:74];
[self addConstraints:@[recoverLeadingConstraint, recoverBottomConstraint]];
[self.recoverButton addConstraints:@[recoverWidthConstraint, recoverHeightConstraint]];
// 线
UIView *verticalLine = [[UIView alloc] init];
verticalLine.backgroundColor = [UIColor colorWithRed:229/255.f green:229/255.f blue:229/255.f alpha:0.2];
verticalLine.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:verticalLine];
NSLayoutConstraint *lineLeadingConstraint = [NSLayoutConstraint constraintWithItem:verticalLine attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.recoverButton attribute:NSLayoutAttributeTrailing multiplier:1 constant:14];
NSLayoutConstraint *lineCenterYConstraint = [NSLayoutConstraint constraintWithItem:verticalLine attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.recoverButton attribute:NSLayoutAttributeCenterY multiplier:1 constant:-15];
NSLayoutConstraint *lineWidthConstraint = [NSLayoutConstraint constraintWithItem:verticalLine attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:1];
NSLayoutConstraint *lineHeightConstraint = [NSLayoutConstraint constraintWithItem:verticalLine attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:24];
[self addConstraints:@[lineLeadingConstraint, lineCenterYConstraint]];
[verticalLine addConstraints:@[lineWidthConstraint, lineHeightConstraint]];
[self addSubview:self.shapeCollectionView];
NSLayoutConstraint *collectionLeadingConstraint = [NSLayoutConstraint constraintWithItem:self.shapeCollectionView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1 constant:76];
NSLayoutConstraint *collectionTrailingConstraint = [NSLayoutConstraint constraintWithItem:self.shapeCollectionView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTrailing multiplier:1 constant:0];
NSLayoutConstraint *collectionBottomConstraint = [NSLayoutConstraint constraintWithItem:self.shapeCollectionView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1 constant:0];
NSLayoutConstraint *collectionHeightConstraint = [NSLayoutConstraint constraintWithItem:self.shapeCollectionView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:98];
[self addConstraints:@[collectionLeadingConstraint, collectionTrailingConstraint, collectionBottomConstraint]];
[self.shapeCollectionView addConstraint:collectionHeightConstraint];
}
- (void)refreshSubviews {
dispatch_async(dispatch_get_main_queue(), ^{
if (self.viewModel.isDefaultValue) {
self.recoverButton.alpha = 0.6;
self.recoverButton.userInteractionEnabled = NO;
} else {
self.recoverButton.alpha = 1;
self.recoverButton.userInteractionEnabled = YES;
}
if (!self.slider.hidden && self.viewModel.selectedIndex >= 0) {
self.slider.bidirection = self.viewModel.beautyShapes[self.viewModel.selectedIndex].defaultValueInMiddle;
self.slider.value = self.viewModel.beautyShapes[self.viewModel.selectedIndex].currentValue;
}
[self.shapeCollectionView reloadData];
if (self.viewModel.selectedIndex >= 0) {
[self.shapeCollectionView selectItemAtIndexPath:[NSIndexPath indexPathForItem:self.viewModel.selectedIndex inSection:0] animated:NO scrollPosition:UICollectionViewScrollPositionNone];
}
});
}
#pragma mark - Event response
- (void)recoverAction {
[FUAlertManager showAlertWithTitle:nil message:FUBeautyStringWithKey(@"是否将所有参数恢复到默认值") cancel:FUBeautyStringWithKey(@"取消") confirm:FUBeautyStringWithKey(@"确定") inController:nil confirmHandler:^{
[self.viewModel recoverAllShapeValuesToDefault];
[self refreshSubviews];
} cancelHandler:nil];
}
- (void)sliderValueChanged {
[self.viewModel setShapeValue:self.slider.value];
}
- (void)sliderChangeEnded {
[self refreshSubviews];
}
#pragma mark - Collection view data source
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return self.viewModel.beautyShapes.count;
}
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
FUBeautyShapeCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kFUBeautyShapeCellIdentifier forIndexPath:indexPath];
FUBeautyShapeModel *shape = self.viewModel.beautyShapes[indexPath.item];
cell.textLabel.text = FUBeautyStringWithKey(shape.name);
cell.imageName = shape.name;
cell.defaultInMiddle = shape.defaultValueInMiddle;
cell.defaultValue = shape.defaultValue;
cell.currentValue = shape.currentValue;
//
if (shape.differentiateDevicePerformance) {
cell.disabled = self.viewModel.performanceLevel != FUDevicePerformanceLevelHigh;
} else {
cell.disabled = NO;
}
cell.selected = indexPath.item == self.viewModel.selectedIndex;
return cell;
}
#pragma mark - Collection view delegate
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {
FUBeautyShapeModel *shape = self.viewModel.beautyShapes[indexPath.item];
if (shape.differentiateDevicePerformance) {
if (self.viewModel.performanceLevel != FUDevicePerformanceLevelHigh) {
[FUTipHUD showTips:[NSString stringWithFormat:FUBeautyStringWithKey(@"该功能只支持在高端机上使用"), FUBeautyStringWithKey(shape.name)] dismissWithDelay:1];
[self.shapeCollectionView reloadData];
if (self.viewModel.selectedIndex >= 0) {
[self.shapeCollectionView selectItemAtIndexPath:[NSIndexPath indexPathForItem:self.viewModel.selectedIndex inSection:0] animated:NO scrollPosition:UICollectionViewScrollPositionNone];
}
return NO;
}
}
return YES;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.item == self.viewModel.selectedIndex) {
return;
}
self.viewModel.selectedIndex = indexPath.item;
FUBeautyShapeModel *shape = self.viewModel.beautyShapes[indexPath.item];
if (self.slider.hidden) {
self.slider.hidden = NO;
}
self.slider.bidirection = shape.defaultValueInMiddle;
self.slider.value = shape.currentValue;
}
#pragma mark - Getters
- (UICollectionView *)shapeCollectionView {
if (!_shapeCollectionView) {
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
layout.itemSize = CGSizeMake(44, 74);
layout.minimumLineSpacing = 22;
layout.minimumInteritemSpacing = 22;
layout.sectionInset = UIEdgeInsetsMake(16, 16, 6, 16);
_shapeCollectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
_shapeCollectionView.translatesAutoresizingMaskIntoConstraints = NO;
_shapeCollectionView.backgroundColor = [UIColor clearColor];
_shapeCollectionView.showsVerticalScrollIndicator = NO;
_shapeCollectionView.showsHorizontalScrollIndicator = NO;
_shapeCollectionView.dataSource = self;
_shapeCollectionView.delegate = self;
[_shapeCollectionView registerClass:[FUBeautyShapeCell class] forCellWithReuseIdentifier:kFUBeautyShapeCellIdentifier];
}
return _shapeCollectionView;
}
- (FUSquareButton *)recoverButton {
if (!_recoverButton) {
_recoverButton = [[FUSquareButton alloc] initWithFrame:CGRectMake(0, 0, 44, 74)];
[_recoverButton setTitle:FUBeautyStringWithKey(@"恢复") forState:UIControlStateNormal];
[_recoverButton setImage:[UIImage imageNamed:@"recover_item"] forState:UIControlStateNormal];
_recoverButton.alpha = 0.6;
_recoverButton.userInteractionEnabled = NO;
[_recoverButton addTarget:self action:@selector(recoverAction) forControlEvents:UIControlEventTouchUpInside];
_recoverButton.translatesAutoresizingMaskIntoConstraints = NO;
}
return _recoverButton;
}
-(FUSlider *)slider {
if (!_slider) {
_slider = [[FUSlider alloc] initWithFrame:CGRectMake(56, 16, CGRectGetWidth(self.frame) - 116, FUBeautyFunctionSliderHeight)];
_slider.hidden = YES;
[_slider addTarget:self action:@selector(sliderValueChanged) forControlEvents:UIControlEventValueChanged];
[_slider addTarget:self action:@selector(sliderChangeEnded) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
}
return _slider;
}
@end
@interface FUBeautyShapeCell ()
@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UILabel *textLabel;
@end
@implementation FUBeautyShapeCell
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self.contentView addSubview:self.imageView];
NSLayoutConstraint *imageTop = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1 constant:0];
NSLayoutConstraint *imageLeading = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeading multiplier:1 constant:0];
NSLayoutConstraint *imageTrailing = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTrailing multiplier:1 constant:0];
NSLayoutConstraint *imageHeight = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.imageView attribute:NSLayoutAttributeWidth multiplier:1 constant:0];
[self.contentView addConstraints:@[imageTop, imageLeading, imageTrailing]];
[self.imageView addConstraint:imageHeight];
[self.contentView addSubview:self.textLabel];
NSLayoutConstraint *textTop = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.imageView attribute:NSLayoutAttributeBottom multiplier:1 constant:7];
NSLayoutConstraint *textLeading = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeading multiplier:1 constant:0];
NSLayoutConstraint *textTrailing = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTrailing multiplier:1 constant:0];
[self.contentView addConstraints:@[textTop, textLeading, textTrailing]];
}
return self;
}
- (void)setSelected:(BOOL)selected {
[super setSelected:selected];
if (self.disabled) {
self.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-0", self.imageName]];
self.imageView.alpha = 0.7;
self.textLabel.alpha = 0.7;
} else {
self.imageView.alpha = 1;
self.textLabel.alpha = 1;
BOOL changed = NO;
if (self.defaultInMiddle) {
changed = fabs(self.currentValue - 0.5) > 0.01;
}else{
changed = self.currentValue > 0.01;
}
if (selected) {
self.imageView.image = changed ? [UIImage imageNamed:[NSString stringWithFormat:@"%@-3", self.imageName]] : [UIImage imageNamed:[NSString stringWithFormat:@"%@-2", self.imageName]];
self.textLabel.textColor = [UIColor colorWithRed:103/255.f green:195/255.f blue:103/255.f alpha:1];
} else {
self.imageView.image = changed ? [UIImage imageNamed:[NSString stringWithFormat:@"%@-1", self.imageName]] : [UIImage imageNamed:[NSString stringWithFormat:@"%@-0", self.imageName]];
self.textLabel.textColor = [UIColor whiteColor];
}
}
}
- (UIImageView *)imageView {
if (!_imageView) {
_imageView = [[UIImageView alloc] init];
_imageView.translatesAutoresizingMaskIntoConstraints = NO;
}
return _imageView;
}
- (UILabel *)textLabel {
if (!_textLabel) {
_textLabel = [[UILabel alloc] init];
_textLabel.font = [UIFont systemFontOfSize:14];
_textLabel.textColor = [UIColor whiteColor];
_textLabel.textAlignment = NSTextAlignmentCenter;
_textLabel.adjustsFontSizeToFitWidth = YES;
_textLabel.translatesAutoresizingMaskIntoConstraints = NO;
}
return _textLabel;
}
@end

View File

@@ -0,0 +1,36 @@
//
// FUBeautySkinView.h
// FUBeautyComponent
//
// Created by 项林平 on 2022/6/21.
//
// 美肤&美型视图
#import <UIKit/UIKit.h>
#import "FUBeautySkinViewModel.h"
NS_ASSUME_NONNULL_BEGIN
@interface FUBeautySkinView : UIView
- (instancetype)initWithFrame:(CGRect)frame viewModel:(FUBeautySkinViewModel *)viewModel;
@end
@interface FUBeautySkinCell : UICollectionViewCell
@property (nonatomic, strong, readonly) UIImageView *imageView;
@property (nonatomic, strong, readonly) UILabel *textLabel;
@property (nonatomic, assign) BOOL defaultInMiddle;
@property (nonatomic, assign) double currentValue;
@property (nonatomic, assign) double defaultValue;
@property (nonatomic, copy) NSString *imageName;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,269 @@
//
// FUBeautySkinView.m
// FUBeautyComponent
//
// Created by on 2022/6/21.
//
#import "FUBeautySkinView.h"
#import "FUBeautyDefine.h"
#import <FUCommonUIComponent/FUCommonUIComponent.h>
static NSString * const kFUBeautySkinCellIdentifier = @"FUBeautySkinCell";
@interface FUBeautySkinView ()<UICollectionViewDataSource, UICollectionViewDelegate>
@property (nonatomic, strong) UICollectionView *skinCollectionView;
///
@property (nonatomic, strong) FUSlider *slider;
///
@property (nonatomic, strong) FUSquareButton *recoverButton;
@property (nonatomic, strong) FUBeautySkinViewModel *viewModel;
@end
@implementation FUBeautySkinView
#pragma mark - Initializer
- (instancetype)initWithFrame:(CGRect)frame {
return [self initWithFrame:frame viewModel:[[FUBeautySkinViewModel alloc] init]];
}
- (instancetype)initWithFrame:(CGRect)frame viewModel:(FUBeautySkinViewModel *)viewModel {
self = [super initWithFrame:frame];
if (self) {
self.viewModel = viewModel;
[self configureUI];
[self refreshSubviews];
[self collectionView:self.skinCollectionView didSelectItemAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
}
return self;
}
#pragma mark - UI
- (void)configureUI {
UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:effect];
effectView.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame));
[self addSubview:effectView];
[self addSubview:self.slider];
[self addSubview:self.recoverButton];
NSLayoutConstraint *recoverLeadingConstraint = [NSLayoutConstraint constraintWithItem:self.recoverButton attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1 constant:17];
NSLayoutConstraint *recoverBottomConstraint = [NSLayoutConstraint constraintWithItem:self.recoverButton attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1 constant:-6];
NSLayoutConstraint *recoverWidthConstraint = [NSLayoutConstraint constraintWithItem:self.recoverButton attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:44];
NSLayoutConstraint *recoverHeightConstraint = [NSLayoutConstraint constraintWithItem:self.recoverButton attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:74];
[self addConstraints:@[recoverLeadingConstraint, recoverBottomConstraint]];
[self.recoverButton addConstraints:@[recoverWidthConstraint, recoverHeightConstraint]];
// 线
UIView *verticalLine = [[UIView alloc] init];
verticalLine.backgroundColor = [UIColor colorWithRed:229/255.f green:229/255.f blue:229/255.f alpha:0.2];
verticalLine.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:verticalLine];
NSLayoutConstraint *lineLeadingConstraint = [NSLayoutConstraint constraintWithItem:verticalLine attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.recoverButton attribute:NSLayoutAttributeTrailing multiplier:1 constant:14];
NSLayoutConstraint *lineCenterYConstraint = [NSLayoutConstraint constraintWithItem:verticalLine attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.recoverButton attribute:NSLayoutAttributeCenterY multiplier:1 constant:-15];
NSLayoutConstraint *lineWidthConstraint = [NSLayoutConstraint constraintWithItem:verticalLine attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:1];
NSLayoutConstraint *lineHeightConstraint = [NSLayoutConstraint constraintWithItem:verticalLine attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:24];
[self addConstraints:@[lineLeadingConstraint, lineCenterYConstraint]];
[verticalLine addConstraints:@[lineWidthConstraint, lineHeightConstraint]];
[self addSubview:self.skinCollectionView];
NSLayoutConstraint *collectionLeadingConstraint = [NSLayoutConstraint constraintWithItem:self.skinCollectionView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1 constant:76];
NSLayoutConstraint *collectionTrailingConstraint = [NSLayoutConstraint constraintWithItem:self.skinCollectionView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTrailing multiplier:1 constant:0];
NSLayoutConstraint *collectionBottomConstraint = [NSLayoutConstraint constraintWithItem:self.skinCollectionView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1 constant:0];
NSLayoutConstraint *collectionHeightConstraint = [NSLayoutConstraint constraintWithItem:self.skinCollectionView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:98];
[self addConstraints:@[collectionLeadingConstraint, collectionTrailingConstraint, collectionBottomConstraint]];
[self.skinCollectionView addConstraint:collectionHeightConstraint];
}
- (void)refreshSubviews {
dispatch_async(dispatch_get_main_queue(), ^{
if (self.viewModel.isDefaultValue) {
self.recoverButton.alpha = 0.6;
self.recoverButton.userInteractionEnabled = NO;
} else {
self.recoverButton.alpha = 1;
self.recoverButton.userInteractionEnabled = YES;
}
if (!self.slider.hidden && self.viewModel.selectedIndex >= 0) {
self.slider.bidirection = self.viewModel.beautySkins[self.viewModel.selectedIndex].defaultValueInMiddle;
self.slider.value = self.viewModel.beautySkins[self.viewModel.selectedIndex].currentValue / self.viewModel.beautySkins[self.viewModel.selectedIndex].ratio;
}
[self.skinCollectionView reloadData];
if (self.viewModel.selectedIndex >= 0) {
[self.skinCollectionView selectItemAtIndexPath:[NSIndexPath indexPathForItem:self.viewModel.selectedIndex inSection:0] animated:NO scrollPosition:UICollectionViewScrollPositionNone];
}
});
}
#pragma mark - Event response
- (void)recoverAction {
[FUAlertManager showAlertWithTitle:nil message:FUBeautyStringWithKey(@"是否将所有参数恢复到默认值") cancel:FUBeautyStringWithKey(@"取消") confirm:FUBeautyStringWithKey(@"确定") inController:nil confirmHandler:^{
[self.viewModel recoverAllSkinValuesToDefault];
[self refreshSubviews];
} cancelHandler:nil];
}
- (void)sliderValueChanged {
[self.viewModel setSkinValue:self.slider.value];
}
- (void)sliderChangeEnded {
[self refreshSubviews];
}
#pragma mark - Collection view data source
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return self.viewModel.beautySkins.count;
}
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
FUBeautySkinCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kFUBeautySkinCellIdentifier forIndexPath:indexPath];
FUBeautySkinModel *skin = self.viewModel.beautySkins[indexPath.item];
cell.textLabel.text = FUBeautyStringWithKey(skin.name);
cell.imageName = skin.name;
cell.defaultInMiddle = skin.defaultValueInMiddle;
cell.defaultValue = skin.defaultValue;
cell.currentValue = skin.currentValue;
cell.selected = indexPath.item == self.viewModel.selectedIndex;
return cell;
}
#pragma mark - Collection view delegate
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.item == self.viewModel.selectedIndex) {
return;
}
self.viewModel.selectedIndex = indexPath.item;
FUBeautySkinModel *skin = self.viewModel.beautySkins[indexPath.item];
if (self.slider.hidden) {
self.slider.hidden = NO;
}
self.slider.bidirection = skin.defaultValueInMiddle;
self.slider.value = skin.currentValue / skin.ratio;
}
#pragma mark - Getters
- (UICollectionView *)skinCollectionView {
if (!_skinCollectionView) {
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
layout.itemSize = CGSizeMake(44, 74);
layout.minimumLineSpacing = 22;
layout.minimumInteritemSpacing = 22;
layout.sectionInset = UIEdgeInsetsMake(16, 16, 6, 16);
_skinCollectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
_skinCollectionView.translatesAutoresizingMaskIntoConstraints = NO;
_skinCollectionView.backgroundColor = [UIColor clearColor];
_skinCollectionView.showsVerticalScrollIndicator = NO;
_skinCollectionView.showsHorizontalScrollIndicator = NO;
_skinCollectionView.dataSource = self;
_skinCollectionView.delegate = self;
[_skinCollectionView registerClass:[FUBeautySkinCell class] forCellWithReuseIdentifier:kFUBeautySkinCellIdentifier];
}
return _skinCollectionView;
}
- (FUSquareButton *)recoverButton {
if (!_recoverButton) {
_recoverButton = [[FUSquareButton alloc] initWithFrame:CGRectMake(0, 0, 44, 74)];
[_recoverButton setTitle:FUBeautyStringWithKey(@"恢复") forState:UIControlStateNormal];
[_recoverButton setImage:[UIImage imageNamed:@"recover_item"] forState:UIControlStateNormal];
_recoverButton.alpha = 0.6;
_recoverButton.userInteractionEnabled = NO;
[_recoverButton addTarget:self action:@selector(recoverAction) forControlEvents:UIControlEventTouchUpInside];
_recoverButton.translatesAutoresizingMaskIntoConstraints = NO;
}
return _recoverButton;
}
-(FUSlider *)slider {
if (!_slider) {
_slider = [[FUSlider alloc] initWithFrame:CGRectMake(56, 16, CGRectGetWidth(self.frame) - 116, FUBeautyFunctionSliderHeight)];
_slider.hidden = YES;//67C367
[_slider addTarget:self action:@selector(sliderValueChanged) forControlEvents:UIControlEventValueChanged];
[_slider addTarget:self action:@selector(sliderChangeEnded) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
}
return _slider;
}
@end
@interface FUBeautySkinCell ()
@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UILabel *textLabel;
@end
@implementation FUBeautySkinCell
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self.contentView addSubview:self.imageView];
NSLayoutConstraint *imageTop = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1 constant:0];
NSLayoutConstraint *imageLeading = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeading multiplier:1 constant:0];
NSLayoutConstraint *imageTrailing = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTrailing multiplier:1 constant:0];
NSLayoutConstraint *imageHeight = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.imageView attribute:NSLayoutAttributeWidth multiplier:1 constant:0];
[self.contentView addConstraints:@[imageTop, imageLeading, imageTrailing]];
[self.imageView addConstraint:imageHeight];
[self.contentView addSubview:self.textLabel];
NSLayoutConstraint *textTop = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.imageView attribute:NSLayoutAttributeBottom multiplier:1 constant:7];
NSLayoutConstraint *textLeading = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeading multiplier:1 constant:0];
NSLayoutConstraint *textTrailing = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTrailing multiplier:1 constant:0];
[self.contentView addConstraints:@[textTop, textLeading, textTrailing]];
}
return self;
}
- (void)setSelected:(BOOL)selected {
[super setSelected:selected];
BOOL changed = NO;
if (self.defaultInMiddle) {
changed = fabs(self.currentValue - 0.5) > 0.01;
}else{
changed = self.currentValue > 0.01;
}
if (selected) {
self.imageView.image = changed ? [UIImage imageNamed:[NSString stringWithFormat:@"%@-3", self.imageName]] : [UIImage imageNamed:[NSString stringWithFormat:@"%@-2", self.imageName]];
self.textLabel.textColor = [UIColor colorWithRed:103/255.f green:195/255.f blue:103/255.f alpha:1];
} else {
self.imageView.image = changed ? [UIImage imageNamed:[NSString stringWithFormat:@"%@-1", self.imageName]] : [UIImage imageNamed:[NSString stringWithFormat:@"%@-0", self.imageName]];
self.textLabel.textColor = [UIColor whiteColor];
}
}
- (UIImageView *)imageView {
if (!_imageView) {
_imageView = [[UIImageView alloc] init];
_imageView.translatesAutoresizingMaskIntoConstraints = NO;
}
return _imageView;
}
- (UILabel *)textLabel {
if (!_textLabel) {
_textLabel = [[UILabel alloc] init];
_textLabel.font = [UIFont systemFontOfSize:14];
_textLabel.textColor = [UIColor whiteColor];
_textLabel.textAlignment = NSTextAlignmentCenter;
_textLabel.adjustsFontSizeToFitWidth = YES;
_textLabel.translatesAutoresizingMaskIntoConstraints = NO;
}
return _textLabel;
}
@end