pbootcms网站模板|日韩1区2区|织梦模板||网站源码|日韩1区2区|jquery建站特效-html5模板网

iOS開發之路--仿網易抽屜效果

本文是IOS開發之路系列的第一篇,主要講訴了如何仿網易新聞客戶端實現抽屜效果,全部源代碼都分享給大家,希望對大家有所幫助

最終效果圖:


MainStoryBoard示意圖:


BeyondViewController.h


//
// BeyondViewController.h
// 19_抽屜效果_仿網易
//
// Created by beyond on 14-8-1.
// Copyright (c) 2014年 com.beyond. All rights reserved.
//

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



@interface BeyondViewController : UIViewController
// 左半邊 (顯示 的是欄目列表 )
@property (weak, nonatomic) IBOutlet UIView *leftView;
// 右半邊 (顯示 的是個人信息設置視圖)
@property (weak, nonatomic) IBOutlet UIView *rightView;
// 最上面,最大的全屏的是主視圖
@property (weak, nonatomic) IBOutlet UIView *mainView;



// 上面標題狀態欄視圖中的標題按鈕 (網易的Logo圖片和欄目的名稱 水平排列)
@property (weak, nonatomic) IBOutlet UIButton *titleBtn;

// mainView的下半部分 是 正文的view,顯示子欄目的view
@property (weak, nonatomic) IBOutlet UIView *contentView;



// pan 拽 手勢處理
- (IBAction)panGesture:(UIPanGestureRecognizer *)sender;

// mainView的上半部分 標題狀態欄視圖中的左,右按鈕
- (IBAction)btnClick:(UIButton *)sender;


@end

BeyondViewController.m


//
// BeyondViewController.m
// 19_抽屜效果_仿網易
//
// Created by beyond on 14-8-1.
// Copyright (c) 2014年 com.beyond. All rights reserved.
//

#import "BeyondViewController.h"
#import "LeftTableViewController.h"
#import "RightViewController.h"
#import "Column.h"
#import <QuartzCore/QuartzCore.h>
// 手勢結束時的x
#define kEndX frame.origin.x
// 左view的寬度
#define kLeftWidth _leftView.frame.size.width

// 右view的寬度
#define kRightWidth _rightView.frame.size.width

// 對協議進行提前聲明
@protocol LeftTableViewControllerDelegate ;

@interface BeyondViewController ()<LeftTableViewControllerDelegate>
{
  // 手指按下的時候,記住,mainView的起始x
  CGFloat _startX;
  
  // 成員變量,記住左邊控制器的實例
  LeftTableViewController *_leftVC;
  // 成員變量,記住右邊控制器的實例
  RightViewController *_rightVC;
  
  
  // 字典 ,記住所有實例化了 欄目的子控制器,避免每次都重新創建
  NSMutableDictionary *_columnViewControllers;
  
}

@end

@implementation BeyondViewController
// 隱藏狀態欄
- (BOOL)prefersStatusBarHidden
{
  return YES;
}
- (void)viewDidLoad
{
  [super viewDidLoad];
  
  _titleBtn.backgroundColor = [UIColor clearColor];
  
  // 0 字典 ,記住所有實例化了 欄目的子控制器,避免每次都重新創建
  _columnViewControllers = [NSMutableDictionary dictionary];
  
  // 0,設置導航條bar的背景 為網 易 紅
  //[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:@"bg.png"] forBarMetrics:UIBarMetricsDefault];
  // 狀態條顏色 改成默認的樣式
  //[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault;
  
  // 1,添加左邊控制器的view到左邊的view里面
  _leftVC = [[LeftTableViewController alloc]init];
  // 關鍵代碼 為了拿到左邊控制器的某一行被點擊時候,對應的欄目數據模型對象,主控制器成為了左邊控制器的代理,遵守了它定好的協議,實現了協議中的方法,從而拿到左邊控制器被點擊行號對應的數據模型對象
  _leftVC.delegate = self;
  _leftVC.view.frame = self.leftView.bounds;
  
  [self.leftView addSubview:_leftVC.view];
  
  // 2,同理,添加右邊控制器的view到右邊的view里面
	_rightVC = [[RightViewController alloc]init];
  
  _rightVC.view.frame = self.rightView.bounds;
  
  [self.rightView addSubview:_rightVC.view];

  // 3,第一次加載時候,就就應該顯示新聞 子欄目的控制器到導航控制器,再將導航控制器的view添加到 mainView里面
  [self firstLoading];
  
  
}


// 自定義方法,第一次加載時候,就就應該顯示新聞 子欄目的控制器到導航控制器,再將導航控制器的view添加到 mainView里面
- (void)firstLoading
{
  Column * column = [Column columnNamed:@"新聞" imgName:@"news.png" className:@"NewsViewController"];
  
  // 僅需手動調用一個 LeftViewController的代理 方法,leftTableViewRowClicked,傳遞一個新聞 子欄目即可
  [self leftTableViewRowClicked:column];
}

// pan 拽 手勢處理
- (IBAction)panGesture:(UIPanGestureRecognizer *)sender
{
  
  // 如果是剛按下的狀態,則記住,mainView的起始x
  if (UIGestureRecognizerStateBegan == sender.state) {
    _startX = self.mainView.frame.origin.x;
  }
  
  
  // 平移拖動的距離
  CGPoint delta = [sender translationInView:_mainView];
  
  CGRect frame = self.mainView.frame;
  
  // 計算新的x值,并做健壯性判斷
  kEndX = _startX + delta.x;
  
  // 1,限制最大拖動范圍
  
  if (kEndX >= kLeftWidth) {
    kEndX = kLeftWidth;
  }
  if (kEndX <= - kRightWidth) {
    kEndX = - kRightWidth;
  }
  // 2,由于 左view和右view在重疊,所以要隱藏其中的一個
  if (kEndX > 0) {
    // NSLog(@"--調用頻率相當高--");
    _rightView.hidden = YES;
    _leftView.hidden = NO;
  } else {
    _rightView.hidden = NO;
    _leftView.hidden = YES;
  }
  
  
  if (UIGestureRecognizerStateEnded == sender.state) {
    
    // 手勢結束的時候,需進行robust判斷
    
    // 2,分析end松手時候,的位置x,決定展開到什么程度
/*
    // 2.1 如果只向右拖了一點點,小于 1/2 的左view的寬度,則歸0
    if (kEndX < 0.5*kLeftWidth && kEndX >= 0) {
      kEndX = 0;
    }else if (kEndX >= 0.5*kLeftWidth && kEndX <= kLeftWidth) {
      // 2.2 如果向右拖一大半了,大于 1/2 的左view的寬度,雖然還沒到位,也可以認為是到位了
      kEndX = kLeftWidth;
    }else if (kEndX > - 0.5*kRightWidth && kEndX <= 0) {
      // 2.3 如果只向左拖了一點點,小于 1/2 的右view的寬度,則歸0
      kEndX = 0;
    }else if (kEndX <= - 0.5*kRightWidth) {
      // 2.4 如果向左拖一大半了,大于 1/2 的右view的寬度,雖然還沒到位,也可以認為是到位了
      kEndX = - kRightWidth;
    }
*/
    
    
    // 第2種判斷方式
    // 起始為0,delta.x大于0 代表向右滑動
    if (_startX == 0 && delta.x >0) {
      kEndX = kLeftWidth;
    }else if (_startX == 0 && delta.x < 0){
      // 起始為0,delta.x小于0 代表向左滑動
      kEndX = - kRightWidth;
    }else if (_startX == kLeftWidth && delta.x < 0){
      // 起始為kLeftWidth,delta.x小于0 代表向左滑動
      kEndX =0;
    }else if (_startX == - kRightWidth && delta.x > 0){
      // 起始為- kRightWidth,delta.x大于0 代表向右滑動
      kEndX = 0;
    }
    

    
  }
  
  // 最后,才設置mainView的新的frame
  [UIView animateWithDuration:0.2 animations:^{
        self.mainView.frame=frame;
  }];
  
  
  
  // 最后,為mainView所在的圖層 添加陰影效果
  [self addShadowFormainViewWithEndX:kEndX];
  
}

// 自定義方法,為mainView所在的圖層 添加陰影效果 (調用頻率相當高)
- (void)addShadowFormainViewWithEndX:(CGFloat)endX
{
  // 1,點擊工程,加號,導入第3方框架 #import <QuartzCore/QuartzCore.h>
  
  // 2,拿到mainView所在的圖層,設置陰影 參數
 
  // NSLog(@"調用頻率很高---");
  _mainView.layer.shadowColor = [UIColor blackColor].CGColor;
  _mainView.layer.shadowOpacity = 0.5;
  if (endX >= 0) {
    _mainView.layer.shadowOffset = CGSizeMake(-5, 0);
  } else {
    _mainView.layer.shadowOffset = CGSizeMake(5, 0);
  }
  
}

// 單擊按鈕,也一樣可以展開 左右側邊欄
- (IBAction)btnClick:(UIButton *)sender
{
  // 定義一個臨時變量
  CGFloat startX = _mainView.frame.origin.x;
  
  
  // 先為mainView所在的圖層 添加陰影效果
  [self addShadowFormainViewWithEndX:sender.tag == 1?1:-1];
  
  
  // 定義一個臨時變量
  CGFloat tempEndX = 0;
  // 左邊的按鈕被單擊
  if (1 == sender.tag) {
    // 隱藏右半邊
    _leftView.hidden = NO;
    _rightView.hidden = YES;
    
    if (startX == 0) {
      tempEndX = kLeftWidth;
    }else if (startX == kLeftWidth){
      tempEndX = 0;
    }
  } else {
    // 單擊右邊按鈕, 隱藏左半邊
    _leftView.hidden = YES;
    _rightView.hidden = NO;
    if (startX == 0) {
      tempEndX = - kRightWidth;
    }else if (startX == - kRightWidth){
      tempEndX = 0;
    }
  }
  // 最后才設置mainView的x,調用抽取出來的公共代碼,設置mainView的x,參數是endX
  [self setmainViewX:tempEndX];
  
  

}


// 抽取出來的公共代碼,設置mainView的x,參數是endX
- (void)setmainViewX:(CGFloat)endX
{
  CGRect frame = self.mainView.frame;
  frame.origin.x = endX;
  [UIView animateWithDuration:0.2 animations:^{
    self.mainView.frame=frame;
  }];
  
}



// 最關鍵的方法,左邊控制器的代理 方法,當前左邊控制器中的某一行被點擊的時候 會調用
- (void)leftTableViewRowClicked:(id)columnSelected
{
  Column *column = (Column *)columnSelected;
  // 1,關閉左邊的控制=======================
  // 調用抽取出來的公共代碼,設置mainView的x,參數是endX
  [self setmainViewX:0];
  
  
  
  // 2,更改標題按鈕上面的文字
  _titleBtn.titleLabel.text = column.columnName;
  
  // 根據欄目數據模型中的類名,實例化對應欄目的控制器,并且將其設置為導航控制器的根控制器,最后將導航控制器的view添加到mainView中,目的是方便設置導航條,以及,各控制器的跳轉
  
  
  // 2,從緩存字典中取,如果子控制器字典有曾經創建過的子控制器,直接取出來用
  UIViewController *columnVC = _columnViewControllers[column.columnClassName];
  // 如果子控制器字典中沒有保存過該欄目的控制器,才要創建子控制器
  if (columnVC == nil) {
    Class c = NSClassFromString(column.columnClassName);
    columnVC = [[c alloc]init];
    // 并且一定要將其放到 子控制器字典里面,存起來
    [_columnViewControllers setObject:columnVC forKey:column.columnClassName];
  }
    
  // 4,移除contentView中的正在顯示的舊的子view
  if (_contentView.subviews.count > 0) {
    UIView *oldView = [_contentView subviews][0];
    [oldView removeFromSuperview];
  }

  // 5,最后將子控制器的view添加到contentView中,顯示
  columnVC.view.frame = _contentView.bounds;
  [self.contentView addSubview:columnVC.view];
  NSLog(@"%@",self.contentView);
  // 在添加到mainView之前 ,先得到mainView導航控制器的子控制器,并將其移除(如果有的話),然后才將新的欄目對應的子控制器添加到導航控制器容器中,注意,這兒可以用字典 記住 所有的已經實例化出來 的欄目子控制器,這樣就避免每次都alloc創建新的欄目子控制器,而是只需要根據類名,從字典取出上一次實例化了的同一欄目的子控制器即可
  
}
@end

欄目數據模型Column.h


//
// Column.h
// 19_抽屜效果_仿網易
//
// Created by beyond on 14-8-1.
// Copyright (c) 2014年 com.beyond. All rights reserved.
//

#import <Foundation/Foundation.h>

// 數據模型 代表一個欄目
@interface Column : NSObject
// 欄目名稱
@property (nonatomic,copy)NSString *columnName;
// 欄目圖片名稱
@property (nonatomic,copy)NSString *columnImgName;
// 欄目對應的控制器的類名
@property (nonatomic,copy)NSString *columnClassName;

// UI控件用weak,字符串用copy,其他對象用strong

// 提供一個類方法,即構造函數,返回封裝好數據的對象(返回id亦可)
+ (Column *)columnNamed:(NSString *)columnName imgName:(NSString*)columnImgName className:(NSString *)columnClassName;
@end

欄目數據模型Column.m


//
// Column.m
// 19_抽屜效果_仿網易
//
// Created by beyond on 14-8-1.
// Copyright (c) 2014年 com.beyond. All rights reserved.
// 數據模型 代表一條欄目

#import "Column.h"

@implementation Column

// 返回一個包含了 欄目對應控制器名字的 對象實例
+ (Column *)columnNamed:(NSString *)columnName imgName:(NSString *)columnImgName className:(NSString *)columnClassName
{
  // 為了兼容子類 使用self
  Column *column = [[self alloc]init];
  column.columnName = columnName;
  column.columnImgName = columnImgName;
  column.columnClassName = columnClassName;
  return column;
}

@end

左邊控制器定義好的協議LeftTableViewControllerDelegate.h


//
// LeftTableViewControllerDelegate.h
// 19_抽屜效果_仿網易
//
// Created by beyond on 14-8-1.
// Copyright (c) 2014年 com.beyond. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Column.h"
// 左邊控制器 定義的代理/協議 它通過調用自己的成員屬性(即代理)的該方法,將數據傳遞出去(給它的代理去使用) (其實 是主控制器想要數據,所以主控制器在實例化左邊控制器的時候,要設置左邊控制器對應的代理 為 主控制器 自身)
@protocol LeftTableViewControllerDelegate <NSObject>


- (void)leftTableViewRowClicked:(Column *)columnSelected;
@end

LeftTableViewController.h


//
// LeftTableViewController.h
// 19_抽屜效果_仿網易
//
// Created by beyond on 14-8-1.
// Copyright (c) 2014年 com.beyond. All rights reserved.
//

#import <UIKit/UIKit.h>
// 對協議進行提前聲明
@protocol LeftTableViewControllerDelegate;


@interface LeftTableViewController : UITableViewController
// 代理 用weak,防止循環問題,可以是任意類型,但必須遵守協議
@property (nonatomic,weak) id<LeftTableViewControllerDelegate> delegate;
@end

LeftTableViewController.m


//
//  LeftTableViewController.m
//  19_抽屜效果_仿網易
//
//  Created by beyond on 14-8-1.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//

#import "LeftTableViewController.h"
#import "Column.h"
#import "LeftTableViewControllerDelegate.h"
@interface LeftTableViewController ()
{
    // 欄目數組,保存的是左邊欄目列表中的所有欄目對象
    NSArray *_arr;
}

@end

@implementation LeftTableViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // 新聞 欄目
    Column *newsColumn = [Column columnNamed:@"新聞" imgName:@"news.png" className:@"NewsViewController"];
    // 圖片 欄目
    Column *picColumn = [Column columnNamed:@"圖片" imgName:@"pic.png" className:@"PicViewController"];
    // 圖片 欄目
    Column *commentColumn = [Column columnNamed:@"跟帖" imgName:@"comment.png" className:@"CommentViewController"];
    // 以后要添加欄目,只要改這里就可以了
   
   
    // 將欄目對象,一次性全添加到不可變數組中
    _arr = @[newsColumn,picColumn,commentColumn];
   
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return _arr.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellID = @"leftVC";
    // 下面這個dequeue只能用于storyboard或xib中
    // UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID forIndexPath:indexPath];
    //
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
   
    if (cell == nil) {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
    }
   
    // 設置獨一無二的數據
    Column *column = _arr[indexPath.row];
    cell.textLabel.text = column.columnName;
    cell.imageView.image = [UIImage imageNamed:column.columnImgName];
    return cell;
}

// 點擊一行時,主控制中的主視圖必須展示相應欄目的內容,因此,必須實例化對應點擊的行的欄目控制器,并用添加到導航控制器,調用代理 的方法傳遞數據給代理 使用,此處的代理 其實就是 主控制器
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 先取消默認的點擊 高亮的顏色
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    // 取出對應行的數據模型(欄目)
    Column *column = _arr[indexPath.row];
   
    if ([self.delegate respondsToSelector:@selector(leftTableViewRowClicked:)]) {
       
        // 傳遞數據給主控制器 BeyondViewController,通過代理
        // 關鍵代碼~
        [self.delegate leftTableViewRowClicked:column];
    }
   
   
}
@end

RightViewController.xib


NewsViewController.xib


PicViewController.xib


CommentViewController.xib


【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

這篇文章主要介紹了ios實現文件對比的方法,主要是用到了filemanager,有需要的小伙伴可以參考下。
這篇文章主要給大家匯總了一下ios下移動文件方法,從簡單到復雜,十分的實用,有需要的小伙伴可以參考下。
本文給大家總結了幾則在IOS系統下刪除文件的代碼,十分的實用,有需要的小伙伴可以參考下。
本文給大家分享的是IOS開發中遇到的一個手風琴特效無法正常工作的問題的解決方法,經過度娘了很久才找到解決方法,這里推薦給大家,有需要的小伙伴可以參考下。
這篇文章主要介紹了iOS、Mac OS X系統中編程實現漢字轉拼音的方法(超級簡單),本文講解的方法不僅支持中文,還支持日文、韓文等,需要的朋友可以參考下
這篇文章主要分享了iOS7 毛玻璃特效代碼,非常的實用,做IOS開發的童鞋們不要錯過了
主站蜘蛛池模板: 垃圾压缩设备_垃圾处理设备_智能移动式垃圾压缩设备--山东明莱环保设备有限公司 | 新型锤式破碎机_新型圆锥式_新型颚式破碎机_反击式打沙机_锤式制砂机_青州建源机械 | 除尘器布袋骨架,除尘器滤袋,除尘器骨架,电磁脉冲阀膜片,卸灰阀,螺旋输送机-泊头市天润环保机械设备有限公司 | 依维柯自动挡房车,自行式国产改装房车,小型房车价格,中国十大房车品牌_南京拓锐斯特房车 - 南京拓锐斯特房车 | 山东PE给水管厂家,山东双壁波纹管,山东钢带增强波纹管,山东PE穿线管,山东PE农田灌溉管,山东MPP电力保护套管-山东德诺塑业有限公司 | 水篦子|雨篦子|镀锌格栅雨水篦子|不锈钢排水篦子|地下车库水箅子—安平县云航丝网制品厂 | 粉碎机_塑料粉碎机_塑料破碎机厂家-星标机械 | 泰兴市热钻机械有限公司-热熔钻孔机-数控热熔钻-热熔钻孔攻牙一体机 | 杭州实验室尾气处理_实验台_实验室家具_杭州秋叶实验设备有限公司 | 铝板冲孔网,不锈钢冲孔网,圆孔冲孔网板,鳄鱼嘴-鱼眼防滑板,盾构走道板-江拓数控冲孔网厂-河北江拓丝网有限公司 | 冷藏车厂家|冷藏车价格|小型冷藏车|散装饲料车厂家|程力专用汽车股份有限公司销售十二分公司 | PC构件-PC预制构件-构件设计-建筑预制构件-PC构件厂-锦萧新材料科技(浙江)股份有限公司 | 礼至家居-全屋定制家具_一站式全屋整装_免费量房设计报价 | 网站建设-临朐爱采购-抖音运营-山东兆通网络科技 | 硬度计,金相磨抛机_厂家-莱州华煜众信试验仪器有限公司 | 武汉高温老化房,恒温恒湿试验箱,冷热冲击试验箱-武汉安德信检测设备有限公司 | 航拍_专业的无人机航拍摄影门户社区网站_航拍网 | 电地暖-电采暖-发热膜-石墨烯电热膜品牌加盟-暖季地暖厂家 | 北京银联移动POS机办理_收银POS机_智能pos机_刷卡机_收银系统_个人POS机-谷骐科技【官网】 | 芜湖厨房设备_芜湖商用厨具_芜湖厨具设备-芜湖鑫环厨具有限公司 控显科技 - 工控一体机、工业显示器、工业平板电脑源头厂家 | 杭州中央空调维修_冷却塔/新风机柜/热水器/锅炉除垢清洗_除垢剂_风机盘管_冷凝器清洗-杭州亿诺能源有限公司 | 金库门,金库房,金库门厂家,金库门价格-河北特旺柜业有限公司 | 智慧食堂_食堂管理系统_食堂订餐_食堂消费系统—客易捷 | 信阳网站建设专家-信阳时代网联-【信阳网站建设百度推广优质服务提供商】信阳网站建设|信阳网络公司|信阳网络营销推广 | 淬火设备-钎焊机-熔炼炉-中频炉-锻造炉-感应加热电源-退火机-热处理设备-优造节能 | 长沙一级消防工程公司_智能化弱电_机电安装_亮化工程专业施工承包_湖南公共安全工程有限公司 | 风淋室生产厂家报价_传递窗|送风口|臭氧机|FFU-山东盛之源净化设备 | 上海办公室装修公司_办公室设计_直营办公装修-羚志悦装 | 钢骨架轻型板_膨石轻型板_钢骨架轻型板价格_恒道新材料 | 冰晶石|碱性嫩黄闪蒸干燥机-有机垃圾烘干设备-草酸钙盘式干燥机-常州市宝康干燥 | 依维柯自动挡房车,自行式国产改装房车,小型房车价格,中国十大房车品牌_南京拓锐斯特房车 - 南京拓锐斯特房车 | 书信之家_书信标准模板范文大全| 南京欧陆电气股份有限公司-风力发电机官网 | LHH药品稳定性试验箱-BPS系列恒温恒湿箱-意大利超低温冰箱-上海一恒科学仪器有限公司 | [官网]叛逆孩子管教_戒网瘾学校_全封闭问题青少年素质教育_新起点青少年特训学校 | 洁净实验室工程-成都手术室净化-无尘车间装修-四川华锐净化公司-洁净室专业厂家 | 柔性测斜仪_滑动测斜仪-广州杰芯科技有限公司 | TMT观察网_独特视角观察TMT行业 派财经_聚焦数字经济内容服务平台 | VOC检测仪-甲醛检测仪-气体报警器-气体检测仪厂家-深恒安科技有限公司 | 钢丝绳探伤仪-钢丝绳检测仪-钢丝绳探伤设备-洛阳泰斯特探伤技术有限公司 | 中医中药治疗血小板减少-石家庄血液病肿瘤门诊部|