重构了KBFunctionView

This commit is contained in:
2025-11-12 16:03:30 +08:00
parent 62f3ddae4a
commit fea22aecab
6 changed files with 294 additions and 68 deletions

View File

@@ -0,0 +1,27 @@
//
// KBFunctionTagListView.h
// 封装标签列表UICollectionView
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@class KBFunctionTagListView;
@protocol KBFunctionTagListViewDelegate <NSObject>
@optional
- (void)tagListView:(KBFunctionTagListView *)view didSelectIndex:(NSInteger)index title:(NSString *)title;
@end
@interface KBFunctionTagListView : UIView
@property (nonatomic, weak, nullable) id<KBFunctionTagListViewDelegate> delegate;
@property (nonatomic, strong, readonly) UICollectionView *collectionView;
- (void)setItems:(NSArray<NSString *> *)items;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,68 @@
//
// KBFunctionTagListView.m
//
#import "KBFunctionTagListView.h"
#import "KBFunctionTagCell.h"
static NSString * const kKBFunctionTagCellId2 = @"KBFunctionTagCellId2";
@interface KBFunctionTagListView () <UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
@property (nonatomic, strong) UICollectionView *collectionViewInternal;
@property (nonatomic, copy) NSArray<NSString *> *items;
@end
@implementation KBFunctionTagListView
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout new];
_collectionViewInternal = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
_collectionViewInternal.backgroundColor = [UIColor clearColor];
_collectionViewInternal.dataSource = self;
_collectionViewInternal.delegate = self;
[_collectionViewInternal registerClass:[KBFunctionTagCell class] forCellWithReuseIdentifier:kKBFunctionTagCellId2];
[self addSubview:_collectionViewInternal];
_collectionViewInternal.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[_collectionViewInternal.topAnchor constraintEqualToAnchor:self.topAnchor],
[_collectionViewInternal.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
[_collectionViewInternal.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
[_collectionViewInternal.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
]];
_items = @[];
}
return self;
}
- (void)setItems:(NSArray<NSString *> *)items { _items = [items copy]; [self.collectionViewInternal reloadData]; }
- (UICollectionView *)collectionView { return self.collectionViewInternal; }
#pragma mark - UICollectionView
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return self.items.count; }
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
KBFunctionTagCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kKBFunctionTagCellId2 forIndexPath:indexPath];
cell.titleLabel.text = (indexPath.item < self.items.count) ? self.items[indexPath.item] : @"";
return cell;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
CGFloat totalW = collectionView.bounds.size.width; CGFloat space = 10.0; NSInteger columns = 3;
CGFloat width = floor((totalW - space * (columns - 1)) / columns);
return CGSizeMake(width, 48);
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { return 10.0; }
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { return 12.0; }
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
if ([self.delegate respondsToSelector:@selector(tagListView:didSelectIndex:title:)]) {
NSString *title = (indexPath.item < self.items.count) ? self.items[indexPath.item] : @"";
[self.delegate tagListView:self didSelectIndex:indexPath.item title:title];
}
}
@end

View File

@@ -0,0 +1,28 @@
//
// KBStreamOverlayView.h
// 自带关闭按钮的流式展示层,内部持有 KBStreamTextView。
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@class KBStreamTextView, KBStreamOverlayView;
@protocol KBStreamOverlayViewDelegate <NSObject>
@optional
- (void)streamOverlayDidTapClose:(KBStreamOverlayView *)overlay;
@end
@interface KBStreamOverlayView : UIView
@property (nonatomic, strong, readonly) KBStreamTextView *textView;
@property (nonatomic, weak, nullable) id<KBStreamOverlayViewDelegate> delegate;
- (void)appendChunk:(NSString *)text;
- (void)finish;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,80 @@
//
// KBStreamOverlayView.m
//
#import "KBStreamOverlayView.h"
#import "KBStreamTextView.h"
#import "Masonry.h"
@interface KBStreamOverlayView ()
@property (nonatomic, strong) KBStreamTextView *textViewInternal;
@property (nonatomic, strong) UIButton *closeButton;
@end
@implementation KBStreamOverlayView
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.92];
self.layer.cornerRadius = 12.0; self.layer.masksToBounds = YES;
[self addSubview:self.textViewInternal];
[self addSubview:self.closeButton];
[self.textViewInternal mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.mas_left).offset(0);
make.right.equalTo(self.mas_right).offset(0);
make.bottom.equalTo(self.mas_bottom).offset(0);
make.top.equalTo(self.mas_top).offset(0);
}];
[self.closeButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.mas_top).offset(8);
make.right.equalTo(self.mas_right).offset(-8);
make.height.mas_equalTo(28);
make.width.mas_greaterThanOrEqualTo(56);
}];
}
return self;
}
- (KBStreamTextView *)textViewInternal {
if (!_textViewInternal) {
_textViewInternal = [[KBStreamTextView alloc] init];
}
return _textViewInternal;
}
- (UIButton *)closeButton {
if (!_closeButton) {
UIButton *del = [UIButton buttonWithType:UIButtonTypeSystem];
del.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.35];
del.layer.cornerRadius = 14; del.layer.masksToBounds = YES;
del.titleLabel.font = [UIFont systemFontOfSize:13 weight:UIFontWeightSemibold];
[del setTitle:@"删除" forState:UIControlStateNormal];
[del setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[del addTarget:self action:@selector(onTapClose) forControlEvents:UIControlEventTouchUpInside];
_closeButton = del;
}
return _closeButton;
}
- (void)onTapClose {
if ([self.delegate respondsToSelector:@selector(streamOverlayDidTapClose:)]) {
[self.delegate streamOverlayDidTapClose:self];
}
}
- (void)appendChunk:(NSString *)text {
if (text.length == 0) return;
[self.textViewInternal appendStreamText:text];
}
- (void)finish {
[self.textViewInternal finishStreaming];
}
- (KBStreamTextView *)textView { return self.textViewInternal; }
@end