`
stephen830
  • 浏览: 3011335 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

iOS的自定义的滑动菜单控件

 
阅读更多

 

 

ZJQBOSwipeMenuOption.h

 

//
//  ZJQBOSwipeMenuOption.h
//  demo010
//
//  Created by zhoujianqiang on 15/9/26.
//  Copyright © 2015年 zhoujianqiang. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface ZJQBOSwipeMenuOption : NSObject

@property (nonatomic,assign) CGRect frame;//菜单区视图的frame属性

@property (nonatomic,strong) UIColor* selectedTextColor;//菜单被选中时的文字颜色
@property (nonatomic,strong) UIColor* unselectedTextColor;//菜单未选中时的文字颜色
@property (nonatomic,strong) UIColor* selectedTextBackground;//菜单被选中时的文字背景颜色
@property (nonatomic,strong) UIColor* unselectedTextBackground;//菜单未选中时的文字背景颜色
@property (nonatomic,strong) UIFont* textFont;//菜单字体大小

@property (nonatomic,strong) UIImage* selectedLineImage;//菜单被选中时底线颜色图片
@property (nonatomic,strong) UIImage* unselectedLineImage;//菜单未选中时底线颜色图片
@property (nonatomic,assign) CGFloat lineImageHeight;//菜单底线图片的高度

@property (nonatomic,assign) NSInteger max;//菜单数量显示上限,超过max数量的菜单必须通过左右滑动手势显示


#pragma mark 对象初始化-对象方法
-(instancetype)initWithFrame : (CGRect) frame
    andWithSelectedTextColor : (UIColor*) selectedTextColor
  andWithUnselectedTextColor : (UIColor*) unselectedTextColor
andWithSelectedTextBackground : (UIColor*) selectedTextBackground
andWithUnselectedTextBackground : (UIColor*) unselectedTextBackground
             andWithTextFont : (UIFont*) textFont
    andWithSelectedLineImage : (UIImage*) selectedLineImage
  andWithUnselectedLineImage : (UIImage*) unselectedLineImage
      andWithLineImageHeight : (CGFloat) lineImageHeight
                  andWithMax : (NSInteger) max;

#pragma mark 对象初始化-类方法
+(instancetype)initWithFrame : (CGRect) frame
    andWithSelectedTextColor : (UIColor*) selectedTextColor
  andWithUnselectedTextColor : (UIColor*) unselectedTextColor
andWithSelectedTextBackground : (UIColor*) selectedTextBackground
andWithUnselectedTextBackground : (UIColor*) unselectedTextBackground
             andWithTextFont : (UIFont*) textFont
    andWithSelectedLineImage : (UIImage*) selectedLineImage
  andWithUnselectedLineImage : (UIImage*) unselectedLineImage
      andWithLineImageHeight : (CGFloat) lineImageHeight
                  andWithMax : (NSInteger) max;
@end

ZJQBOSwipeMenuOption.m

//
//  ZJQBOSwipeMenuOption.m
//  demo010
//
//  Created by zhoujianqiang on 15/9/26.
//  Copyright © 2015年 zhoujianqiang. All rights reserved.
//

#import "ZJQBOSwipeMenuOption.h"

@implementation ZJQBOSwipeMenuOption



#pragma mark 对象初始化-对象方法
-(instancetype)initWithFrame : (CGRect) frame
    andWithSelectedTextColor : (UIColor*) selectedTextColor
  andWithUnselectedTextColor : (UIColor*) unselectedTextColor
andWithSelectedTextBackground : (UIColor*) selectedTextBackground
andWithUnselectedTextBackground : (UIColor*) unselectedTextBackground
             andWithTextFont : (UIFont*) textFont
    andWithSelectedLineImage : (UIImage*) selectedLineImage
  andWithUnselectedLineImage : (UIImage*) unselectedLineImage
      andWithLineImageHeight : (CGFloat) lineImageHeight
                  andWithMax : (NSInteger) max
{
    if (self=[super init]) {
        _frame=frame;
        _selectedTextColor=selectedTextColor;
        _unselectedTextColor=unselectedTextColor;
        _selectedTextBackground=selectedTextBackground;
        _unselectedTextBackground=unselectedTextBackground;
        _textFont=textFont;
        _selectedLineImage=selectedLineImage;
        _unselectedLineImage=unselectedLineImage;
        _lineImageHeight=lineImageHeight;
        _max=max;
    }
    return self;
}

#pragma mark 对象初始化-类方法
+(instancetype)initWithFrame : (CGRect) frame
    andWithSelectedTextColor : (UIColor*) selectedTextColor
  andWithUnselectedTextColor : (UIColor*) unselectedTextColor
andWithSelectedTextBackground : (UIColor*) selectedTextBackground
andWithUnselectedTextBackground : (UIColor*) unselectedTextBackground
             andWithTextFont : (UIFont*) textFont
    andWithSelectedLineImage : (UIImage*) selectedLineImage
  andWithUnselectedLineImage : (UIImage*) unselectedLineImage
      andWithLineImageHeight : (CGFloat) lineImageHeight
                  andWithMax : (NSInteger) max
{
    ZJQBOSwipeMenuOption* option = [[ZJQBOSwipeMenuOption alloc] initWithFrame:frame
                                                      andWithSelectedTextColor:selectedTextColor
                                                    andWithUnselectedTextColor:unselectedTextColor
                                                 andWithSelectedTextBackground:selectedTextBackground
                                               andWithUnselectedTextBackground:unselectedTextBackground
                                                               andWithTextFont:textFont
                                                      andWithSelectedLineImage:selectedLineImage
                                                    andWithUnselectedLineImage:unselectedLineImage
                                                        andWithLineImageHeight:lineImageHeight
                                                                    andWithMax:max];
    return option;
}
@end

 

ZJQBOSwipeMenuOption.h

//
//  ZJQSwipeMenuView.h
//  demo010
//
//  Created by zhoujianqiang on 15/9/26.
//  Copyright © 2015年 zhoujianqiang. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "ZJQBOSwipeMenuOption.h"

@protocol ZJQSwipeMenuViewDelegate <NSObject>

-(void)menuClickedAtIndex : (NSInteger) index;

@end

@interface ZJQSwipeMenuView : UIView

@property (nonatomic,strong) NSMutableArray* menus; //菜单数组:字符串数组类型,例如[@"菜单1",@"菜单2",...]
@property (nonatomic,strong) ZJQBOSwipeMenuOption* option;//菜单参数
@property (nonatomic,strong) id <ZJQSwipeMenuViewDelegate> delegate;//委托代理

-(instancetype)initWithMenus : (NSMutableArray*) menus
               andWithOption : (ZJQBOSwipeMenuOption*) option;
@end

 

ZJQSwipeMenuView.m

//
//  ZJQSwipeMenuView.m
//  demo010
//
//  Created by zhoujianqiang on 15/9/26.
//  Copyright © 2015年 zhoujianqiang. All rights reserved.
//

#import "ZJQSwipeMenuView.h"
#define TAG_MENU 10000 //菜单默认起始tag属性值
#define TAG_LINE 20000 //菜单下划线默认起始tag属性值

@implementation ZJQSwipeMenuView
{
@private
    CGFloat menuWidth_;//单个菜单占用的宽度
    NSInteger count_;//总的菜单个数
    NSInteger showedCount_;//屏幕显示的菜单个数
    NSInteger rightIndexInAllMenus_;//最右边菜单索引号,在整个菜单数组中从0开始计数的
    BOOL hasUnshowedMenu_;//是否有屏幕未展示的菜单,如果菜单总数超过菜单上限,那么肯定为YES
    NSInteger selectedMenuIndex_;//当前选择的菜单索引号
    
    CGPoint touchBeginPoint_;//触摸移动开始位置
    CGFloat minX_;//菜单区起点x最小值
    CGFloat maxX_;//菜单区起点x最大值
}

#pragma mark --------> 构造器 <--------
-(instancetype)initWithMenus : (NSMutableArray*) menus
              andWithOption : (ZJQBOSwipeMenuOption*) option
{
    if (self=[super init]) {
        _menus=menus;
        _option=option;
        [self _init];
    }
    return self;
}

#pragma mark --------> 初始化 <--------
-(void)_init {
    [self _initView];
    [self _initVariables];
    [self _initMenus];
}

-(void)_initView{
    self.frame=_option.frame;//菜单区frame
}

-(void)_initVariables{
    count_=_menus.count;//总的菜单个数
    showedCount_=(count_>_option.max)?_option.max:count_;//屏幕显示的菜单个数,如果超过菜单显示上限,则后面的不显示
    CGFloat width = self.frame.size.width;//菜单区的宽度
    CGFloat frameX=self.frame.origin.x;
    menuWidth_=width/showedCount_;//单个菜单占用的宽度
    rightIndexInAllMenus_=showedCount_-1;//最右边菜单索引号
    selectedMenuIndex_=0;//屏幕上被选中菜单的索引号
    hasUnshowedMenu_=(count_>_option.max)?YES:NO;//是否有屏幕未展示的菜单
    
    //重新计算菜单区的宽度
    CGFloat newWidth = count_*menuWidth_;
    newWidth = (newWidth>width)? newWidth:width;
    CGRect newFrame = self.frame;
    newFrame.size.width=newWidth;
    self.frame=newFrame;
    //计算菜单区起点x坐标的范围
    maxX_=frameX;
    minX_=maxX_+width-self.frame.size.width;
}

-(void)_initMenus {
    for (int i=0; i<count_; i++) {
        //
        BOOL isSelected = (selectedMenuIndex_==i);
        [self _addMenu:isSelected andWithIndexInShowedMenus:i andWithIndexInAllMenus:i andIsAppnedAtTail:YES];
    }
}

#pragma mark --------> tag与菜单项的关系操作区 <--------
-(NSInteger) _getMenuTagWithIndexInAllMenus : (NSInteger) indexInAllMenus{
    return TAG_MENU+indexInAllMenus;
}

-(NSInteger) _getIndexInAllMenusWithMenuTag : (NSInteger) menuTag{
    return menuTag-TAG_MENU;
}

-(NSInteger) _getLineTagWithIndexInAllMenus : (NSInteger) indexInAllMenus{
    return TAG_LINE+indexInAllMenus;
}

-(NSInteger) _getIndexInAllMenusWithLineTag : (NSInteger) lineTag{
    return lineTag-TAG_LINE;
}


#pragma mark --------> 添加1项菜单 <--------
-(void)_addMenu : (BOOL) isSelected andWithIndexInShowedMenus : (NSInteger) indexInShowedMenus andWithIndexInAllMenus :(NSInteger) indexInAllMenus andIsAppnedAtTail : (BOOL) isAppendAtTail{
    //菜单文字
    NSString* menuTitle = _menus[indexInAllMenus];
    
    UILabel* lblTabMenu = [[UILabel alloc]init];
    lblTabMenu.frame = CGRectMake(indexInShowedMenus*menuWidth_, 0, menuWidth_, self.frame.size.height-_option.lineImageHeight);
    lblTabMenu.backgroundColor=(isSelected)?_option.selectedTextBackground:_option.unselectedTextBackground;
    lblTabMenu.text=menuTitle;
    lblTabMenu.textColor=(isSelected)?_option.selectedTextColor:_option.unselectedTextColor;
    lblTabMenu.font=_option.textFont;
    lblTabMenu.textAlignment=NSTextAlignmentCenter;
    lblTabMenu.tag=[self _getMenuTagWithIndexInAllMenus:indexInAllMenus];
    
    lblTabMenu.userInteractionEnabled=YES;
    UITapGestureRecognizer* tapGestureRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(_menuClicked:)];
    [lblTabMenu addGestureRecognizer:tapGestureRecognizer];
    
    
    
    UIImageView* ivLine = [[UIImageView alloc]init];
    ivLine.image = (isSelected)?_option.selectedLineImage:_option.unselectedLineImage;
    ivLine.frame= CGRectMake(indexInShowedMenus*menuWidth_, self.frame.size.height-_option.lineImageHeight, menuWidth_, _option.lineImageHeight);
    ivLine.tag=[self _getLineTagWithIndexInAllMenus:indexInAllMenus];

    if (isAppendAtTail) {
        [self addSubview:lblTabMenu];
        [self addSubview:ivLine];
    }else{
        //注意插入最前面的时候,顺序要和上面的相反
        [self insertSubview:ivLine atIndex:0];
        [self insertSubview:lblTabMenu atIndex:0];
    }
    ivLine.alpha=0;
    [UIView animateWithDuration:0.5 animations:^{ ivLine.alpha = 1; } completion:^(BOOL finished){ }];
    
}


#pragma mark --------> 按钮点击和滑动手势事件区 <--------
-(void) _menuClicked : (UITapGestureRecognizer*) sender {
    UILabel* lblMenu = (UILabel*)sender.view;
    NSInteger tag = lblMenu.tag;
    NSInteger menuIndex = [self _getIndexInAllMenusWithMenuTag:tag];
    
    [self _didSelectMenuAtIndex:menuIndex];
    
    //让delegate去继续执行
    if (_delegate) {
        if ([_delegate respondsToSelector:@selector(menuClickedAtIndex:)]) {
            [_delegate menuClickedAtIndex:menuIndex];
        }
    }
}

-(void) _didSelectMenuAtIndex : (NSInteger) menuIndex {
    
    //将之前选择的菜单取消选择
    NSInteger lblOldMenuTag = [self _getMenuTagWithIndexInAllMenus:selectedMenuIndex_];
    UILabel* lblOldMenu = (UILabel*) [self viewWithTag:lblOldMenuTag];
    lblOldMenu.backgroundColor=_option.unselectedTextBackground;
    lblOldMenu.textColor=_option.unselectedTextColor;
    
    NSInteger oldLineTag = [self _getLineTagWithIndexInAllMenus:selectedMenuIndex_];
    UIImageView* ivOldLine = (UIImageView*) [self viewWithTag:oldLineTag];
    ivOldLine.image=_option.unselectedLineImage;
    
    
    //选择当前点中的菜单
    NSInteger lblMenuTag = [self _getMenuTagWithIndexInAllMenus:menuIndex];
    UILabel* lblMenu = (UILabel*) [self viewWithTag:lblMenuTag];
    lblMenu.backgroundColor=_option.selectedTextBackground;
    lblMenu.textColor=_option.selectedTextColor;
    
    NSInteger lineTag = [self _getLineTagWithIndexInAllMenus:menuIndex];
    UIImageView* ivLine = (UIImageView*) [self viewWithTag:lineTag];
    ivLine.image=_option.selectedLineImage;

    
    //更新当前选中的菜单索引
    selectedMenuIndex_=menuIndex;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch* touch = [touches anyObject];
    touchBeginPoint_=[touch locationInView:self];
    [super touchesBegan:touches withEvent:event];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch* touch = [touches anyObject];
    CGPoint point = [touch locationInView:self];
    //x坐标变化
    CGFloat xChanged = point.x-touchBeginPoint_.x;
    //xChanged<0表示向左移动,xChanged>0表示向右移动
    //判断是否可以移动菜单
    BOOL isCanMoveMenu = NO;
    CGFloat newX = self.frame.origin.x+xChanged;
    isCanMoveMenu = (newX>=minX_ && newX<=maxX_);
    //修改菜单区frame
    CGRect newFrame = self.frame;
    if (isCanMoveMenu) {
        newFrame.origin.x=newFrame.origin.x+xChanged;
    }else{
        if (xChanged>0) {
            newFrame.origin.x=maxX_;
        }else{
            newFrame.origin.x=minX_;
        }
    }
    self.frame=newFrame;
}

@end

 

 调用方法:

ViewController996.h

//
//  ViewController996.h
//  demo010
//
//  Created by zhoujianqiang on 15/9/26.
//  Copyright © 2015年 zhoujianqiang. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "ZJQBOSwipeMenuOption.h"
#import "ZJQSwipeMenuView.h"

@interface ViewController996 : UIViewController<ZJQSwipeMenuViewDelegate>


@property (nonatomic,strong) ZJQSwipeMenuView* swipeMenuView;
@property (nonatomic,strong) ZJQBOSwipeMenuOption* menuOption;
@end

 

ViewController996.m

//
//  ViewController996.m
//  demo010
//
//  Created by zhoujianqiang on 15/9/26.
//  Copyright © 2015年 zhoujianqiang. All rights reserved.
//

#import "ViewController996.h"
#define IOS7 [[[UIDevice currentDevice]systemVersion] floatValue] >= 7.0 //判断SDK版本号是否是7.0或7。0以上


@interface ViewController996 ()

@end

@implementation ViewController996

#pragma mark ----------> 系统方法区 <----------
- (void)viewDidLoad {
    [super viewDidLoad];
    [self _init];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}


#pragma mark ----------> 初始化 <----------
-(void)_init{
    if (IOS7) {
        self.edgesForExtendedLayout=UIRectEdgeNone;
    }
    self.title=@"Swipe Menu";
    [self _initPropertys];
}

-(void)_initPropertys{
    CGRect frame = CGRectMake(0, 0, self.view.frame.size.width, 40);
    _menuOption = [ZJQBOSwipeMenuOption initWithFrame:frame andWithSelectedTextColor:[UIColor redColor] andWithUnselectedTextColor:[UIColor blackColor] andWithSelectedTextBackground:[UIColor whiteColor] andWithUnselectedTextBackground:[UIColor whiteColor] andWithTextFont:[UIFont systemFontOfSize:13] andWithSelectedLineImage:[UIImage imageNamed:@"r"] andWithUnselectedLineImage:[UIImage imageNamed:@"w"] andWithLineImageHeight:3 andWithMax:6];
    
    NSMutableArray* menus = [[NSMutableArray alloc]init];
    for (int i=0; i<10; i++) {
        [menus addObject:[NSString stringWithFormat:@"菜单%d",i]];
    }
    
    _swipeMenuView = [[ZJQSwipeMenuView alloc]initWithMenus:menus andWithOption:_menuOption];
    [self.view addSubview:_swipeMenuView];
    
    _swipeMenuView.delegate=self;
}

#pragma mark ----------> 实现ZJQSwipeMenuViewDelegate中的方法 <----------
-(void)menuClickedAtIndex:(NSInteger)index{
    NSLog(@"menuClickedAtIndex:index=%ld,%@",index,_swipeMenuView.menus[index]);
}

@end

 

 

 

效果图:



 

 

 完整工程代码为附件中的demo010.zip

  • 大小: 50.1 KB
分享到:
评论

相关推荐

    仿ios滑动控件

    在Android应用开发中,"仿ios滑动控件"是一个常见的需求,主要是为了提供与iOS设备上相似的用户体验。这个控件通常指的是实现类似于iOS中PickerView或SegmentedControl的功能,它允许用户通过滑动来选择不同的选项。...

    IOS 左右滑动菜单

    在iOS开发中,"左右滑动菜单"是一种常见的交互设计,它允许用户通过左右滑动手势在多个视图之间切换,通常用于展示主菜单、设置或者其他功能选项。这种设计模式在许多应用程序中都能看到,例如社交应用、电商应用等...

    iOS自定义侧滑删除按钮功能

    UITableView是iOS中用于展示列表数据的核心控件,它由一个个单元格(UITableViewCell)组成。每个单元格都可以自定义显示内容和交互行为。在这个案例中,我们需要实现的功能就是在单元格被滑动时,展示一个或多个可...

    IOS自定义控件集合(TabBar,nav bar等)

    标题提到的“IOS自定义控件集合(TabBar, nav bar等)”涵盖了两个关键组件:TabBar(标签栏)和NavBar(导航栏),这些都是iOS界面设计中的核心元素。下面将详细介绍这两个控件以及自定义它们的方法。 首先,...

    ios-自定义支持纵向横向滑动的滑杆,可设置正向和逆向的排序.zip

    1. **自定义滑动方向**: 通常,iOS中的滑杆是水平滑动的,但"ZHPSlider"允许你改变滑动方向,可以设置为纵向滑动。这种特性使得滑杆在垂直布局或者空间有限的界面设计中更加实用。 2. **正向和逆向排序**: 滑杆...

    ios-自定义分段控件.zip

    在iOS开发中,分段控件(Segmented Control)是一种常用的UI组件,它允许用户在多个相关选项之间进行切换。本教程将详细讲解如何使用Swift语言实现一个自定义的分段控件,使得每个选项不仅可以包含文字,还能支持...

    ios-横向滑动菜单.zip

    在iOS开发中,横向滑动菜单是一种常见的交互设计,它为用户提供了一种便捷的方式来浏览或切换不同的内容区域。"ios-横向滑动菜单.zip"是一个包含实现这种功能的代码资源的压缩包,其中的核心文件是...

    IOS源码应用Demo-iphone开发技巧UI篇之自定义TabBar CustomTabBar.zip

    4. **扩展功能**:例如增加下拉菜单、滑动切换等功能,提供更多操作入口。 在实现自定义TabBar的过程中,开发者通常会用到以下技术: - **Swift或Objective-C**:iOS开发的两种主要编程语言,用于编写TabBar的逻辑...

    iOS实现滑动弧形菜单的思路与方法

    首先,要实现滑动弧形菜单,开发者需要对UI控件进行自定义布局。在文章中,作者起初尝试通过自定义UICollectionView的layout来实现,但最终还是选择使用UIView来构建整个弧形菜单。这表明在一些特殊的布局需求下,...

    下拉菜单 下拉抽屉 自定义控件

    本话题将详细探讨"下拉菜单"和"下拉抽屉"这两种常见的自定义控件,并结合实际项目中的应用进行阐述。 首先,下拉菜单(Dropdown Menu)是一种常见的交互元素,常用于空间有限但选项众多的场景。在用户界面中,它以...

    自定义日期控件

    在IT领域,自定义日期控件是用户界面(UI)设计中的一个重要组成部分,尤其是在开发Web应用、桌面软件或移动应用时。日期控件允许用户方便地选择和输入日期,为用户提供直观、友好的交互体验。下面我们将深入探讨...

    iOS导航下拉菜单

    1. 创建自定义导航栏视图:继承自UIView,并在其中添加一个下拉菜单的UI控件,例如UILabel、UIButton或UICollectionView。这些控件将作为下拉菜单的选项显示。 2. 实现下拉菜单的动画效果:可以通过手势识别(如...

    ios-简单的自定义分享样式.zip

    `YXCustomActionSheet`的设计思路和实现方式对iOS开发者来说是一个很好的学习参考,特别是在处理自定义UI组件和控件布局时。同时,它也展示了如何利用Swift或Objective-C进行组件封装,以便在不同项目中复用。

    android仿ios三级菜单效果的demo

    首先,iOS的三级菜单通常表现为滑动选择器,每一级都是一个可滚动的列表,当选择某一项时,下一级别的选项会根据当前选中项的变化而更新。在Android中,我们可以使用`Spinner`控件或者自定义视图来实现类似的效果。...

    自定义日期选择控件 三级联动

    同时,我们也可以考虑使用滑动选择而非点击下拉菜单,这将需要实现滑动手势检测,可能需要用到`GestureDetector`和`Scroller`类。 此外,考虑到性能优化,我们可以将部分计算和更新操作放在子线程中,避免阻塞主线...

    ios-导航菜单栏、支持左右滑动.zip

    总之,这个项目提供了一个自定义的、可滑动的导航菜单栏实现,对于想要学习自定义视图和手势识别的iOS开发者来说,是一个很好的实践案例。通过深入研究这个项目,开发者可以学习到如何在没有`UINavigationController...

    swift-iOS侧滑控件支持左右滑动的侧滑菜单可配置单侧滑动

    Swift-iOS侧滑控件,如描述中提到的支持左右滑动的侧滑菜单,是实现这种常见交互模式的有效工具。这种控件允许用户通过在主屏幕内容上进行左滑或右滑手势来展示隐藏的侧边菜单,为用户提供快捷的导航选项。 侧滑...

    史上最全最好用的滑动控件

    在iOS开发中,许多优秀的滑动控件来自第三方库,如SWRevealViewController(用于侧滑菜单)、Segment.io(用于选项卡切换)和CollectionViewSlantedLayout(提供倾斜效果的UICollectionView布局)。这些第三方库通常...

    swift-iOSSwift下拉菜单列表

    标签"Swift开发-菜单控件"提示我们关注的重点是Swift中的菜单控件实现。在UIKit中,没有直接提供下拉菜单的控件,但可以通过组合现有控件,如UIButton和UITableView,来创建自定义的下拉菜单效果。 在...

Global site tag (gtag.js) - Google Analytics