当前位置: 首页 > wzjs >正文

网站怎么做登录模块制作自己的网页

网站怎么做登录模块,制作自己的网页,网站建设先做前台还是后台,小程序登录失败优雅实现水平滚动工具栏:UIScrollView与UIStackView的完美组合 本文将介绍如何通过UIScrollView与UIStackView的黄金组合,实现一个灵活高效的水平滚动工具栏。这种组合方案具有以下优势: 自动布局:UIScrollView提供滚动容器&…

优雅实现水平滚动工具栏:UIScrollView与UIStackView的完美组合

本文将介绍如何通过UIScrollView与UIStackView的黄金组合,实现一个灵活高效的水平滚动工具栏。这种组合方案具有以下优势:

  1. 自动布局:UIScrollView提供滚动容器,UIStackView管理动态布局
  2. 命令模式:采用协议化设计实现按钮与业务逻辑解耦
  3. 动态扩展:支持按钮的灵活增减
  4. 性能优化:原生控件组合带来流畅滚动体验
  5. 代码简洁:告别复杂的布局计算

核心实现原理

1. 视图层级结构
ButtonBarView
└── UIScrollView└── UIStackView (Horizontal)└── 自定义按钮视图(SLVerticalButtonView)×N
2. 关键布局策略
// 核心约束设置
// StackView 约束到 ScrollView 的 ContentLayoutGuide
[_stackView.topAnchor constraintEqualToAnchor:_scrollView.contentLayoutGuide.topAnchor],
[_stackView.leadingAnchor constraintEqualToAnchor:_scrollView.contentLayoutGuide.leadingAnchor],
[_stackView.trailingAnchor constraintEqualToAnchor:_scrollView.contentLayoutGuide.trailingAnchor],
[_stackView.bottomAnchor constraintEqualToAnchor:_scrollView.contentLayoutGuide.bottomAnchor],// StackView 高度与 ScrollView 的 FrameLayoutGuide 一致
[_stackView.heightAnchor constraintEqualToAnchor:_scrollView.frameLayoutGuide.heightAnchor]
3. 动态内容更新
- (void)setCommands:(NSArray<id<Command>> *)commands {// 清空旧视图// 动态生成新按钮// 更新布局
}
// 更新布局
- (void)updateStackViewWidthIfNeeded {[self.scrollView layoutIfNeeded]; // 立即布局以获取准确宽度CGFloat contentWidth = self.stackView.frame.size.width;CGFloat scrollViewWidth = self.scrollView.bounds.size.width;if (contentWidth < scrollViewWidth && self.commands.count > 0) {if (!self.stackViewWidthConstraint) {// 添加约束使stackView宽度等于scrollView的宽度self.stackViewWidthConstraint = [self.stackView.widthAnchor constraintEqualToAnchor:self.scrollView.frameLayoutGuide.widthAnchor];self.stackViewWidthConstraint.priority = UILayoutPriorityRequired;[self.stackViewWidthConstraint setActive:YES];[self.scrollView layoutIfNeeded]; // 应用新约束}} else {if (self.stackViewWidthConstraint) {[self.stackViewWidthConstraint setActive:NO];self.stackViewWidthConstraint = nil;[self.scrollView layoutIfNeeded];}}
}

完整实现代码(Objective-C)

//====================
// 命令协议
//====================
@protocol Command <NSObject>
@property (strong, nonatomic) ExtendCompositional *descriptor;
- (void)execute;
@end//====================
// 命令工厂协议
//====================
@protocol CommandFactory <NSObject>
- (NSArray<id<Command>> *)commandsForContext:(UIViewController *)context;
@end//====================
// 基础命令抽象类
//====================
@interface Command : NSObject <Command>
@property (weak, nonatomic) UIViewController *context;
+ (instancetype)commandWithContext:(UIViewController *)context;
@end@implementation Command
@synthesize descriptor = _descriptor;
+ (instancetype)commandWithContext:(UIViewController *)context {Command *cmd = [self new];cmd.context = context;return cmd;
}- (void)execute { /* 子类实现 */ }
@end//====================
// 工具栏视图
//====================
@interface ButtonBarView : UIView<UIScrollViewDelegate>
@property (strong, nonatomic) UIScrollView *scrollView;
@property (strong, nonatomic) UIStackView *stackView;
@property (strong, nonatomic) NSArray<id<Command>> *commands;
@end@interface ButtonBarView ()
@property (nonatomic, strong) NSLayoutConstraint *stackViewWidthConstraint;
@end@implementation ButtonBarView
- (instancetype)initWithFrame:(CGRect)frame
{self = [super initWithFrame:frame];if (self) {[self setupScrollSystem];}return self;
}- (void)setupScrollSystem {_scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];_scrollView.showsHorizontalScrollIndicator = NO;_scrollView.delegate = self;_stackView = [[UIStackView alloc] init];_stackView.axis = UILayoutConstraintAxisHorizontal;_stackView.alignment = UIStackViewAlignmentFill;_stackView.distribution = UIStackViewDistributionFillEqually;_stackView.spacing = 20;[_scrollView addSubview:_stackView];[self addSubview:_scrollView];// 布局约束_stackView.translatesAutoresizingMaskIntoConstraints = NO;_scrollView.translatesAutoresizingMaskIntoConstraints = NO;[NSLayoutConstraint activateConstraints:@[[_scrollView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],[_scrollView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],[_scrollView.topAnchor constraintEqualToAnchor:self.topAnchor],[_scrollView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],// StackView 约束到 ScrollView 的 ContentLayoutGuide[_stackView.topAnchor constraintEqualToAnchor:_scrollView.contentLayoutGuide.topAnchor],[_stackView.leadingAnchor constraintEqualToAnchor:_scrollView.contentLayoutGuide.leadingAnchor],[_stackView.trailingAnchor constraintEqualToAnchor:_scrollView.contentLayoutGuide.trailingAnchor],[_stackView.bottomAnchor constraintEqualToAnchor:_scrollView.contentLayoutGuide.bottomAnchor],// StackView 高度与 ScrollView 的 FrameLayoutGuide 一致[_stackView.heightAnchor constraintEqualToAnchor:_scrollView.frameLayoutGuide.heightAnchor]]];
}
- (void)setCommands:(NSArray<id<Command>> *)commands {_commands = commands;// 清空旧按钮[_stackView.arrangedSubviews makeObjectsPerformSelector:@selector(removeFromSuperview)];// 动态生成按钮[commands enumerateObjectsUsingBlock:^(id<Command> command, NSUInteger idx, BOOL *stop) {SLVerticalButtonView *button = [[SLVerticalButtonView alloc] initWithFrame:CGRectZero target:command action:@selector(execute)];button.image = command.descriptor.image;button.title = command.descriptor.title;button.identifier = command.descriptor.identifier;[button setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];[self.stackView addArrangedSubview:button];}];[self updateStackViewWidthIfNeeded];
}
- (void)layoutSubviews {[super layoutSubviews];[self updateStackViewWidthIfNeeded];
}
- (void)updateStackViewWidthIfNeeded {[self.scrollView layoutIfNeeded]; // 立即布局以获取准确宽度CGFloat contentWidth = self.stackView.frame.size.width;CGFloat scrollViewWidth = self.scrollView.bounds.size.width;if (contentWidth < scrollViewWidth && self.commands.count > 0) {if (!self.stackViewWidthConstraint) {// 添加约束使stackView宽度等于scrollView的宽度self.stackViewWidthConstraint = [self.stackView.widthAnchor constraintEqualToAnchor:self.scrollView.frameLayoutGuide.widthAnchor];self.stackViewWidthConstraint.priority = UILayoutPriorityRequired;[self.stackViewWidthConstraint setActive:YES];[self.scrollView layoutIfNeeded]; // 应用新约束}} else {if (self.stackViewWidthConstraint) {[self.stackViewWidthConstraint setActive:NO];self.stackViewWidthConstraint = nil;[self.scrollView layoutIfNeeded];}}
}
@end

使用示例

1. 创建命令工厂
@interface CommandFactory : NSObject <CommandFactory>
@end
@implementation CommandFactory
- (NSArray<id<Command>> *)commandsForContext:(UIViewController *)context {return @[[AddPhotoCommand commandWithContext:context],[AddTextCommand commandWithContext:context],[AddBackgroundCommand commandWithContext:context],[AddFilterCommand commandWithContext:context]];
}@end
2. 在ViewController中使用
- (void)viewDidLoad {[super viewDidLoad];// 创建工具栏ButtonBarView *toolbar = [[ButtonBarView alloc] initWithFrame:CGRectMake(0, 100, self.view.bounds.size.width, 80)];// 获取命令列表id<CommandFactory> factory = [CommandFactory new];toolbar.commands = [factory commandsForContext:self];[self.view addSubview:toolbar];
}
3. 自定义按钮示例(SLVerticalButtonView)
// 实现垂直排列的图标+文字按钮
@implementation SLVerticalButtonView- (instancetype)initWithFrame:(CGRect)frame target:(id)target action:(SEL)action {self = [super initWithFrame:frame];// 添加图片视图和文字标签// 设置点击事件[self addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];return self;
}
@end

关键点解析

  1. 布局锚点选择

    • contentLayoutGuide:决定可滚动内容范围
    • frameLayoutGuide:限制可视区域范围
  2. 性能优化

    • 复用UIStackView的自动布局
    • 避免复杂图层结构
  3. 扩展性设计

    • 遵循命令模式
    • 支持动态命令配置

效果展示

水平滚动工具栏将自动根据内容多少:

  • 内容少时:居中显示
  • 内容多时:支持左右滑动
  • 自动维持统一高度

这种实现方案完美结合了UIScrollView的滚动能力和UIStackView的自动布局优势,特别适合需要动态生成水平排列元素的场景,避免选择UICollectionView层级结构比较多的视图。通过命令模式的引入,使得每个按钮的行为可以灵活配置,极大提高了代码的可维护性和扩展性。

http://www.dtcms.com/wzjs/323557.html

相关文章:

  • 政府门户网站平台建设长春seo网站管理
  • 汕头潮阳网站建设培训心得模板
  • 网站页面类型百度的总部在哪里
  • 宁波企业做网站北京网络推广优化公司
  • 有没有专门做一件代发的网站网址提交百度
  • 泰安网站建设公司哪家好网址怎么注册
  • 如何用手机建网站搜外友链平台
  • 网络教育室内设计专业seo自学网官方
  • 如何在阿里巴巴建设网站seo公司外包
  • 物流公司会计好做吗安徽seo优化
  • asp 做网站的缺点营销成功的案例
  • win8网站模板有必要买优化大师会员吗
  • 如何利用网站模板做网站许昌seo公司
  • 北京网站建设项目企点qq
  • 360安全网址百度搜索优化关键词排名
  • 免费效果图网站软文有哪几种类型
  • 做网站需要注意什么十种营销方式
  • 中为网站建设2020十大网络热词
  • 怎么做视频网站赚钱吗网络营销app有哪些
  • 哪家网站专做女性服装网站媒体推广
  • 做网站编辑应该注意什么宁德市委书记
  • 什么网站可以做设计兼职搜索引擎收录提交入口
  • python做网站吗掌门一对一辅导官网
  • 合肥网站建设设计中文搜索引擎
  • 申请做网站 论坛版主网站优化公司哪个好
  • 请简述网站建设的一般流程百度地址如何设置门店地址
  • 做网站成都品牌宣传策划方案
  • 游戏网站做关键字我的百度账号
  • 福州专业网站建设公司网络营销价格策略有哪些
  • 吉林省四平市网站建设成都达洱狐网络科技有限公司