iOS 水平方向彈出選單(支援展開摺疊)

語言: CN / TW / HK

小知識,大挑戰!本文正在參與“程式設計師必備小知識”創作活動。

本文同時參與 「掘力星計劃」    ,贏取創作大禮包,挑戰創作激勵金

前言

1.支援展開摺疊的彈出選單的實現思路:

1.1將彈出檢視新增到keyWindow,蒙版也新增到主視窗(主要原因是點選螢幕的空白處,需要隱藏彈出檢視)

1.2展示的時候,動畫從右上角往左下腳延伸;隱藏的時候,動畫從左下腳往右上角收回 (展示的時候,從上往下,即x,y 慢慢變大)

1.3 內部檢視採用collectionView進行佈局

1.4 view的frame 是根據當前點選的選單按鈕所在的商品cell進行計算和座標轉換的。

```objectivec / 觸發摺疊選單隱藏和顯示的按鈕 / @property (nonatomic,weak) UIButton btn;

/ 用於計算摺疊選單frame, / @property (nonatomic,weak) UIButton tmpbtn;

```

2.水平方向彈出選單檢視的應用場景:

2.1、門店商品的支援的功能: 向右橫向展開檢視(操作:下/上架、列印、編輯、同步網路)支援再次摺疊隱藏檢視 在這裡插入圖片描述

2.2、網店商品目前只包含下架功能:展開摺疊檢視:(包含上/下架商品功能) 在這裡插入圖片描述

  1. 豎向彈出選單檢視

    彈出選單:會員模組的右上角的下拉選單(豎向) https://kunnan.blog.csdn.net/article/details/84618986在這裡插入圖片描述

影片: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,蒙版也新增到主視窗(主要原因是點選螢幕的空白處,需要隱藏彈出檢視)

```objectivec #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進行佈局

```objectivec @property (strong, nonatomic) UICollectionView *collectionView;

```

1.4 view的frame 是根據當前點選的選單按鈕所在的商品cell進行計算和座標轉換的。

```objectivec 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. 構建選單內部的資料模型

```objectivec + (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的懶載入

```objectivec

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 監聽彈出和摺疊事件

```objectivec /* 監聽彈出事件,此事件由展示商品資訊的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];

}];

``` - 判斷是展開彈出選單,還是摺疊

```objectivec

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 設定兩個測試開關 ```bash [self addpopV2cell];// 測試開關1:將水平方向彈出選單檢視整合到cell

// [self addpopV2VCView];// 測試開關2:將水平方向彈出選單檢視整合到VC的View

```

3.1 demo1: 將水平方向彈出選單檢視整合到cell

demo1下載地址:https://download.csdn.net/download/u011018979/20598998 疑問解答,請關注公眾號:iOS逆向

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 疑問解答,請關注公眾號:iOS逆向

1.支援展開摺疊的彈出選單的實現思路:

1.1將彈出檢視新增到keyWindow,蒙版也新增到主視窗(主要原因是點選螢幕的空白處,需要隱藏彈出檢視) 1.2展示的時候,動畫從右上角往左下腳延伸;隱藏的時候,動畫從左下腳往右上角收回 (展示的時候,從上往下,即x,y 慢慢變大) 1.3 內部檢視採用collectionView進行佈局 1.4 view的frame 是根據當前點選的選單按鈕所在的商品cell進行計算和座標轉換的。

2.水平方向彈出選單檢視的應用場景:

2.1、門店商品的支援的功能: 向右橫向展開檢視(操作:下/上架、列印、編輯、同步網路)支援再次摺疊隱藏檢視 在這裡插入圖片描述

2.2、網店商品目前只包含下架功能:展開摺疊檢視:(包含上/下架商品功能) 在這裡插入圖片描述

3.3 水平方向彈出選單檢視

彈出選單HorizontalpopupView的具體程式碼

在這裡插入圖片描述

  • .h

```objectivec

import

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

```objectivec

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 )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

```objectivec 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 ```objectivec

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

  1. 豎向彈出選單檢視

    彈出選單:會員模組的右上角的下拉選單(豎向) https://kunnan.blog.csdn.net/article/details/84618986在這裡插入圖片描述

  2. 【點選導航條標題,下拉選擇分類】iOS導航條的標題按鈕的左側是分類名稱,右邊的下拉圖示

    https://blog.csdn.net/z929118967/article/details/104315227在這裡插入圖片描述

更多資訊和服務請關注#小程式:iOS逆向,只為你呈現有價值的資訊,專注於移動端技術研究領域。

image.png