擺脫第三方庫系列(一)- 自己寫一個側拉菜單

ffzv4484 8年前發布 | 9K 次閱讀 iOS開發 移動開發

前言

一直有這么一個想法,就是擺脫第三方庫來開發程序,雖然很不現實,但想嘗試做一點努力。這篇文章先實現比較常見的側拉菜單功能。

側拉菜單基本結構

一般側拉菜單就是一個中心頁和一個側邊頁構成。通過添加手勢移動中心頁,展示出側邊頁。

現在APP中常見的側拉菜單大體可以分成兩種類型的,一種是外國的APP(比如Steam,非死book)比較喜歡的分頁式的側拉菜單,就是用中心頁覆蓋住側邊頁,然后移動中心頁的時候就能展現出被中心頁覆蓋的側邊頁;還有一種就是國內(比如知乎日報)比較喜歡的一體式側拉菜單,側邊頁放置在中心頁的左邊或者右邊,拉動時就可展現另一頁內容。下面兩張圖第一張是分頁式,第二張是一體式。

擺脫第三方庫系列(一)- 自己寫一個側拉菜單

擺脫第三方庫系列(一)- 自己寫一個側拉菜單

實現側拉菜單

這篇文章將主要介紹一體式側拉菜單的寫法。

先創建一個側邊頁TogetherLeftView,最簡單的繼承于UIView的普通頁面就行。在里面重寫了初始化方法,改個顏色便于區分。

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
        if (self) {
        self.backgroundColor = [UIColor redColor];
    }
    return self;
}

然后就是中心頁TogetherMainView,一般將手勢寫在這一頁。先聲明兩個對象兩個變量。還有宏定義側邊頁的寬度

#define LEFTVIEWWIDTH 280

@interface TogetherMainView : UIView @property (nonatomic, assign) float centerX; @property (nonatomic, assign) float centerY; @property (nonatomic, strong) UIPanGestureRecognizer panGestureRecognizer; @property (nonatomic, strong) UIButton leftBtn; </code></pre>

其中UIPanGestureRecognizer是蘋果公司給的基本手勢抽象類中的拖動手勢,View添加這個后就可以拖動了。想學習其他基本手勢的可以看看蘋果UIGestureRecognizer的文檔,這里不做介紹。leftBtn是點擊后可以隱藏(出現)菜單的按鈕。

然后重寫初始化方法。

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        CGRect screen = [[UIScreen mainScreen] bounds];
        self.centerX = screen.size.width / 2;
        self.centerY = screen.size.height / 2;

    self.backgroundColor = [UIColor greenColor];

    [self addSubview:self.leftBtn];
    [self addGestureRecognizer:self.panGestureRecognizer];
}
return self;

} </code></pre>

這里的centerX和centerY是對屏幕初始中心位置的記錄,我們一會還原位置要用到。然后先看手勢部分,panGestureRecognizer的get方法如下

- (UIPanGestureRecognizer *)panGestureRecognizer
{
    if (_panGestureRecognizer == nil) {
        _panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
    }
    return _panGestureRecognizer;
}

這里給拖動時添加了一個方法handlePan,關鍵點就在這個方法里

- (void)handlePan:(UIPanGestureRecognizer *)recognizer
{
    CGPoint translation = [recognizer   translationInView:self];
    float x = self.center.x + translation.x;

if (x < _centerX) {
    x = _centerX;
}
self.center = CGPointMake(x, _centerY);

if (recognizer.state == UIGestureRecognizerStateEnded) {
    [UIView animateWithDuration:0.2 animations:^(void){
        if (x > (self.centerX + LEFTVIEWWIDTH/2)) {
            self.center = CGPointMake(self.centerX + LEFTVIEWWIDTH, _centerY);
        }else{
            self.center = CGPointMake(_centerX, _centerY);
        }
    }];
}
[recognizer setTranslation:CGPointZero inView:self];

} </code></pre>

當我們在View界面中拖動時就會進入這個方法,我們先設一個CGPoint來獲取每次得到的移動距離translation,然后float x就表示當前屏幕中心點的位置(原來的位置加上移動量)。

由于我寫的是一個左側的菜單,所以中心頁應該是不能左移的,假如我們左移,就會造成x < _centerX,那樣的話舊把x設成原來的中心點centerX就行了,這樣就能阻止中心頁左移。(如果想阻止右移把小于改成大于就行了。

然后就是在拖動效果結束(松開鼠標)時做一個判定,這里為了看起來平滑一點用了一個動畫效果,如果拖動距離超過側邊頁的一半舊顯示出側邊頁,否則還原。

最后還要將recognizer置位零。因為拖動時會多次執行這個方法,如果不置零可能出錯。

這樣最關鍵的部分就講解完了,然后上按鈕的動作代碼,應該可以看的懂。

- (UIButton *)leftBtn
{
    if (_leftBtn == nil) {
        _leftBtn = [[UIButton alloc] initWithFrame:CGRectMake(20, 20, 120, 40)];
        [_leftBtn setTitle:@"點我彈出菜單" forState:UIControlStateNormal];
        [_leftBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [_leftBtn addTarget:self action:@selector(leftViewAppear) forControlEvents:UIControlEventTouchUpInside];
    }
    return _leftBtn;
}

  • (void)leftViewAppear { [UIView animateWithDuration:0.2 animations:^(void){
      if (self.center.x == self.centerX) {
          self.center = CGPointMake(self.centerX + LEFTVIEWWIDTH, self.centerY);
      }else if (self.center.x == self.centerX + LEFTVIEWWIDTH) {
          self.center = CGPointMake(self.centerX, self.centerY);
      }
    
    }];

} </code></pre>

接下來就是添加到ViewController里面了,兩個頁面對象都要聲明

@property (nonatomic, strong) TogetherLeftView *leftView;
@property (nonatomic, strong) TogetherMainView *mainView;

這里上一下代碼,不做過多解釋

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.view addSubview:self.mainView];
    [self.mainView addSubview:self.leftView];
}

  • (TogetherMainView *)mainView { if (_mainView == nil) {

      _mainView = [[TogetherMainView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
    

    } return _mainView; }

  • (TogetherLeftView *)leftView { if (_leftView == nil) {

      _leftView = [[TogetherLeftView alloc] initWithFrame:CGRectMake(-LEFTVIEWWIDTH, 0, LEFTVIEWWIDTH, [UIScreen mainScreen].bounds.size.height)];
    

    } return _leftView; } </code></pre>

    那么如何寫一個分頁式的側拉菜單呢?其實主要的區別就是在ViewController中添加頁面的時候用中心頁將側邊頁覆蓋就行了,具體的代碼可以去我的github下載來看。

    總結

    我想將比較常用的功能都自己動手寫一遍這樣更能明白底層的原理,我覺得更適合新手的學習,直接用第三方庫誰都會,但哪天有需求變動要求你改你卻無從下手就很尷尬了。這個系列我也會堅持下去,同樣如果筆者哪里有錯的地方希望大家提出來我好改正。

    來源:http://cbsfly.github.io/ios/slipview

 本文由用戶 ffzv4484 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!