cdts/xdts-ios 3/TreeHole/CYHResetCode/CYH/QMUIKit/QMUIComponents/QMUIDialogViewController.m

964 lines
40 KiB
Mathematica
Raw Normal View History

2023-07-27 09:20:00 +08:00
/**
* Tencent is pleased to support the open source community by making QMUI_iOS available.
* Copyright (C) 2016-2021 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
*/
//
// QMUIDialogViewController.m
// WeRead
//
// Created by QMUI Team on 16/7/8.
//
#import "QMUIDialogViewController.h"
#import "QMUICore.h"
#import "QMUIButton.h"
#import "QMUILabel.h"
#import "QMUITextField.h"
#import "QMUITableViewCell.h"
#import "QMUINavigationTitleView.h"
#import "CALayer+QMUI.h"
#import "UITableView+QMUI.h"
#import "NSString+QMUI.h"
#import "UIScrollView+QMUI.h"
#import "QMUIAppearance.h"
@implementation QMUIDialogViewController (UIAppearance)
+ (instancetype)appearance {
return [QMUIAppearance appearanceForClass:self];
}
+ (void)initialize {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
QMUIDialogViewController *dialogViewControllerAppearance = QMUIDialogViewController.appearance;
dialogViewControllerAppearance.cornerRadius = 6;
dialogViewControllerAppearance.dialogViewMargins = UIEdgeInsetsMake(20, 20, 20, 20); // -didInitialize iPhone X safeAreaInsets
dialogViewControllerAppearance.maximumContentViewWidth = [QMUIHelper screenSizeFor55Inch].width - UIEdgeInsetsGetHorizontalValue(dialogViewControllerAppearance.dialogViewMargins);
dialogViewControllerAppearance.backgroundColor = UIColorWhite;
dialogViewControllerAppearance.titleTintColor = nil;
dialogViewControllerAppearance.titleLabelFont = UIFontMake(16);
dialogViewControllerAppearance.titleLabelTextColor = UIColorMake(53, 60, 70);
dialogViewControllerAppearance.subTitleLabelFont = UIFontMake(12);
dialogViewControllerAppearance.subTitleLabelTextColor = UIColorMake(133, 140, 150);
dialogViewControllerAppearance.headerSeparatorColor = UIColorMake(222, 224, 226);
dialogViewControllerAppearance.headerViewHeight = 48;
dialogViewControllerAppearance.headerViewBackgroundColor = UIColorMake(244, 245, 247);
dialogViewControllerAppearance.contentViewMargins = UIEdgeInsetsZero;
dialogViewControllerAppearance.contentViewBackgroundColor = nil;
dialogViewControllerAppearance.footerSeparatorColor = UIColorMake(222, 224, 226);
dialogViewControllerAppearance.footerViewHeight = 48;
dialogViewControllerAppearance.footerViewBackgroundColor = nil;
dialogViewControllerAppearance.buttonBackgroundColor = nil;
dialogViewControllerAppearance.buttonTitleAttributes = @{NSForegroundColorAttributeName: UIColorBlue};
dialogViewControllerAppearance.buttonHighlightedBackgroundColor = [UIColorBlue colorWithAlphaComponent:.25];
});
}
@end
@interface QMUIDialogViewController ()
@property(nonatomic, assign) BOOL hasCustomContentView;
@property(nonatomic,copy) void (^cancelButtonBlock)(QMUIDialogViewController *dialogViewController);
@property(nonatomic,copy) void (^submitButtonBlock)(QMUIDialogViewController *dialogViewController);
@end
@implementation QMUIDialogViewController
- (void)didInitialize {
[super didInitialize];
[self qmui_applyAppearance];
_contentView = [[UIView alloc] init]; // 使setterself.hasCustomContentView
self.contentView.backgroundColor = self.contentViewBackgroundColor;
_headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, self.headerViewHeight)];
self.headerView.backgroundColor = self.headerViewBackgroundColor;
// 使QMUINavigationTitleViewloadingsubTitle
[self.headerView addSubview:self.titleView];
// 线
_headerViewSeparatorLayer = [CALayer layer];
[self.headerViewSeparatorLayer qmui_removeDefaultAnimations];
self.headerViewSeparatorLayer.backgroundColor = self.headerSeparatorColor.CGColor;
[self.headerView.layer addSublayer:self.headerViewSeparatorLayer];
_footerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, self.footerViewHeight)];
self.footerView.backgroundColor = self.footerViewBackgroundColor;
self.footerView.hidden = YES;
_footerViewSeparatorLayer = [CALayer layer];
[self.footerViewSeparatorLayer qmui_removeDefaultAnimations];
self.footerViewSeparatorLayer.backgroundColor = self.footerSeparatorColor.CGColor;
[self.footerView.layer addSublayer:self.footerViewSeparatorLayer];
_buttonSeparatorLayer = [CALayer layer];
[self.buttonSeparatorLayer qmui_removeDefaultAnimations];
self.buttonSeparatorLayer.backgroundColor = self.footerViewSeparatorLayer.backgroundColor;
self.buttonSeparatorLayer.hidden = YES;
[self.footerView.layer addSublayer:self.buttonSeparatorLayer];
self.modalPresentationViewController = [[QMUIModalPresentationViewController alloc] init];
self.modalPresentationViewController.modal = YES;
}
- (void)setCornerRadius:(CGFloat)cornerRadius {
_cornerRadius = cornerRadius;
if ([self isViewLoaded]) {
self.view.layer.cornerRadius = cornerRadius;
}
}
- (void)setBackgroundColor:(UIColor *)backgroundColor {
_backgroundColor = backgroundColor;
if ([self isViewLoaded]) {
self.view.backgroundColor = backgroundColor;
}
}
- (void)setTitleTintColor:(UIColor *)titleTintColor {
_titleTintColor = titleTintColor;
[self updateTitleViewColor];
}
- (void)setTitleLabelFont:(UIFont *)titleLabelFont {
_titleLabelFont = titleLabelFont;
self.titleView.titleLabel.font = titleLabelFont;
self.titleView.verticalTitleFont = titleLabelFont;
}
- (void)setTitleLabelTextColor:(UIColor *)titleLabelTextColor {
_titleLabelTextColor = titleLabelTextColor;
[self updateTitleViewColor];
}
- (void)setSubTitleLabelFont:(UIFont *)subTitleLabelFont {
_subTitleLabelFont = subTitleLabelFont;
self.titleView.subtitleLabel.font = subTitleLabelFont;
self.titleView.verticalSubtitleFont = subTitleLabelFont;
}
- (void)setSubTitleLabelTextColor:(UIColor *)subTitleLabelTextColor {
_subTitleLabelTextColor = subTitleLabelTextColor;
[self updateTitleViewColor];
}
- (void)updateTitleViewColor {
self.titleView.adjustsSubviewsTintColorAutomatically = !self.titleLabelTextColor && !self.subTitleLabelTextColor;
if (self.titleView.adjustsSubviewsTintColorAutomatically) {
self.titleView.tintColor = self.titleTintColor;// call tintColorDidChange
} else {
self.titleView.titleLabel.textColor = self.titleLabelTextColor ?: (self.titleTintColor ?: self.titleView.tintColor);
self.titleView.subtitleLabel.textColor = self.subTitleLabelTextColor ?: (self.titleTintColor ?: self.titleView.tintColor);
}
}
- (void)setHeaderSeparatorColor:(UIColor *)headerSeparatorColor {
_headerSeparatorColor = headerSeparatorColor;
self.headerViewSeparatorLayer.backgroundColor = headerSeparatorColor.CGColor;
}
- (void)setFooterSeparatorColor:(UIColor *)footerSeparatorColor {
_footerSeparatorColor = footerSeparatorColor;
self.footerViewSeparatorLayer.backgroundColor = footerSeparatorColor.CGColor;
self.buttonSeparatorLayer.backgroundColor = footerSeparatorColor.CGColor;
}
- (void)setHeaderViewHeight:(CGFloat)headerViewHeight {
_headerViewHeight = headerViewHeight;
[self.modalPresentationViewController updateLayout];
}
- (void)setHeaderViewBackgroundColor:(UIColor *)headerViewBackgroundColor {
_headerViewBackgroundColor = headerViewBackgroundColor;
self.headerView.backgroundColor = headerViewBackgroundColor;
}
- (void)setContentViewMargins:(UIEdgeInsets)contentViewMargins {
_contentViewMargins = contentViewMargins;
[self.modalPresentationViewController updateLayout];
}
- (void)setContentViewBackgroundColor:(UIColor *)contentViewBackgroundColor {
_contentViewBackgroundColor = contentViewBackgroundColor;
if (!self.hasCustomContentView) {
self.contentView.backgroundColor = contentViewBackgroundColor;
}
}
- (void)setFooterViewHeight:(CGFloat)footerViewHeight {
_footerViewHeight = footerViewHeight;
}
- (void)setFooterViewBackgroundColor:(UIColor *)footerViewBackgroundColor {
_footerViewBackgroundColor = footerViewBackgroundColor;
self.footerView.backgroundColor = footerViewBackgroundColor;
}
- (void)setButtonTitleAttributes:(NSDictionary<NSString *,id> *)buttonTitleAttributes {
_buttonTitleAttributes = buttonTitleAttributes;
if (self.cancelButton) {
[self.cancelButton setAttributedTitle:[[NSAttributedString alloc] initWithString:[self.cancelButton attributedTitleForState:UIControlStateNormal].string attributes:buttonTitleAttributes] forState:UIControlStateNormal];
}
if (self.submitButton) {
[self.submitButton setAttributedTitle:[[NSAttributedString alloc] initWithString:[self.submitButton attributedTitleForState:UIControlStateNormal].string attributes:buttonTitleAttributes] forState:UIControlStateNormal];
}
}
- (void)setButtonBackgroundColor:(UIColor *)buttonBackgroundColor {
_buttonBackgroundColor = buttonBackgroundColor;
if (self.cancelButton) {
self.cancelButton.backgroundColor = buttonBackgroundColor;
}
if (self.submitButton) {
self.submitButton.backgroundColor = buttonBackgroundColor;
}
}
- (void)setButtonHighlightedBackgroundColor:(UIColor *)buttonHighlightedBackgroundColor {
_buttonHighlightedBackgroundColor = buttonHighlightedBackgroundColor;
if (self.cancelButton) {
self.cancelButton.highlightedBackgroundColor = buttonHighlightedBackgroundColor;
}
if (self.submitButton) {
self.submitButton.highlightedBackgroundColor = buttonHighlightedBackgroundColor;
}
}
BeginIgnoreClangWarning(-Wobjc-missing-super-calls)
- (void)setupNavigationItems {
// self.titleView navigationItem
// [super setupNavigationItems];
}
EndIgnoreClangWarning
- (void)viewDidLoad {
[super viewDidLoad];
// subviews didInitialize dialog 访 self.view viewDidLoad
[self.view addSubview:self.contentView];
[self.view addSubview:self.headerView];
[self.view addSubview:self.footerView];
self.view.clipsToBounds = YES;
self.view.backgroundColor = self.backgroundColor;
self.view.layer.cornerRadius = self.cornerRadius;
}
- (void)setContentView:(UIView *)contentView {
if (_contentView != contentView) {
[_contentView removeFromSuperview];
_contentView = contentView;
if ([self isViewLoaded]) {
[self.view insertSubview:_contentView atIndex:0];
}
self.hasCustomContentView = YES;
} else {
self.hasCustomContentView = NO;
}
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
BOOL isFooterViewShowing = self.footerView && !self.footerView.hidden;
self.headerView.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), self.headerViewHeight);
self.headerViewSeparatorLayer.frame = CGRectFlatMake(0, self.headerViewHeight, CGRectGetWidth(self.view.bounds), PixelOne);
CGFloat headerViewPaddingHorizontal = 16;
CGFloat headerViewContentWidth = CGRectGetWidth(self.headerView.bounds) - headerViewPaddingHorizontal * 2;
CGSize titleViewSize = [self.titleView sizeThatFits:CGSizeMake(headerViewContentWidth, CGFLOAT_MAX)];
CGFloat titleViewWidth = MIN(titleViewSize.width, headerViewContentWidth);
self.titleView.frame = CGRectMake(CGFloatGetCenter(CGRectGetWidth(self.headerView.bounds), titleViewWidth), CGFloatGetCenter(CGRectGetHeight(self.headerView.bounds), titleViewSize.height), titleViewWidth, titleViewSize.height);
if (isFooterViewShowing) {
self.footerView.frame = CGRectMake(0, CGRectGetHeight(self.view.bounds) - self.footerViewHeight, CGRectGetWidth(self.view.bounds), self.footerViewHeight);
self.footerViewSeparatorLayer.frame = CGRectMake(0, -PixelOne, CGRectGetWidth(self.footerView.bounds), PixelOne);
NSUInteger buttonCount = self.footerView.subviews.count;
if (buttonCount == 1) {
QMUIButton *button = self.cancelButton ? : self.submitButton;
button.frame = self.footerView.bounds;
self.buttonSeparatorLayer.hidden = YES;
} else {
CGFloat buttonWidth = flat(CGRectGetWidth(self.footerView.bounds) / buttonCount);
self.cancelButton.frame = CGRectMake(0, 0, buttonWidth, CGRectGetHeight(self.footerView.bounds));
self.submitButton.frame = CGRectMake(CGRectGetMaxX(self.cancelButton.frame), 0, CGRectGetWidth(self.footerView.bounds) - CGRectGetMaxX(self.cancelButton.frame), CGRectGetHeight(self.footerView.bounds));
self.buttonSeparatorLayer.hidden = NO;
self.buttonSeparatorLayer.frame = CGRectMake(CGRectGetMaxX(self.cancelButton.frame), 0, PixelOne, CGRectGetHeight(self.footerView.bounds));
}
}
CGFloat contentViewMinY = CGRectGetMaxY(self.headerView.frame) + self.contentViewMargins.top;
CGFloat contentViewHeight = (isFooterViewShowing ? CGRectGetMinY(self.footerView.frame) - self.contentViewMargins.bottom : CGRectGetHeight(self.view.bounds)) - contentViewMinY;
self.contentView.frame = CGRectMake(self.contentViewMargins.left, contentViewMinY, CGRectGetWidth(self.view.bounds) - UIEdgeInsetsGetHorizontalValue(self.contentViewMargins), contentViewHeight);
}
- (void)addCancelButtonWithText:(NSString *)buttonText block:(void (^)(__kindof QMUIDialogViewController *))block {
[self removeCancelButton];
_cancelButton = [self generateButtonWithText:buttonText];
[self.cancelButton addTarget:self action:@selector(handleCancelButtonEvent:) forControlEvents:UIControlEventTouchUpInside];
self.footerView.hidden = NO;
[self.footerView addSubview:self.cancelButton];
self.cancelButtonBlock = block;
}
- (void)removeCancelButton {
[_cancelButton removeFromSuperview];
self.cancelButtonBlock = nil;
_cancelButton = nil;
if (!self.cancelButton && !self.submitButton) {
self.footerView.hidden = YES;
}
}
- (void)addSubmitButtonWithText:(NSString *)buttonText block:(void (^)(__kindof QMUIDialogViewController *dialogViewController))block {
[self removeSubmitButton];
_submitButton = [self generateButtonWithText:buttonText];
[self.submitButton addTarget:self action:@selector(handleSubmitButtonEvent:) forControlEvents:UIControlEventTouchUpInside];
self.footerView.hidden = NO;
[self.footerView addSubview:self.submitButton];
self.submitButtonBlock = block;
}
- (void)removeSubmitButton {
[_submitButton removeFromSuperview];
self.submitButtonBlock = nil;
_submitButton = nil;
if (!self.cancelButton && !self.submitButton) {
self.footerView.hidden = YES;
}
}
- (QMUIButton *)generateButtonWithText:(NSString *)buttonText {
QMUIButton *button = [[QMUIButton alloc] init];
button.titleLabel.font = UIFontBoldMake((IS_320WIDTH_SCREEN) ? 14 : 15);
button.backgroundColor = self.buttonBackgroundColor;
button.highlightedBackgroundColor = self.buttonHighlightedBackgroundColor;
[button setAttributedTitle:[[NSAttributedString alloc] initWithString:buttonText attributes:self.buttonTitleAttributes] forState:UIControlStateNormal];
return button;
}
- (void)handleCancelButtonEvent:(QMUIButton *)cancelButton {
[self hideWithAnimated:YES completion:nil];
if (self.cancelButtonBlock) {
self.cancelButtonBlock(self);
}
}
- (void)handleSubmitButtonEvent:(QMUIButton *)submitButton {
if (self.submitButtonBlock) {
// self block dialog
self.submitButtonBlock(self);
}
}
- (void)show {
[self showWithAnimated:YES completion:nil];
}
- (void)showWithAnimated:(BOOL)animated completion:(void (^)(BOOL))completion {
self.modalPresentationViewController.contentViewMargins = self.dialogViewMargins;
self.modalPresentationViewController.maximumContentViewWidth = self.maximumContentViewWidth;
self.modalPresentationViewController.contentViewController = self;
[self.modalPresentationViewController showWithAnimated:YES completion:completion];
}
- (void)hide {
[self hideWithAnimated:YES completion:nil];
}
- (void)hideWithAnimated:(BOOL)animated completion:(void (^)(BOOL))completion {
[self.modalPresentationViewController hideWithAnimated:animated completion:^(BOOL finished) {
if (completion) {
completion(finished);
}
self.modalPresentationViewController.contentViewController = nil;
}];
}
#pragma mark - <QMUIModalPresentationContentViewControllerProtocol>
- (CGSize)preferredContentSizeInModalPresentationViewController:(QMUIModalPresentationViewController *)controller keyboardHeight:(CGFloat)keyboardHeight limitSize:(CGSize)limitSize {
if (!self.hasCustomContentView) {
return limitSize;
}
BOOL isFooterViewShowing = self.footerView && !self.footerView.hidden;
CGFloat footerHeight = isFooterViewShowing ? self.footerViewHeight : 0;
CGFloat contentViewVerticalMargin = UIEdgeInsetsGetVerticalValue(self.contentViewMargins);
CGSize contentViewLimitSize = CGSizeMake(limitSize.width, limitSize.height - self.headerViewHeight - contentViewVerticalMargin - footerHeight);
CGSize contentViewSize = [self.contentView sizeThatFits:contentViewLimitSize];
CGSize finalSize = CGSizeMake(MIN(limitSize.width, contentViewSize.width), MIN(limitSize.height, self.headerViewHeight + contentViewSize.height + contentViewVerticalMargin + footerHeight));
return finalSize;
}
#pragma mark - <QMUIModalPresentationComponentProtocol>
- (void)hideModalPresentationComponent {
[self hideWithAnimated:NO completion:nil];
}
@end
@implementation QMUIDialogSelectionViewController (UIAppearance)
+ (instancetype)appearance {
return [QMUIAppearance appearanceForClass:self];
}
+ (void)initialize {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
QMUIDialogSelectionViewController.appearance.rowHeight = TableViewCellNormalHeight;
});
}
@end
const NSInteger QMUIDialogSelectionViewControllerSelectedItemIndexNone = -1;
@interface QMUIDialogSelectionViewController ()
@property(nonatomic,strong,readwrite) QMUITableView *tableView;
@end
@implementation QMUIDialogSelectionViewController
- (void)didInitialize {
[super didInitialize];
self.selectedItemIndex = QMUIDialogSelectionViewControllerSelectedItemIndexNone;
self.selectedItemIndexes = [[NSMutableSet alloc] init];
self.tableView = [[QMUITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
self.tableView.dataSource = self;
self.tableView.delegate = self;
self.tableView.alwaysBounceVertical = NO;
self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
// tableView sizeThatFits: dialog estimated
self.tableView.estimatedRowHeight = 0;
self.tableView.estimatedSectionHeaderHeight = 0;
self.tableView.estimatedSectionFooterHeight = 0;
self.contentView = self.tableView;
self.tableView.backgroundColor = self.contentViewBackgroundColor;// QMUIDialogSelectionViewController 使 customContentView self.contentViewBackgroundColor
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
//
if (self.selectedItemIndex != QMUIDialogSelectionViewControllerSelectedItemIndexNone && self.selectedItemIndex < self.items.count && ![self.tableView qmui_cellVisibleAtIndexPath:[NSIndexPath indexPathForRow:self.selectedItemIndex inSection:0]]) {
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.selectedItemIndex inSection:0] atScrollPosition:UITableViewScrollPositionMiddle animated:animated];
}
}
- (void)setContentViewBackgroundColor:(UIColor *)contentViewBackgroundColor {
[super setContentViewBackgroundColor:contentViewBackgroundColor];
self.tableView.backgroundColor = contentViewBackgroundColor;
}
- (void)setItems:(NSArray<NSString *> *)items {
_items = [items copy];
[self.tableView reloadData];
if (self.modalPresentationViewController.visible) {
[self.modalPresentationViewController updateLayout];
}
}
- (void)setSelectedItemIndex:(NSInteger)selectedItemIndex {
[self.selectedItemIndexes removeAllObjects];
_selectedItemIndex = selectedItemIndex;
}
- (void)setSelectedItemIndexes:(NSMutableSet<NSNumber *> *)selectedItemIndexes {
self.selectedItemIndex = QMUIDialogSelectionViewControllerSelectedItemIndexNone;
_selectedItemIndexes = selectedItemIndexes;
}
- (void)setAllowsMultipleSelection:(BOOL)allowsMultipleSelection {
_allowsMultipleSelection = allowsMultipleSelection;
self.selectedItemIndex = QMUIDialogSelectionViewControllerSelectedItemIndexNone;
}
- (void)setRowHeight:(CGFloat)rowHeight {
_rowHeight = rowHeight;
[self.tableView setNeedsLayout];
}
#pragma mark - <QMUITableViewDataSource, QMUITableViewDelegate>
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.items.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifier = @"cell";
QMUITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
cell = [[QMUITableViewCell alloc] initForTableView:tableView withStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
cell.backgroundColor = nil;// 使 tableView
}
cell.textLabel.text = self.items[indexPath.row];
if (self.allowsMultipleSelection) {
//
if ([self.selectedItemIndexes containsObject:@(indexPath.row)]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
} else {
//
if (self.selectedItemIndex == indexPath.row) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
[cell updateCellAppearanceWithIndexPath:indexPath];
if (self.cellForItemBlock) {
self.cellForItemBlock(self, cell, indexPath.row);
}
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (self.heightForItemBlock) {
return self.heightForItemBlock(self, indexPath.row);
}
return self.rowHeight;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// cell
if (!self.allowsMultipleSelection && self.selectedItemIndex == indexPath.row) {
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
return;
}
// cellreturn
if (self.canSelectItemBlock && !self.canSelectItemBlock(self, indexPath.row)) {
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
return;
}
if (self.allowsMultipleSelection) {
if ([self.selectedItemIndexes containsObject:@(indexPath.row)]) {
// cell
[self.selectedItemIndexes removeObject:@(indexPath.row)];
if (self.didDeselectItemBlock) {
self.didDeselectItemBlock(self, indexPath.row);
}
} else {
[self.selectedItemIndexes addObject:@(indexPath.row)];
if (self.didSelectItemBlock) {
self.didSelectItemBlock(self, indexPath.row);
}
}
if ([tableView qmui_cellVisibleAtIndexPath:indexPath]) {
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
} else {
BOOL isSelectedIndexPathBeforeVisible = NO;
// cellcell
NSIndexPath *selectedIndexPathBefore = nil;
if (self.selectedItemIndex != QMUIDialogSelectionViewControllerSelectedItemIndexNone) {
selectedIndexPathBefore = [NSIndexPath indexPathForRow:self.selectedItemIndex inSection:0];
if (self.didDeselectItemBlock) {
self.didDeselectItemBlock(self, selectedIndexPathBefore.row);
}
isSelectedIndexPathBeforeVisible = [tableView qmui_cellVisibleAtIndexPath:selectedIndexPathBefore];
}
self.selectedItemIndex = indexPath.row;
// cellcellcellForRow
if (isSelectedIndexPathBeforeVisible) {
[tableView reloadRowsAtIndexPaths:@[selectedIndexPathBefore, indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else {
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
if (self.didSelectItemBlock) {
self.didSelectItemBlock(self, indexPath.row);
}
}
}
@end
@implementation QMUIDialogTextFieldViewController (UIAppearance)
+ (instancetype)appearance {
return [QMUIAppearance appearanceForClass:self];
}
+ (void)initialize {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
QMUIDialogTextFieldViewController *dialogTextFieldViewControllerAppearance = QMUIDialogTextFieldViewController.appearance;
dialogTextFieldViewControllerAppearance.textFieldLabelFont = UIFontBoldMake(12);
dialogTextFieldViewControllerAppearance.textFieldLabelTextColor = UIColorGrayDarken;
dialogTextFieldViewControllerAppearance.textFieldFont = UIFontMake(17);
dialogTextFieldViewControllerAppearance.textFieldTextColor = UIColorBlack;
dialogTextFieldViewControllerAppearance.textFieldSeparatorColor = UIColorSeparator;
dialogTextFieldViewControllerAppearance.textFieldLabelMargins = UIEdgeInsetsMake(16, 22, -2, 22);
dialogTextFieldViewControllerAppearance.textFieldMargins = UIEdgeInsetsMake(16, 16, 10, 16);
dialogTextFieldViewControllerAppearance.textFieldHeight = 25;
dialogTextFieldViewControllerAppearance.textFieldSeparatorInsets = UIEdgeInsetsMake(0, 0, 16, 0);
});
}
@end
@interface QMUIDialogTextFieldViewController ()<QMUITextFieldDelegate>
@property(nonatomic, strong) UIScrollView *scrollView;
@property(nonatomic, strong) NSMutableArray<QMUILabel *> *mutableTitleLabels;
@property(nonatomic, strong) NSMutableArray<QMUITextField *> *mutableTextFields;
@property(nonatomic, strong) NSMutableArray<CALayer *> *mutableSeparatorLayers;
@end
@implementation QMUIDialogTextFieldViewController
- (void)didInitialize {
[super didInitialize];
self.mutableTitleLabels = [[NSMutableArray alloc] init];
self.mutableTextFields = [[NSMutableArray alloc] init];
self.mutableSeparatorLayers = [[NSMutableArray alloc] init];
self.shouldManageTextFieldsReturnEventAutomatically = YES;
self.enablesSubmitButtonAutomatically = YES;
self.scrollView = [[UIScrollView alloc] init];
self.scrollView.scrollsToTop = NO;
self.scrollView.clipsToBounds = YES;
self.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
self.contentView = self.scrollView;
self.scrollView.backgroundColor = self.contentViewBackgroundColor;
}
- (void)addTextFieldWithTitle:(NSString *)textFieldTitle configurationHandler:(void (^)(QMUILabel *titleLabel, QMUITextField *textField, CALayer *separatorLayer))configurationHandler {
QMUILabel *label = [self generateTextFieldTitleLabel];
label.text = textFieldTitle;
if (textFieldTitle.length <= 0) {
label.hidden = YES;
}
[self.mutableTitleLabels addObject:label];
QMUITextField *textField = [self generateTextField];
[self.mutableTextFields addObject:textField];
CALayer *separatorLayer = [self generateTextFieldSeparatorLayer];
[self.mutableSeparatorLayers addObject:separatorLayer];
if (configurationHandler) {
configurationHandler(label, textField, separatorLayer);
}
}
- (QMUILabel *)generateTextFieldTitleLabel {
QMUILabel *textFieldLabel = [[QMUILabel alloc] init];
textFieldLabel.font = self.textFieldLabelFont;
textFieldLabel.textColor = self.textFieldLabelTextColor;
[self.contentView addSubview:textFieldLabel];
return textFieldLabel;
}
- (QMUITextField *)generateTextField {
QMUITextField *textField = [[QMUITextField alloc] init];
textField.delegate = self;
textField.font = self.textFieldFont;
textField.textColor = self.textFieldTextColor;
textField.backgroundColor = nil;
textField.returnKeyType = UIReturnKeyNext;
textField.clearButtonMode = UITextFieldViewModeWhileEditing;
textField.enablesReturnKeyAutomatically = self.enablesSubmitButtonAutomatically;
[textField addTarget:self action:@selector(handleTextFieldTextDidChangeEvent:) forControlEvents:UIControlEventEditingChanged];
[self.contentView addSubview:textField];
return textField;
}
- (CALayer *)generateTextFieldSeparatorLayer {
CALayer *textFieldSeparatorLayer = [CALayer qmui_separatorLayer];
textFieldSeparatorLayer.backgroundColor = self.textFieldSeparatorColor.CGColor;
[self.contentView.layer addSublayer:textFieldSeparatorLayer];
return textFieldSeparatorLayer;
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
// contentView
QMUIAssert(self.mutableTitleLabels.count == self.mutableTextFields.count && self.mutableTextFields.count == self.mutableSeparatorLayers.count, NSStringFromClass(self.class), @"标题、输入框、分隔线的数量不匹配");
CGFloat minY = 0;
for (NSInteger i = 0; i < self.mutableTitleLabels.count; i++) {
QMUILabel *label = self.mutableTitleLabels[i];
QMUITextField *textField = self.mutableTextFields[i];
CALayer *separatorLayer = self.mutableSeparatorLayers[i];
if (!label.hidden) {
[label sizeToFit];
label.frame = CGRectFlatMake(self.textFieldLabelMargins.left, minY + self.textFieldLabelMargins.top, CGRectGetWidth(self.contentView.bounds) - UIEdgeInsetsGetHorizontalValue(self.textFieldLabelMargins), CGRectGetHeight(label.frame));
minY = CGRectGetMaxY(label.frame) + self.textFieldLabelMargins.bottom;
}
textField.frame = CGRectFlatMake(self.textFieldMargins.left, minY + self.textFieldMargins.top, CGRectGetWidth(self.contentView.bounds) - UIEdgeInsetsGetHorizontalValue(self.textFieldMargins), self.textFieldHeight);
minY = CGRectGetMaxY(textField.frame) + self.textFieldMargins.bottom;
// textField textField.textInsets
if (!separatorLayer.hidden) {
CGFloat separatorMinX = CGRectGetMinX(textField.frame) + textField.textInsets.left + self.textFieldSeparatorInsets.left;
CGFloat separatorWidth = CGRectGetWidth(textField.frame) - UIEdgeInsetsGetHorizontalValue(textField.textInsets) - UIEdgeInsetsGetHorizontalValue(self.textFieldSeparatorInsets);
separatorLayer.frame = CGRectMake(separatorMinX, minY + self.textFieldSeparatorInsets.top, separatorWidth, PixelOne);
minY = CGRectGetMinY(separatorLayer.frame) + self.textFieldSeparatorInsets.bottom;// minY 线
}
}
self.scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.scrollView.bounds), minY);
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.mutableTextFields.firstObject becomeFirstResponder];
if (self.enablesSubmitButtonAutomatically) {
// enablesReturnKeyAutomatically
self.enablesSubmitButtonAutomatically = self.enablesSubmitButtonAutomatically;
}
// Done Next
self.mutableTextFields.lastObject.returnKeyType = UIReturnKeyDone;
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.view endEditing:YES];
}
#pragma mark - Getters & Setters
- (void)setContentViewBackgroundColor:(UIColor *)contentViewBackgroundColor {
[super setContentViewBackgroundColor:contentViewBackgroundColor];
self.scrollView.backgroundColor = contentViewBackgroundColor;
}
- (void)setTextFieldLabelFont:(UIFont *)textFieldLabelFont {
_textFieldLabelFont = textFieldLabelFont;
[self.mutableTitleLabels enumerateObjectsUsingBlock:^(QMUILabel * _Nonnull label, NSUInteger idx, BOOL * _Nonnull stop) {
label.font = textFieldLabelFont;
}];
if (self.mutableTitleLabels.count) {
[self.modalPresentationViewController updateLayout];
}
}
- (void)setTextFieldLabelTextColor:(UIColor *)textFieldLabelTextColor {
_textFieldLabelTextColor = textFieldLabelTextColor;
[self.mutableTitleLabels enumerateObjectsUsingBlock:^(QMUILabel * _Nonnull label, NSUInteger idx, BOOL * _Nonnull stop) {
label.textColor = textFieldLabelTextColor;
}];
}
- (void)setTextFieldFont:(UIFont *)textFieldFont {
_textFieldFont = textFieldFont;
[self.mutableTextFields enumerateObjectsUsingBlock:^(QMUITextField * _Nonnull textField, NSUInteger idx, BOOL * _Nonnull stop) {
textField.font = textFieldFont;
}];
}
- (void)setTextFieldTextColor:(UIColor *)textFieldTextColor {
_textFieldTextColor = textFieldTextColor;
[self.mutableTextFields enumerateObjectsUsingBlock:^(QMUITextField * _Nonnull textField, NSUInteger idx, BOOL * _Nonnull stop) {
textField.textColor = textFieldTextColor;
}];
}
- (void)setTextFieldSeparatorColor:(UIColor *)textFieldSeparatorColor {
_textFieldSeparatorColor = textFieldSeparatorColor;
[self.mutableSeparatorLayers enumerateObjectsUsingBlock:^(CALayer * _Nonnull layer, NSUInteger idx, BOOL * _Nonnull stop) {
layer.backgroundColor = textFieldSeparatorColor.CGColor;
}];
}
- (void)setTextFieldLabelMargins:(UIEdgeInsets)textFieldLabelMargins {
_textFieldLabelMargins = textFieldLabelMargins;
if (self.mutableTitleLabels.count) {
[self.modalPresentationViewController updateLayout];
}
}
- (void)setTextFieldMargins:(UIEdgeInsets)textFieldMargins {
_textFieldMargins = textFieldMargins;
if (self.textFields.count) {
[self.modalPresentationViewController updateLayout];
}
}
- (void)setTextFieldHeight:(CGFloat)textFieldHeight {
_textFieldHeight = textFieldHeight;
if (self.textFields.count) {
[self.modalPresentationViewController updateLayout];
}
}
- (void)setTextFieldSeparatorInsets:(UIEdgeInsets)textFieldSeparatorInsets {
_textFieldSeparatorInsets = textFieldSeparatorInsets;
if (self.mutableSeparatorLayers.count) {
[self.modalPresentationViewController updateLayout];
}
}
- (NSArray<QMUILabel *> *)textFieldTitleLabels {
return self.mutableTitleLabels.copy;
}
- (NSArray<QMUITextField *> *)textFields {
return self.mutableTextFields.copy;
}
- (NSArray<CALayer *> *)textFieldSeparatorLayers {
return self.mutableSeparatorLayers.copy;
}
#pragma mark - Submit Button Enables
- (void)setEnablesSubmitButtonAutomatically:(BOOL)enablesSubmitButtonAutomatically {
_enablesSubmitButtonAutomatically = enablesSubmitButtonAutomatically;
[self.mutableTextFields enumerateObjectsUsingBlock:^(QMUITextField * _Nonnull textField, NSUInteger idx, BOOL * _Nonnull stop) {
// enablesSubmitButtonAutomatically
if (enablesSubmitButtonAutomatically && idx != self.mutableTextFields.count - 1) {
textField.enablesReturnKeyAutomatically = NO;
} else {
textField.enablesReturnKeyAutomatically = enablesSubmitButtonAutomatically;
}
}];
if (enablesSubmitButtonAutomatically) {
[self updateSubmitButtonEnables];
}
}
- (void)updateSubmitButtonEnables {
self.submitButton.enabled = [self shouldEnabledSubmitButton];
}
- (BOOL)shouldEnabledSubmitButton {
if (self.shouldEnableSubmitButtonBlock) {
return self.shouldEnableSubmitButtonBlock(self);
}
if (self.enablesSubmitButtonAutomatically) {
__block BOOL enabled = NO;
[self.mutableTextFields enumerateObjectsUsingBlock:^(QMUITextField * _Nonnull textField, NSUInteger idx, BOOL * _Nonnull stop) {
NSInteger textLength = textField.text.qmui_trim.length;
enabled = 0 < textLength && textLength <= textField.maximumTextLength;
if (!enabled) {
*stop = YES;
}
}];
return enabled;
}
return YES;
}
- (void)handleTextFieldTextDidChangeEvent:(QMUITextField *)textField {
if ([self.mutableTextFields containsObject:textField]) {
[self updateSubmitButtonEnables];
}
}
- (void)addSubmitButtonWithText:(NSString *)buttonText block:(void (^)(__kindof QMUIDialogViewController *dialogViewController))block {
[super addSubmitButtonWithText:buttonText block:block];
[self updateSubmitButtonEnables];
}
#pragma mark - <QMUIModalPresentationContentViewControllerProtocol>
- (CGSize)preferredContentSizeInModalPresentationViewController:(QMUIModalPresentationViewController *)controller keyboardHeight:(CGFloat)keyboardHeight limitSize:(CGSize)limitSize {
CGFloat textFieldLabelHeight = 0;
for (QMUILabel *label in self.mutableTitleLabels) {
if (!label.hidden) {
CGFloat labelHeight = flat([label sizeThatFits:CGSizeMax].height);
textFieldLabelHeight += labelHeight + UIEdgeInsetsGetVerticalValue(self.textFieldLabelMargins);
}
}
CGFloat textFieldHeight = self.mutableTextFields.count * (self.textFieldHeight + UIEdgeInsetsGetVerticalValue(self.textFieldMargins));
CGFloat separatorHeight = 0;
for (CALayer *separatorLayer in self.mutableSeparatorLayers) {
if (!separatorLayer.hidden) {
separatorHeight += UIEdgeInsetsGetVerticalValue(self.textFieldSeparatorInsets);
}
}
CGFloat contentHeight = textFieldLabelHeight + textFieldHeight + separatorHeight + UIEdgeInsetsGetVerticalValue(self.scrollView.adjustedContentInset);
CGFloat contentViewVerticalMargin = UIEdgeInsetsGetVerticalValue(self.contentViewMargins);
BOOL isFooterViewShowing = self.footerView && !self.footerView.hidden;
CGFloat footerHeight = isFooterViewShowing ? self.footerViewHeight : 0;
CGSize finalSize = CGSizeMake(limitSize.width, MIN(limitSize.height, self.headerViewHeight + contentHeight + contentViewVerticalMargin + footerHeight));
return finalSize;
}
#pragma mark - <QMUITextFieldDelegate>
- (BOOL)textFieldShouldReturn:(QMUITextField *)textField {
if (!self.shouldManageTextFieldsReturnEventAutomatically) {
return NO;
}
if (![self.mutableTextFields containsObject:textField]) {
return NO;
}
if (self.mutableTextFields.count > 1) {
if (textField != self.mutableTextFields.lastObject && textField.returnKeyType == UIReturnKeyNext) {
NSUInteger index = [self.mutableTextFields indexOfObject:textField];
[self.mutableTextFields[index + 1] becomeFirstResponder];
return YES;
}
}
// submitButton cancel UIAlertController
if (self.submitButton.enabled) {
[self.submitButton sendActionsForControlEvents:UIControlEventTouchUpInside];
return NO;
}
return NO;
}
@end