iOS 水平方向弹出菜单(支持展开折叠)

简介: iOS 水平方向弹出菜单(支持展开折叠)

前言

1.支持展开折叠的弹出菜单的实现思路:

1.1将弹出视图添加到keyWindow,蒙版也添加到主窗口(主要原因是点击屏幕的空白处,需要隐藏弹出视图)

1.2展示的时候,动画从右上角往左下脚延伸;隐藏的时候,动画从左下脚往右上角收回 (展示的时候,从上往下,即x,y 慢慢变大)

1.3 内部视图采用collectionView进行布局

1.4 view的frame 是根据当前点击的菜单按钮所在的商品cell进行计算和坐标转换的。

/**
 触发折叠菜单隐藏和显示的按钮
 */
@property (nonatomic,weak) UIButton *btn;
/**
 用于计算折叠菜单frame,
 */
@property (nonatomic,weak) UIButton *tmpbtn;

2.水平方向弹出菜单视图的应用场景:

2.1、门店商品的支持的功能:向右横向展开视图(操作:下/上架、打印、编辑、同步网络)支持再次折叠隐藏视图

image.png

2.2、网店商品目前只包含下架功能:展开折叠视图:(包含上/下架商品功能)

image.png

  1. 竖向弹出菜单视图

弹出菜单:会员模块的右上角的下拉菜单(竖向)https://kunnan.blog.csdn.net/article/details/84618986

image.png

视频:https://live.csdn.net/v/173757

demo1下载地址:https://download.csdn.net/download/u011018979/20598998

demo 设置两个测试开关 :

测试开关1:将水平方向弹出菜单视图集成到cell

测试开关2:将水平方向弹出菜单视图集成到VC的View

demo2下载地址:https://download.csdn.net/download/u011018979/20537947

demo2的内容是:将水平方向弹出菜单视图集成到VC的View

疑问解答,请关注公众号:iOS逆向

I、 支持展开折叠的弹出菜单的实现思路

1.1将弹出视图添加到keyWindow,蒙版也添加到主窗口(主要原因是点击屏幕的空白处,需要隐藏弹出视图)

#define kWindow [UIApplication sharedApplication].keyWindow
 [kWindow addSubview:self];
 [kWindow addSubview:self.cover];//蒙版添加到主窗口, 蒙版用于监听点击事件,来隐藏弹出视图

1.2 展开

展示的时候,动画从右上角往左下脚延伸;隐藏的时候,动画从左下脚往右上角收回 (展示的时候,从上往下,即x,y 慢慢变大)

展开效果的实现原理:

1 点击展示商品信息的cell 上面的弹出按钮时,阴影alpha由0到1,弹窗的scale由0到1(这里使用CABasicAnimation)

2  点击空白处(self.cover),再让阴影alpha由1到0,弹窗的scale由1到0(同样使用CABasicAnimation),动画完成后移除阴影和弹窗

1.3 内部视图采用collectionView进行布局

@property (strong, nonatomic) UICollectionView *collectionView;

1.4 view的frame 是根据当前点击的菜单按钮所在的商品cell进行计算和坐标转换的。

CGRect endRect = [weakSelf.btn.superview convertRect:weakSelf.btn.frame toView:kWindow];
     CGRect Rect = [weakSelf.tmpbtn.superview convertRect:weakSelf.tmpbtn.frame toView:kWindow];
     // 设置菜单的frame
     weakSelf.models.rect = Rect;
     weakSelf.models.endRect =   endRect;// 结束的位置
     [[[weakSelf models].viewModel            expandMenuSubject] sendNext:weakSelf.models];
 }];

II、用法

2.1 创建弹出菜单popmenuView

  1. 构建菜单内部的数据模型
+ (NSMutableArray*)getMenudatas4MiniAppWithBlock:(void (^)(id sender))block{
   NSMutableArray* tmp = [NSMutableArray array];
    QCTCollectionModel *network = [QCTCollectionModel new];
    network.titleName =  QCTLocal(@"Shelves_key");
    network.imgName= @"icon_sp_shangjia";
    network.block = block;
    network.type =QCTCollectionModelType4Shelves;
    [tmp addObject:network];
    return tmp;
}
  1. 实现popmenuView的懒加载
#pragma mark - ******** 支持展开折叠的弹出菜单视图
- (QCTHorizontalpopupView *)popmenuView{
    if (!_popmenuView) {
        _popmenuView = [[QCTHorizontalpopupView alloc] initWithFrame:self.view.frame viewModel:self.viewModel];
        _popmenuView.hidden = YES;
       #pragma mark - ******** 构建折叠视图的模型
        __weak __typeof__(self) weakSelf = self;
            self.viewModel.Menudatas = [QCTCollectionModel getMenudatas4MiniAppWithBlock:^(  QCTCollectionModel * sender) {
                [[[weakSelf viewModel] hiddenSubject]sendNext:nil];
                NSLog(@"点击了%@",[sender titleName]);
                switch (sender.type) {
                    case QCTCollectionModelType4edit:
                    {
                        [weakSelf setupQCTEditMerchandiseViewController:sender];
                    }
                        break;
                    case QCTCollectionModelType4Shelves:
                        //        /**上架*/
                    {
                        // 根据不同的商品类型进行界面跳转
                        [weakSelf setupQCTCollectionModelType4Shelves:sender];
                    }
                        break;
                    case QCTCollectionModelType4Offtheshelf:
                    {
                        // 根据不同的商品类型进行界面跳转
                        [weakSelf setupQCTCollectionModelType4Shelves:sender];
                    }
                        break;
                        //        /**打印*/
                    case QCTCollectionModelType4Printer:
                    {
                        //打印
                        [weakSelf printerInfo:self.popmenuView.model];
                    }
                        break;
                    default:
                        break;
                }
            } ];
        _popmenuView.models = self.viewModel.Menudatas;
    }
    return _popmenuView;
}

2.2 监听弹出和折叠事件

/**
     监听弹出事件,此事件由展示商品信息的cell发出。
     */
    [self.viewModel.showMenuSubject subscribeNext:^(QCTgoodsManListModel  * x) {
        [weakSelf.popmenuView updateRect:   x.rect  ];// 更新popmenuView的位置。
        [weakSelf.popmenuView updateendRect:   x.endRect  ];// 设置折叠动画的终点
        [weakSelf.popmenuView expandView:x.expandViewCGPoint  ];
    }];
    /**
     折叠弹出菜单
     */
    [self.viewModel.hiddenSubject subscribeNext:^(id  _Nullable x) {
        [weakSelf.popmenuView foldView];
    }];
    // 监听弹出菜单按钮的点击事情,进行判断是展开还是隐藏
    [self.viewModel.expandMenuSubject subscribeNext:^(id  _Nullable x) {
        [weakSelf expandMenu:x];
    }];
  • 判断是展开弹出菜单,还是折叠
#pragma mark - ******** 判断是展开弹出菜单,还是折叠
- (void)expandMenu:(id)x{//点击按钮
    self.popmenuView.model = x;
    [ self.viewModel.reloadSubject sendNext:nil];
    if ([self.popmenuView isHidden]) {
        [self.viewModel.showMenuSubject sendNext:x];
    }else{
        [self.viewModel.hiddenSubject sendNext:nil];
    }
}

III、完整demo

demo 设置两个测试开关

[self addpopV2cell];//  测试开关1:将水平方向弹出菜单视图集成到cell
//    [self addpopV2VCView];//  测试开关2:将水平方向弹出菜单视图集成到VC的View

3.1 demo1: 将水平方向弹出菜单视图集成到cell

demo1下载地址:https://download.csdn.net/download/u011018979/20598998


3.2 demo2:将水平方向弹出菜单视图集成到VC的View

文章:https://kunnan.blog.csdn.net/article/details/106406160

视频:https://live.csdn.net/v/173757

demo2下载地址:https://download.csdn.net/download/u011018979/20537947

1.支持展开折叠的弹出菜单的实现思路:

1.1将弹出视图添加到keyWindow,蒙版也添加到主窗口(主要原因是点击屏幕的空白处,需要隐藏弹出视图)

1.2展示的时候,动画从右上角往左下脚延伸;隐藏的时候,动画从左下脚往右上角收回 (展示的时候,从上往下,即x,y 慢慢变大)

1.3 内部视图采用collectionView进行布局

1.4 view的frame 是根据当前点击的菜单按钮所在的商品cell进行计算和坐标转换的。

2.水平方向弹出菜单视图的应用场景:

2.1、门店商品的支持的功能:向右横向展开视图(操作:下/上架、打印、编辑、同步网络)支持再次折叠隐藏视图

image.png

2.2、网店商品目前只包含下架功能:展开折叠视图:(包含上/下架商品功能)

image.png

3.3 水平方向弹出菜单视图

弹出菜单HorizontalpopupView的具体代码

image.png

  • .h
#import <UIKit/UIKit.h>
#import "QCTgoodsManListModel.h"
#import "QCThorizontalMenuCollectionViewCell.h"
#import "QCTgoodsListViewModel.h"
NS_ASSUME_NONNULL_BEGIN
/**
 Horizontal  Popup View 横向(水平方向)弹出菜单视图
 本app类似的弹出菜单:会员模块的右上角的下拉菜单(竖向)。
 I 、 展开折叠菜单(横向):
 0、场景:
 0.1、网店商品目前只包含下架功能:展开折叠视图:(包含上/下架商品功能)。
 0.2、门店商品的支持的功能: 向右横向展开视图(操作:下/上架、打印、编辑、同步网络)支持再次折叠隐藏视图
II、实现思路:
1、 将视图添加到keyWindow,蒙版也添加到主窗口(避免每个商品cell都创建一个菜单视图)
 #define kWindow [UIApplication sharedApplication].keyWindow
 [kWindow addSubview:self];
 [kWindow addSubview:self.cover];//蒙版添加到主窗口
 2、展开效果:展示的时候,动画从右上角往左下脚延伸;隐藏的时候,动画从左下脚往右上角收回 // (展示的时候,从上往下,即x,y 慢慢变大)
 2.1、展开效果的实现原理:
 点击弹出按钮时,阴影alpha由0到1,弹窗的scale由0到1(这里使用CABasicAnimation)
 点击空白处,再让阴影alpha由1到0,弹窗的scale由1到0(同样使用CABasicAnimation),动画完成后移除阴影和弹窗
3、内部视图采用collectionView进行布局
 4、view的frame 是根据当前点击的菜单按钮所在的商品cell进行计算和坐标转换的。
 [[_btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
 // 获取_btn 在Windows的 frame
     CGRect endRect = [weakSelf.btn.superview convertRect:weakSelf.btn.frame toView:kWindow];
     CGRect Rect = [weakSelf.tmpbtn.superview convertRect:weakSelf.tmpbtn.frame toView:kWindow];
     // 设置菜单的frame
     weakSelf.models.rect = Rect;
     weakSelf.models.endRect =   endRect;// 结束的位置
     [[[weakSelf models].viewModel            expandMenuSubject] sendNext:weakSelf.models];
 }];
 */
@interface QCTHorizontalpopupView : UIView
/**
 商品数据,存储着商品信息。用于打印、上下架以及编辑等
 */
@property (nonatomic, strong) QCTgoodsManListModel* model;
/**
 菜单视图的模型数据
 */
@property (nonatomic, strong) NSMutableArray* models;
@property (nonatomic, copy) void (^block)(id sender);
@property (nonatomic,strong) QCTgoodsListViewModel *viewModel;
- (id)initWithFrame:(CGRect)frame viewModel:(id)viewModel ;
/**
 更新菜单的frame。 需要根据models 设置设置下宽度
 */
- (void)updateRect:(CGRect)rect;
/**
 更新折叠动画的结束位置
 */
- (void)updateendRect:(CGRect)rect;
/**
 展开方法
 */
- (void)expandView:(CGPoint)AnchorPoint;
/**
 折叠方法
 */
- (void)foldView;
@end
NS_ASSUME_NONNULL_END
  • m
#import "QCTHorizontalpopupView.h"
@interface QCTHorizontalpopupView ()
/**
 */
@property (strong, nonatomic) UICollectionView *collectionView;
@property (strong, nonatomic) NSIndexPath *indexPath;
/**
 蒙版,用于处理点击空白处(即非弹出菜单部分)的事件
 */
@property (nonatomic, weak) UIView *cover;
/**
 弹出菜单的横向箭头
 */
@property (nonatomic, strong) UIImageView *img;
/**
 存储折叠动画的结束位置的View
 */
@property (nonatomic, strong) UIView *clickView;
@end
@implementation QCTHorizontalpopupView
- (UIView *)clickView{
    if (nil == _clickView) {
        UIView *tmpView = [[UIView alloc]init];
        _clickView = tmpView;
        [self addSubview:_clickView];
        tmpView.backgroundColor = [UIColor clearColor];
        tmpView.alpha = 0;
        __weak __typeof__(self) weakSelf = self;
        [tmpView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.centerY.equalTo(weakSelf).offset(0);
            make.size.mas_equalTo(CGSizeMake(kAdjustRatio(10), kAdjustRatio(10)));
            make.left.equalTo(weakSelf.img.mas_right).offset(kAdjustRatio(5));
        }];
    }
    return _clickView;
}
// 背景图片的菜单箭头
-(UIImageView *)img{//icon_huiyuanka_sanjiao
    if (!_img) {
        _img = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"icon_sp_sanjiao"]];//
        [self addSubview:_img];
        __weak __typeof__(self) weakSelf = self;
        [_img mas_makeConstraints:^(MASConstraintMaker *make) {
            make.centerY.equalTo(weakSelf).offset(0);
            make.left.equalTo(weakSelf.mas_right).offset(-kAdjustRatio(0));
        }];
    }
    return _img;
}
/**
 蒙版用于监听点击事件,来隐藏弹出视图
 */
-(UIView *)cover{
    if (!_cover) {
        UIView *tmp = [[UIView alloc] initWithFrame:kWindow.bounds];
        _cover = tmp;
        _cover.backgroundColor = [UIColor clearColor];
        [kWindow addSubview:self.cover];//蒙版添加到主窗口
        _cover.hidden = YES;
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(removeMenuList)];
        [_cover addGestureRecognizer:tap];
    }
    return _cover;
}
- (void)setViewModel:(QCTgoodsListViewModel *)viewModel{
    _viewModel = viewModel;
}
- (id)init {
    return [self initWithFrame:CGRectZero viewModel:nil];
}
- (id)initWithFrame:(CGRect)frame {
    return [self initWithFrame:frame viewModel:nil];
}
- (id)initWithCoder:(NSCoder *)aDecoder {
    return [self initWithFrame:CGRectZero viewModel:nil];
}
- (id)initWithViewModel:(id)viewModel {
    return [self initWithFrame:CGRectZero viewModel:viewModel];
}
- (id)initWithFrame:(CGRect)frame viewModel:(id)viewModel {
    if (self = [super initWithFrame:frame]) {
        self.viewModel = viewModel;
        [self bindViewModel];
        [self collectionView];
        [self cover];
        [self img];
        [self clickView];
    }
    return self;
}
- (void)bindViewModel {
    @weakify(self);
    __weak __typeof__(self) weakSelf = self;
    [self.viewModel.reloadSubject subscribeNext:^(id  _Nullable x) {
        @strongify(self);
        [self.collectionView reloadData];
    }];
}
- (void)updateendRect:(CGRect)rect{
    self.clickView.frame = rect;
}
/**
 更新frame.
 rect  是根据写,x, y 是根据当前选中的商品对应的cell位置进行获取的。
 */
- (void)updateRect:(CGRect)rect{
    self.frame = rect;
    [self updateFocusIfNeeded];
    [self.collectionView updateConstraints];
    [self.collectionView layoutIfNeeded];
    [self layoutSubviews];
}
/**
 NSMutableArray
 */
- (void)setModels:(NSMutableArray*)models{
    _models = models;
    [self.collectionView reloadData];
}
- (UICollectionView *)collectionView {
    if (_collectionView == nil) {
        UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
        // 2.设置整个collectionView的内边距
        //分别为上、左、下、右
        //        flowLayout.sectionInset = UIEdgeInsetsMake(0,kAdjustRatio(10),0,kAdjustRatio(10));
        //.设置每一行之间的间距
        flowLayout.minimumLineSpacing = 0;
        flowLayout.minimumInteritemSpacing = 0;
        //        flowLayout.itemSize = CGSizeMake((SCREEN_WIDTH-3*kAdjustRatio(10))/3.0, self.optionsView.height);
        _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:flowLayout];
//        _collectionView.backgroundColor = [UIColor clearColor];
        UIView *style = _collectionView;
        style.layer.cornerRadius = 3;
        style.layer.backgroundColor = [[UIColor colorWithRed:0.0f/255.0f green:0.0f/255.0f blue:0.0f/255.0f alpha:1.0f] CGColor];
        style.alpha = 0.8;
        _collectionView.showsVerticalScrollIndicator = NO;
        _collectionView.bounces = NO;
        _collectionView.dataSource = self;
        _collectionView.delegate = self;
        [_collectionView registerClass:[QCThorizontalMenuCollectionViewCell class] forCellWithReuseIdentifier:@"QCThorizontalMenuCollectionViewCell"];
        if (@available(iOS 11.0, *)) {
            _collectionView.contentInsetAdjustmentBehavior =  UIScrollViewContentInsetAdjustmentNever;
        } else {
            // Fallback on earlier versions
        }
        _collectionView.scrollEnabled = NO;
        __weak __typeof__(self) weakSelf = self;
        [self addSubview:_collectionView];
        [_collectionView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.top.bottom.right.equalTo(weakSelf);
        }];
    }
    return _collectionView;
}
#pragma mark - UICollectionViewDelegate
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
    return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return self.models.count;
}
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    CGSize size;
    //
    size = CGSizeMake(self.collectionView.width/self.models.count, kAdjustRatio(kHorizontalpopupViewH));//kHorizontalpopupViewH
//    size = CGSizeMake(self.collectionView.width/3, kAdjustRatio(50));
    return size;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    QCThorizontalMenuCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"QCThorizontalMenuCollectionViewCell" forIndexPath:indexPath];
    QCTCollectionModel *model = self.models[indexPath.row];
//
//    /**上架*/
//    QCTCollectionModelType4Shelves,
//    /**下架*/
//    QCTCollectionModelType4Offtheshelf,
//
//
    if(model.type == QCTCollectionModelType4Shelves ||  model.type == QCTCollectionModelType4Offtheshelf  ){
        if(!self.model.state.boolValue){
            model.titleName = QCTLocal(@"Shelves_key");
//            @"上架";
            model.imgName = @"icon_sp_shangjia";
            model.type = QCTCollectionModelType4Shelves;
        }else{
            model.type = QCTCollectionModelType4Offtheshelf;
            model.titleName = QCTLocal(@"Off_the_shelf");
//            @"下架";
            model.imgName = @"icon_sp_xiajia";
        }
    }
    cell.model =model;
    cell.goodmodel = self.model;
    return cell;
}
#pragma 动画: 设置layer.anchorPoint
+ (void) setAnchorPoint:(CGPoint)anchorpoint forView:(UIView *)view{
    CGRect oldFrame = view.frame;
    view.layer.anchorPoint = anchorpoint;
    view.frame = oldFrame;
}
/**
 点击弹出按钮时,阴影alpha由0到1,弹窗的scale由0到1(这里使用CABasicAnimation)
 点击空白处,再让阴影alpha由1到0,弹窗的scale由1到0(同样使用CABasicAnimation),动画完成后移除阴影和弹窗
 //展示的时候,动画从右上角往左下脚延伸;隐藏的时候,动画从左下脚往右上角收回
 // (展示的时候,从上往下,即x,y 慢慢变大)
 */
- (void)expandView:(CGPoint)AnchorPoint{
    [self removeFromSuperview];
    [kWindow addSubview:self];
    [self.cover removeFromSuperview];
    [kWindow addSubview:self.cover];//蒙版添加到主窗口
    [kWindow bringSubviewToFront:self];
    //展示的时候,动画从右上角往左下脚延伸;隐藏的时候,动画从左下脚往右上角收回
    // (展示的时候,从上往下,即x,y 慢慢变大)
    [[self class] setAnchorPoint:CGPointMake(1.f, 0.5f) forView:self];
    self.transform = CGAffineTransformMakeScale(0.001f, 0.001f);
    self.hidden = NO;// 修改为动画, MemberCardMenuView 提供一个动画的实例方法
    self.cover.hidden = NO;
    self.cover.alpha = 0;
    [UIView animateWithDuration:0.3 animations:^{
        self.transform = CGAffineTransformMakeScale(1.f, 1.f);
        self.cover.alpha = 1;
    } completion:^(BOOL finished) {
        self.transform = CGAffineTransformIdentity;
    }];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    [self.viewModel.hiddenSubject sendNext:nil];
}
/**
 折叠
 */
- (void)foldView{
    /*
     知识点:
     (0,0) 为左上角,(0,1) 为左下角,
     (1, 0)右上, (1,1) 右下
     */
    [UIView animateWithDuration:0.3 animations:^{
        self.transform = CGAffineTransformMakeScale(0.001f, 0.001f);
        self.cover.alpha = 0;
    } completion:^(BOOL finished) {
        self.hidden = YES;
        self.cover.hidden = YES;
        self.transform = CGAffineTransformIdentity;
        [self removeFromSuperview];
        [self.cover removeFromSuperview];
    }];
}
#pragma mark - 移除菜单
-(void)removeMenuList{
    [self.viewModel.hiddenSubject sendNext:nil];
}
@end

3.4 集成到cell

粉丝疑问:是否可以用在cell的点击事件

答:可以,请参考本文的集成例子QCTQCTgoodsListTableViewCellView

你也可以利用cancelsTouchesInView属性,控制点击事件优先级。案例:iOS设置tableView的点击事件优先级低于cell的选中事件【场景:比如筛选视图,监听蒙版的点击事件就隐藏筛选视图】https://blog.csdn.net/z929118967/article/details/89405040

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] init];
    [[tap rac_gestureSignal] subscribeNext:^(id x) {
        @strongify(self);
        if (self.alpha) {
            [self.viewModel.hiddenSubject sendNext:nil];
        }
    }];
    [self addGestureRecognizer:tap];
    UITapGestureRecognizer *cutTap = [[UITapGestureRecognizer alloc] init];
    cutTap.cancelsTouchesInView = NO;// 设置tableView的点击事件优先级,低于cell的选中事件
    [[cutTap rac_gestureSignal] subscribeNext:^(id x) {
        //        @strongify(self);
        [self.viewModel.hiddenSubject sendNext:nil];
    }];
    [self.tableView addGestureRecognizer:cutTap];

QCTQCTgoodsListTableViewCellView

集成到cell

#import "QCTQCTgoodsListTableViewCellView.h"
/**
 展示商品信息
 */
@interface QCTQCTgoodsListTableViewCellView ()
@property (strong, nonatomic) UIImageView *iconImgV;
@property (nonatomic,weak) UILabel *titleLab;
@property (nonatomic,weak) UILabel *barCodeTitleLab;//
@property (nonatomic,weak) UILabel *priceLab;
@property (nonatomic,weak) UILabel *skuLab;// 库存
/**
 折叠菜单按钮
 */
@property (nonatomic,weak) UIButton *btn;// 更多
/**
 用于 计算折叠菜单frame,
 */
@property (nonatomic,weak) UIButton *tmpbtn;//
@property (nonatomic,weak) UIView *linView;//
@end
@implementation QCTQCTgoodsListTableViewCellView
// 完整代码从demo查看
@end

see also

目录
相关文章
|
iOS开发 开发者
iOS系统菜单控制器UIMenuController使用简介(一)
iOS系统菜单控制器UIMenuController使用简介
708 0
iOS系统菜单控制器UIMenuController使用简介(一)
|
iOS开发
iOS支持展开折叠的弹出菜单(水平方向弹出菜单视图) 【修订版】
iOS支持展开折叠的弹出菜单(水平方向弹出菜单视图) 【修订版】
478 0
iOS支持展开折叠的弹出菜单(水平方向弹出菜单视图) 【修订版】
|
iOS开发
iOS支持展开折叠的弹出菜单(水平方向弹出菜单视图)
iOS支持展开折叠的弹出菜单(水平方向弹出菜单视图)
245 0
iOS支持展开折叠的弹出菜单(水平方向弹出菜单视图)
|
iOS开发 开发者
iOS系统菜单控制器UIMenuController使用简介(二)
iOS系统菜单控制器UIMenuController使用简介
379 0
iOS系统菜单控制器UIMenuController使用简介(二)
|
存储 设计模式 缓存
备战九十,iOS面试题菜单,持续更新(题目及答案已上传Github)
Objective_C语言特性 (戳这里跳转到Github) 分类 扩展 代理(Delegate) 通知(NSNotification) KVO (Key-value observing) KVC(Key-value coding) 属性关键字 runloop (戳这里跳转到Github) ...
2278 0
|
iOS开发
HTML5_CSS3实现iOS Path菜单
在线演示 本地下载
923 0
|
iOS开发
[译]如何在 iOS 上实现类似 Airbnb 中的可展开式菜单
本文讲的是[译]如何在 iOS 上实现类似 Airbnb 中的可展开式菜单,几个月前,我有机会实现了一个可展开式菜单,效果同知名的 iOS 应用 Airbnb。然后,我认为把它封装为库会更好。现在我想和大家分享用于实现漂亮的滚动驱动动画采用的一些解决方案。
1074 0
|
Android开发 iOS开发
张高兴的 Xamarin.Forms 开发笔记:为 Android 与 iOS 引入 UWP 风格的汉堡菜单 ( MasterDetailPage )
  所谓 UWP 样式的汉堡菜单,我曾在“张高兴的 UWP 开发笔记:汉堡菜单进阶”里说过,也就是使用 Segoe MDL2 Assets 字体作为左侧 Icon,并且左侧使用填充颜色的矩形用来表示 ListView 的选中。
1342 0