重构了KBFunctionView
This commit is contained in:
27
CustomKeyboard/View/Function/KBFunctionTagListView.h
Normal file
27
CustomKeyboard/View/Function/KBFunctionTagListView.h
Normal 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
|
||||
|
||||
68
CustomKeyboard/View/Function/KBFunctionTagListView.m
Normal file
68
CustomKeyboard/View/Function/KBFunctionTagListView.m
Normal 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
|
||||
28
CustomKeyboard/View/Function/KBStreamOverlayView.h
Normal file
28
CustomKeyboard/View/Function/KBStreamOverlayView.h
Normal 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
|
||||
|
||||
80
CustomKeyboard/View/Function/KBStreamOverlayView.m
Normal file
80
CustomKeyboard/View/Function/KBStreamOverlayView.m
Normal 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
|
||||
|
||||
@@ -17,30 +17,25 @@
|
||||
#import "KBSkinManager.h"
|
||||
#import "KBURLOpenBridge.h" // 兜底从扩展侧直接尝试 openURL:
|
||||
#import "KBStreamTextView.h" // 流式文本视图
|
||||
#import "KBStreamOverlayView.h" // 带关闭按钮的流式层
|
||||
#import "KBFunctionTagListView.h"
|
||||
#import "KBStreamFetcher.h" // 网络流封装
|
||||
|
||||
static NSString * const kKBFunctionTagCellId = @"KBFunctionTagCellId";
|
||||
|
||||
@interface KBFunctionView () <UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, KBFunctionBarViewDelegate>
|
||||
@interface KBFunctionView () <KBFunctionBarViewDelegate, KBStreamOverlayViewDelegate, KBFunctionTagListViewDelegate>
|
||||
// UI
|
||||
@property (nonatomic, strong) KBFunctionBarView *barViewInternal;
|
||||
@property (nonatomic, strong) KBFunctionPasteView *pasteViewInternal;
|
||||
@property (nonatomic, strong) UICollectionView *collectionViewInternal;
|
||||
@property (nonatomic, strong) KBFunctionTagListView *tagListView;
|
||||
@property (nonatomic, strong) UIView *rightButtonContainer; // 右侧竖排按钮容器
|
||||
@property (nonatomic, strong) UIButton *pasteButtonInternal;
|
||||
@property (nonatomic, strong) UIButton *deleteButtonInternal;
|
||||
@property (nonatomic, strong) UIButton *clearButtonInternal;
|
||||
@property (nonatomic, strong) UIButton *sendButtonInternal;
|
||||
|
||||
// 临时:点击标签后展示的“流式文本视图”与其删除按钮
|
||||
@property (nonatomic, strong, nullable) KBStreamTextView *streamTextView;
|
||||
@property (nonatomic, strong, nullable) UIButton *streamDeleteButton;
|
||||
// 流式测试数据 & 定时器
|
||||
@property (nonatomic, strong, nullable) NSTimer *streamMockTimer;
|
||||
@property (nonatomic, strong, nullable) NSArray<NSString *> *streamMockChunks;
|
||||
@property (nonatomic, assign) NSInteger streamMockIndex;
|
||||
@property (nonatomic, copy, nullable) NSString *streamMockSource; // 连续文本源(包含 \t 作为分段)
|
||||
@property (nonatomic, assign) NSInteger streamMockCursor; // 当前光标位置
|
||||
// 叠层:流式文本视图 + 关闭按钮
|
||||
@property (nonatomic, strong, nullable) KBStreamOverlayView *streamOverlay;
|
||||
|
||||
// 网络流式(封装)
|
||||
@property (nonatomic, strong, nullable) KBStreamFetcher *streamFetcher;
|
||||
@@ -152,9 +147,9 @@ static NSString * const kKBFunctionTagCellId = @"KBFunctionTagCellId";
|
||||
make.height.mas_equalTo(48);
|
||||
}];
|
||||
|
||||
// 3. CollectionView
|
||||
[self addSubview:self.collectionViewInternal];
|
||||
[self.collectionViewInternal mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
// 3. Tag List View
|
||||
[self addSubview:self.tagListView];
|
||||
[self.tagListView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(self.mas_left).offset(12);
|
||||
make.right.equalTo(self.rightButtonContainer.mas_left).offset(-12);
|
||||
make.top.equalTo(self.pasteViewInternal.mas_bottom).offset(10);
|
||||
@@ -167,7 +162,7 @@ static NSString * const kKBFunctionTagCellId = @"KBFunctionTagCellId";
|
||||
- (void)reloadDemoData {
|
||||
// 演示数据(可由外部替换)
|
||||
self.itemsInternal = @[@"高情商", @"暖味拉扯", @"风趣幽默", @"撩女生", @"社交惬匿", @"情场高手", @"一枚暖男", @"聊天搭子", @"表达爱意", @"更多话术"];
|
||||
[self.collectionViewInternal reloadData];
|
||||
[self.tagListView setItems:self.itemsInternal];
|
||||
}
|
||||
|
||||
#pragma mark - UICollectionView
|
||||
@@ -201,43 +196,21 @@ static NSString * const kKBFunctionTagCellId = @"KBFunctionTagCellId";
|
||||
|
||||
- (void)kb_showStreamTextViewIfNeededWithTitle:(NSString *)title {
|
||||
// 已有则不重复创建
|
||||
if (self.streamTextView.superview) { return; }
|
||||
if (self.streamOverlay.superview) { return; }
|
||||
|
||||
// 隐藏标签列表,使用同一区域展示流式文本
|
||||
self.collectionViewInternal.hidden = YES;
|
||||
self.tagListView.hidden = YES;
|
||||
|
||||
KBStreamTextView *sv = [[KBStreamTextView alloc] init];
|
||||
sv.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.92];
|
||||
sv.layer.cornerRadius = 12.0; sv.layer.masksToBounds = YES;
|
||||
// 演示:可选填充一段初始文本
|
||||
if (title.length > 0) {
|
||||
[sv appendStreamText:[NSString stringWithFormat:@"%@\t", title]]; // 以制表符结尾,生成一个段落
|
||||
}
|
||||
[self addSubview:sv];
|
||||
[sv mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
KBStreamOverlayView *overlay = [[KBStreamOverlayView alloc] init];
|
||||
overlay.delegate = (id)self;
|
||||
[self addSubview:overlay];
|
||||
[overlay mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(self.mas_left).offset(12);
|
||||
make.right.equalTo(self.rightButtonContainer.mas_left).offset(-12);
|
||||
make.top.equalTo(self.pasteViewInternal.mas_bottom).offset(10);
|
||||
make.bottom.equalTo(self.mas_bottom).offset(-10);
|
||||
}];
|
||||
self.streamTextView = sv;
|
||||
|
||||
// 右上角删除按钮
|
||||
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(kb_onTapStreamDelete) forControlEvents:UIControlEventTouchUpInside];
|
||||
[sv addSubview:del];
|
||||
[del mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.equalTo(sv.mas_top).offset(8);
|
||||
make.right.equalTo(sv.mas_right).offset(-8);
|
||||
make.height.mas_equalTo(28);
|
||||
make.width.mas_greaterThanOrEqualTo(56);
|
||||
}];
|
||||
self.streamDeleteButton = del;
|
||||
self.streamOverlay = overlay;
|
||||
|
||||
// 优先拉取后端测试数据(GET);失败则回落到本地演示
|
||||
[self kb_startNetworkStreamingWithSeed:title];
|
||||
@@ -246,11 +219,14 @@ static NSString * const kKBFunctionTagCellId = @"KBFunctionTagCellId";
|
||||
- (void)kb_onTapStreamDelete {
|
||||
// 关闭并销毁流式视图,恢复标签列表
|
||||
[self kb_stopNetworkStreaming];
|
||||
[self.streamDeleteButton removeFromSuperview];
|
||||
self.streamDeleteButton = nil;
|
||||
[self.streamTextView removeFromSuperview];
|
||||
self.streamTextView = nil;
|
||||
self.collectionViewInternal.hidden = NO;
|
||||
[self.streamOverlay removeFromSuperview];
|
||||
self.streamOverlay = nil;
|
||||
self.tagListView.hidden = NO;
|
||||
}
|
||||
|
||||
// 叠层关闭回调
|
||||
- (void)streamOverlayDidTapClose:(KBStreamOverlayView *)overlay {
|
||||
[self kb_onTapStreamDelete];
|
||||
}
|
||||
|
||||
|
||||
@@ -282,12 +258,8 @@ static NSString * const kKBStreamDemoURL = @"http://192.168.1.144:7529/api/demo/
|
||||
};
|
||||
fetcher.onFinish = ^(NSError * _Nullable error) {
|
||||
__strong typeof(weakSelf) self = weakSelf; if (!self) return;
|
||||
if (error) {
|
||||
[KBHUD showInfo:@"拉取失败"];
|
||||
[self.streamTextView finishStreaming];
|
||||
} else {
|
||||
[self.streamTextView finishStreaming];
|
||||
}
|
||||
if (error) { [KBHUD showInfo:@"拉取失败"]; }
|
||||
[self.streamOverlay finish];
|
||||
};
|
||||
self.streamFetcher = fetcher;
|
||||
[self.streamFetcher start];
|
||||
@@ -305,11 +277,47 @@ static NSString * const kKBStreamDemoURL = @"http://192.168.1.144:7529/api/demo/
|
||||
/// - 目前网络层(KBStreamFetcher)已做 “/t->\t、首段去一个 \t、段间去一个空格”
|
||||
/// - 这里仅负责附加到视图与标记首段状态,避免 UI 抖动
|
||||
- (void)kb_appendChunkToStreamView:(NSString *)chunk {
|
||||
if (chunk.length == 0 || !self.streamTextView) return;
|
||||
[self.streamTextView appendStreamText:chunk];
|
||||
if (chunk.length == 0 || !self.streamOverlay) return;
|
||||
[self.streamOverlay appendChunk:chunk];
|
||||
self.streamHasOutput = YES;
|
||||
}
|
||||
|
||||
#pragma mark - KBFunctionTagListViewDelegate
|
||||
|
||||
- (void)tagListView:(KBFunctionTagListView *)view didSelectIndex:(NSInteger)index title:(NSString *)title {
|
||||
// 权限全部打开(键盘已启用 + 完全访问)。在扩展进程中仅需判断“完全访问”。
|
||||
if ([[KBFullAccessManager shared] hasFullAccess]) {
|
||||
[self kb_showStreamTextViewIfNeededWithTitle:title ?: @""];
|
||||
return;
|
||||
}
|
||||
// 保留原有拉起主 App 的逻辑(若需要)
|
||||
[KBHUD showInfo:@"处理中…"];
|
||||
UIInputViewController *ivc = KBFindInputViewController(self);
|
||||
if (!ivc) return;
|
||||
NSString *encodedTitle = [title stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]] ?: @"";
|
||||
NSURL *ul = [NSURL URLWithString:[NSString stringWithFormat:@"%@?src=functionView&index=%ld&title=%@", KB_UL_LOGIN, (long)index, encodedTitle]];
|
||||
if (!ul) return;
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.05 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
[ivc.extensionContext openURL:ul completionHandler:^(BOOL ok) {
|
||||
if (ok) return; // Universal Link 成功
|
||||
NSURL *scheme = [NSURL URLWithString:[NSString stringWithFormat:@"%@@//login?src=functionView&index=%ld&title=%@", KB_APP_SCHEME, (long)index, encodedTitle]];
|
||||
[ivc.extensionContext openURL:scheme completionHandler:^(BOOL ok2) {
|
||||
if (ok2) return;
|
||||
BOOL bridged = NO;
|
||||
@try {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunguarded-availability"
|
||||
bridged = [KBURLOpenBridge openURLViaResponder:scheme from:self];
|
||||
#pragma clang diagnostic pop
|
||||
} @catch (__unused NSException *e) { bridged = NO; }
|
||||
if (!bridged) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{ [[KBFullAccessManager shared] ensureFullAccessOrGuideInView:self]; });
|
||||
}
|
||||
}];
|
||||
}];
|
||||
});
|
||||
}
|
||||
|
||||
// 用户点击功能标签:优先 UL 拉起主App,失败再 Scheme;两次都失败则提示开启完全访问。
|
||||
// 若已开启“完全访问”,则直接在键盘侧创建 KBStreamTextView,并在其右上角提供删除按钮关闭。
|
||||
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
@@ -501,17 +509,12 @@ static NSString * const kKBStreamDemoURL = @"http://192.168.1.144:7529/api/demo/
|
||||
return _pasteViewInternal;
|
||||
}
|
||||
|
||||
- (UICollectionView *)collectionViewInternal {
|
||||
if (!_collectionViewInternal) {
|
||||
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
|
||||
layout.sectionInset = UIEdgeInsetsZero; // 外边距交由约束控制
|
||||
_collectionViewInternal = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
|
||||
_collectionViewInternal.backgroundColor = [UIColor clearColor];
|
||||
_collectionViewInternal.dataSource = self;
|
||||
_collectionViewInternal.delegate = self;
|
||||
[_collectionViewInternal registerClass:[KBFunctionTagCell class] forCellWithReuseIdentifier:kKBFunctionTagCellId];
|
||||
- (KBFunctionTagListView *)tagListView {
|
||||
if (!_tagListView) {
|
||||
_tagListView = [[KBFunctionTagListView alloc] init];
|
||||
_tagListView.delegate = (id)self;
|
||||
}
|
||||
return _collectionViewInternal;
|
||||
return _tagListView;
|
||||
}
|
||||
|
||||
- (UIView *)rightButtonContainer {
|
||||
@@ -580,7 +583,7 @@ static NSString * const kKBStreamDemoURL = @"http://192.168.1.144:7529/api/demo/
|
||||
|
||||
#pragma mark - Expose
|
||||
|
||||
- (UICollectionView *)collectionView { return self.collectionViewInternal; }
|
||||
- (UICollectionView *)collectionView { return self.tagListView.collectionView; }
|
||||
- (NSArray<NSString *> *)items { return self.itemsInternal; }
|
||||
- (KBFunctionBarView *)barView { return self.barViewInternal; }
|
||||
- (KBFunctionPasteView *)pasteView { return self.pasteViewInternal; }
|
||||
|
||||
@@ -89,6 +89,8 @@
|
||||
049FB22F2EC34EB900FAB05D /* KBStreamTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB22E2EC34EB900FAB05D /* KBStreamTextView.m */; };
|
||||
049FB2322EC45A0000FAB05D /* KBStreamFetcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB2312EC45A0000FAB05D /* KBStreamFetcher.m */; };
|
||||
049FB2352EC45C6A00FAB05D /* NetworkStreamHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB2342EC45C6A00FAB05D /* NetworkStreamHandler.m */; };
|
||||
049FB23B2EC4766700FAB05D /* KBFunctionTagListView.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB2372EC4766700FAB05D /* KBFunctionTagListView.m */; };
|
||||
049FB23C2EC4766700FAB05D /* KBStreamOverlayView.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB2392EC4766700FAB05D /* KBStreamOverlayView.m */; };
|
||||
049FB31D2EC21BCD00FAB05D /* KBMyKeyboardCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB31C2EC21BCD00FAB05D /* KBMyKeyboardCell.m */; };
|
||||
04A9FE0F2EB481100020DB6D /* KBHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC97082EB31B14007BD342 /* KBHUD.m */; };
|
||||
04A9FE132EB4D0D20020DB6D /* KBFullAccessManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04A9FE112EB4D0D20020DB6D /* KBFullAccessManager.m */; };
|
||||
@@ -308,6 +310,10 @@
|
||||
049FB2312EC45A0000FAB05D /* KBStreamFetcher.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBStreamFetcher.m; sourceTree = "<group>"; };
|
||||
049FB2332EC45C6A00FAB05D /* NetworkStreamHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NetworkStreamHandler.h; sourceTree = "<group>"; };
|
||||
049FB2342EC45C6A00FAB05D /* NetworkStreamHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NetworkStreamHandler.m; sourceTree = "<group>"; };
|
||||
049FB2362EC4766700FAB05D /* KBFunctionTagListView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBFunctionTagListView.h; sourceTree = "<group>"; };
|
||||
049FB2372EC4766700FAB05D /* KBFunctionTagListView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBFunctionTagListView.m; sourceTree = "<group>"; };
|
||||
049FB2382EC4766700FAB05D /* KBStreamOverlayView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBStreamOverlayView.h; sourceTree = "<group>"; };
|
||||
049FB2392EC4766700FAB05D /* KBStreamOverlayView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBStreamOverlayView.m; sourceTree = "<group>"; };
|
||||
049FB31B2EC21BCD00FAB05D /* KBMyKeyboardCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBMyKeyboardCell.h; sourceTree = "<group>"; };
|
||||
049FB31C2EC21BCD00FAB05D /* KBMyKeyboardCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBMyKeyboardCell.m; sourceTree = "<group>"; };
|
||||
04A9A67D2EB9E1690023B8F4 /* KBResponderUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBResponderUtils.h; sourceTree = "<group>"; };
|
||||
@@ -680,6 +686,17 @@
|
||||
path = BMLongPressDragCellCollectionView;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
049FB23A2EC4766700FAB05D /* Function */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
049FB2362EC4766700FAB05D /* KBFunctionTagListView.h */,
|
||||
049FB2372EC4766700FAB05D /* KBFunctionTagListView.m */,
|
||||
049FB2382EC4766700FAB05D /* KBStreamOverlayView.h */,
|
||||
049FB2392EC4766700FAB05D /* KBStreamOverlayView.m */,
|
||||
);
|
||||
path = Function;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
04A9FE122EB4D0D20020DB6D /* Manager */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -759,6 +776,7 @@
|
||||
04FC95B12EB0B2CC007BD342 /* KBSettingView.m */,
|
||||
049FB22D2EC34EB900FAB05D /* KBStreamTextView.h */,
|
||||
049FB22E2EC34EB900FAB05D /* KBStreamTextView.m */,
|
||||
049FB23A2EC4766700FAB05D /* Function */,
|
||||
);
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
@@ -1409,6 +1427,8 @@
|
||||
049FB2352EC45C6A00FAB05D /* NetworkStreamHandler.m in Sources */,
|
||||
04FC956A2EB05497007BD342 /* KBKeyButton.m in Sources */,
|
||||
04FC95B22EB0B2CC007BD342 /* KBSettingView.m in Sources */,
|
||||
049FB23B2EC4766700FAB05D /* KBFunctionTagListView.m in Sources */,
|
||||
049FB23C2EC4766700FAB05D /* KBStreamOverlayView.m in Sources */,
|
||||
049FB22F2EC34EB900FAB05D /* KBStreamTextView.m in Sources */,
|
||||
04FC95702EB09516007BD342 /* KBFunctionView.m in Sources */,
|
||||
04FC956D2EB054B7007BD342 /* KBKeyboardView.m in Sources */,
|
||||
|
||||
Reference in New Issue
Block a user