草庐IT

ios - 像 Facebook 这样的 iOS 侧边栏菜单实现?

coder 2023-07-26 原文

我想像 iOS 6 中的 Facebook iPhone 应用一样创建侧边栏菜单。

如何创建它?

我是这个 iPhone 开发的新手。

请给我一些指示或告诉我一些基本教程,我可以按照步骤一步一步地实现它。

最佳答案

我们可以很容易地自己做。非常简单。

我在这里解释的方法正在我的应用中使用。

目标:

When a button is pressed in title bar a side bar has to slide in and out from left side.

步骤:

1) Create a view controller(home) and two nsObject classes(sidebar,main)

2) add a tool bar on view controller

3) In sidebar (Left side view):

i) Build a uiview(to be added on vc) with desired sidebar width within that add views as needed for your project

ii) then create button and make it as property because it's target events will have to occur in view controller

iii) you have to have two CGRects for both button and the resultant view one CGrect is for expanded state another CGrect is for collapsed

iv) as far as button is cocerned it's x is sidebarwidth-buttonwidth for expanded state and it's x is 0+buttonwidth for collapsed state and as far as view is concerned it's x is 0 for expanded state and it's x is -sidebarwidth for collapsed state

4) In main(right side view):

i) Build a UIView and add it to UiscollView(to be added on vc)

ii) UIView will have two CGREcts for UIscrollView one for expanded and one for collapsed

iii) UIview's x is 0 y is 0 width is 1024 and height is 726(landscape view height-toolbar width on vc)

iv) On Collapsed time uIscrollview's x is sidebarwidth y is 42(vc'tool bar height) and width is 1024-sidebarwidth and height is same as uiview's

v) on expanded time Uiscrollview's x is 0 and width becomes 1024

vi) Uiscrollview content size always should be 1024,726 as we need scrolling if the size is shrunk than this

5) In view controller (home page):

i) add both the side bar and main in home

ii) then add and event for the button in sidebar and then add it on the tool bar usign addsubview method

iii) In the button touch event call toggle events inside

 -(void)OnCollapsibleExtenderTouchUpInside
{
   [UIView animateWithDuration:1.0 animations:^{

    [sideBarObj ToggleVuPosition];

    [mainVuObj ToggleVuSize];

 }];

}

The below code works for me..(I just renamed some field for my own sake)

为了更好地理解下面的代码:

1) The View controller name is Home and side bar name is side bar and right side area name is Main

2) I have wrote the coding for landscape alone...you can customize it for portrait also one use it.

边栏:

#import <Foundation/Foundation.h>

@interface SideBar : NSObject
{
UIView *vuSideBar;

UIScrollView *scrollVuSideBar;

UIImageView *imgProfilePicture;

CGRect rectVuSideBar,rectExpandedScrollVuSideBar,rectCollapsedScrollVuSideBar,rectImgProfilePicture,rectExpandedBtnCollapsibleExtender,rectCollapsedBtnCollapsibleExtender;

 int sideBarWidth,sideBarHeight;
}

@property(strong,nonatomic)UIButton *btnCollapsibleExtender;

-(id)initWithParent:(UIView *)vuParent andToolBar:(UIToolbar *)toolBarParent;

-(void)ToggleVuPosition;

@end

边栏实现:

 #import "SideBar.h"

@interface  SideBar()

-(void)initRects;

-(void)initVus;

-(void)initOtherIvars;

-(void)AddViewsOnHierarchy;

-(void)AddToParentVu:(UIView *)ParentVu;

-(void)OnCollapsibleExtenderTouchUpInside;

@end

@implementation SideBar

@synthesize btnCollapsibleExtender;

-(id)initWithParent:(UIView *)vuParent andToolBar:(UIToolbar  *)toolBarParent
{
 self = [super init]; //calls init because UIResponder has no custom init methods
 if (self)
 {
    [self initOtherIvars];

    [self initRects];

    [self initVus];

    [self AddViewsOnHierarchy];

    [self AddToParentVu:vuParent];

    [self AddToParentToolbar:toolBarParent];

   }
   return self;
 }

 -(void)initOtherIvars
 {
   NSLog(@"initOtherIvars");

   sideBarWidth=300;

   sideBarHeight=768;
 }

 -(void)initRects
 {
  NSLog(@"initRects");

  rectExpandedScrollVuSideBar=CGRectMake(0,42,sideBarWidth,sideBarHeight);

 rectCollapsedScrollVuSideBar=CGRectMake(-sideBarWidth,42,sideBarWidth,sideBarHeight);

rectExpandedBtnCollapsibleExtender=CGRectMake(sideBarWidth-30,6,30,30);

rectCollapsedBtnCollapsibleExtender=CGRectMake(6,6,30,30);

rectVuSideBar=CGRectMake(0,0,sideBarWidth,sideBarHeight);

rectImgProfilePicture=CGRectMake(5,5,sideBarWidth-10,200);
 }

 -(void)initVus
 {
  NSLog(@"initVus");

   scrollVuSideBar=[[UIScrollView  alloc]initWithFrame:rectExpandedScrollVuSideBar];

   [scrollVuSideBar setContentSize:CGSizeMake(sideBarWidth,sideBarHeight)];


   btnCollapsibleExtender=[[UIButton alloc]initWithFrame:rectExpandedBtnCollapsibleExtender];

   UIImage *imgCollapsibleExtender=[UIImage imageNamed:@"SideBarExpandCollapse.png"];

   [btnCollapsibleExtender setImage:imgCollapsibleExtender forState:UIControlStateNormal];


   vuSideBar=[[UIView alloc]initWithFrame:rectVuSideBar];

   [vuSideBar setBackgroundColor:[UIColor darkGrayColor]];


   imgProfilePicture=[[UIImageView alloc]initWithFrame:rectImgProfilePicture];

   UIImage *imgDefaultProfile=[UIImage imageNamed:@"defaultProfileImage.png"];

   [imgProfilePicture setImage:imgDefaultProfile];

  }

 -(void)AddViewsOnHierarchy
{
   NSLog(@"AddViewsOnHierarchy");

   [vuSideBar addSubview:imgProfilePicture];

   [scrollVuSideBar addSubview:vuSideBar];
 }

 -(void)AddToParentVu:(UIView *)ParentVu
 {
   NSLog(@"AddToParent vu");

  [ParentVu addSubview:scrollVuSideBar];
 }

 -(void)AddToParentToolbar:(UIToolbar *)ParentToolBar
 {
  NSLog(@"AddToParent toolbar");

 [ParentToolBar addSubview:btnCollapsibleExtender];
 }

 -(void)ToggleVuPosition
 {
 switch ((int)scrollVuSideBar.frame.origin.x)
 {
     case 0:

        scrollVuSideBar.frame=rectCollapsedScrollVuSideBar;

             btnCollapsibleExtender.frame=rectCollapsedBtnCollapsibleExtender;

        break;

      default:

        scrollVuSideBar.frame=rectExpandedScrollVuSideBar;

          btnCollapsibleExtender.frame=rectExpandedBtnCollapsibleExtender;

        break;
   }
 }

@end

主要(右 View ):

 #import <Foundation/Foundation.h>

 @interface MainView : NSObject
 {
  UIView *vuMain;

  UIScrollView *scrollVuMain;

  CGRect  rectVuMain,rectScrollVuMainExpanded,rectScrollVuMainCollpased;

  int mainWidth,mainHeight,sideBarWidth,HeaderBarHeight;
 }

 -(id)initWithParent:(UIView *)vuParent;

 -(void)ToggleVuSize;
 @end

主要(右侧 View )实现:

#import "MainView.h"

@interface MainView ()

-(void)initRects;

-(void)initVus;

-(void)initOtherIvars;

-(void)AddViewsOnHierarchy;

-(void)AddToParentVu:(UIView *)ParentVu;

@end

@implementation SGGI_MainView

-(id)initWithParent:(UIView *)vuParent
{
  self = [super init]; //calls init because UIResponder has no custom init methods
  if (self)
  {
    [self initOtherIvars];

    [self initRects];

    [self initVus];

    [self AddViewsOnHierarchy];

    [self AddToParentVu:vuParent];
   }
   return self;
 } 

-(void)initRects
{
rectVuMain=CGRectMake(0,0,1024,726);

       rectScrollVuMainExpanded=CGRectMake(0,HeaderBarHeight,mainWidth,mainHeight-HeaderBarHeight);

  rectScrollVuMainCollpased=CGRectMake(sideBarWidth,HeaderBarHeight,mainWidth-sideBarWidth,mainHeight-HeaderBarHeight);
}

-(void)initVus
{
 scrollVuMain=[[UIScrollView alloc]initWithFrame:rectScrollVuMainCollpased];

 [scrollVuMain setContentSize:CGSizeMake(mainWidth,mainHeight-HeaderBarHeight)];

 vuMain=[[UIView alloc]initWithFrame:rectVuMain];

 UILabel *lbl=[[UILabel alloc]initWithFrame:CGRectMake(0,0,1024,30)];

 [lbl setText:@"Details123456789abcdefghijklmnopqrstuvwxyz987654321abcdefghijklmnopqrstuvwxyz123456789abcdefghijklmnopqrstuvwxyz9876"];

 [vuMain addSubview:lbl];


}

-(void)initOtherIvars
{
 NSLog(@"initOtherIvars");

 mainWidth=1024;

 mainHeight=768;

 sideBarWidth=300;

 HeaderBarHeight=42;

}

-(void)AddViewsOnHierarchy
{
 [scrollVuMain addSubview:vuMain];
}

  -(void)AddToParentVu:(UIView *)ParentVu
 {
   [ParentVu addSubview:scrollVuMain];
 }

  -(void)ToggleVuSize
 {

 switch ((int)scrollVuMain.frame.size.width)
 {
    case 1024:

        scrollVuMain.frame=rectScrollVuMainCollpased;

        break;

    default:

        scrollVuMain.frame=rectScrollVuMainExpanded;

        break;
  }
}

@end

Home(嵌入以上两个一个VC):

#import <UIKit/UIKit.h>

@interface Home : UIViewController

@end

家庭实现:

#import "Home.h"

#import "sideBar.h"

#import "Main.h"

@interface Home ()
{
 sideBar *sideBarObj;

 Main *mainVuObj;

 UIToolbar *HeaderBarObj;
 }

 -(void)AddSideBar;

 -(void)AddMainView;

 -(void)AddHeaderBar;

 -(void)AddCollapsibleExtenderEvent;

 -(void)OnCollapsibleExtenderTouchUpInside;

@end

@implementation Home

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
 self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
 if (self) {
    // Custom initialization
 }
  return self;
}

- (void)viewDidLoad
{
 [super viewDidLoad];

 [self.view setBackgroundColor:[UIColor grayColor]];

 [self AddHeaderBar];

 [self AddSideBar];

  [self AddMainView];

 [self AddCollapsibleExtenderEvent];
}

  - (void)didReceiveMemoryWarning
 {
  [super didReceiveMemoryWarning];
  // Dispose of any resources that can be recreated.
 }

-(void)AddHeaderBar
 {
  HeaderBarObj=[[UIToolbar  alloc]initWithFrame:CGRectMake(0,0,1024,42)];

  [self.view addSubview:HeaderBarObj];
 }

-(void)AddSideBar
{
 sideBarObj=[[SideBar alloc]initWithParent:self.view andToolBar:HeaderBarObj];
}

-(void)AddMainView
{
 mainVuObj=[[MainView alloc]initWithParent:self.view];
}

-(void)AddCollapsibleExtenderEvent
{
SEL   selCollapsibleTouch=@selector(OnCollapsibleExtenderTouchUpInside);

 [sideBarObj.btnCollapsibleExtender addTarget:self action:selCollapsibleTouch forControlEvents:UIControlEventTouchUpInside];
}

-(void)OnCollapsibleExtenderTouchUpInside
{
     [UIView animateWithDuration:1.0 animations:^{

    [sideBarObj ToggleVuPosition];

    [mainVuObj ToggleVuSize];

 }];

}

@end

可以通过不使用 main 并在 Home view controller 中添加代码来进一步自定义上述代码,同样可以避免侧边栏的单独类并将其包含在 home viewcontroller 本身中。

就当用户按下侧边栏中的按钮时,对于主视图中的更改,您可以使用协议(protocol)委托(delegate),或者我们可以将侧边栏中的按钮作为属性并在 View Controller 中添加事件。

希望对您有所帮助。

关于ios - 像 Facebook 这样的 iOS 侧边栏菜单实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17019612/

有关ios - 像 Facebook 这样的 iOS 侧边栏菜单实现?的更多相关文章

  1. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  2. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  3. ruby-on-rails - 如何在 Rails Controller Action 上触发 Facebook 像素 - 2

    我有一个ruby​​onrails应用程序。我按照facebook的说明添加了一个像素。但是,要跟踪转化,Facebook要求您将页面置于达到预期结果时出现的转化中。即,如果我想显示客户已注册,我会将您注册后转到的页面作为成功对象进行跟踪。我的问题是,当客户注册时,在我的应用程序中没有登陆页面。该应用程序将用户带回主页。它在主页上显示了一条消息,所以我想看看是否有一种方法可以跟踪来自Controller操作而不是实际页面的转化。我需要计数的Action没有页面,它们是ControllerAction。是否有任何人都知道的关于如何执行此操作的gem、文档或最佳实践?这是进入布局文件的像素

  4. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  5. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  6. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  7. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  8. MIMO-OFDM无线通信技术及MATLAB实现(1)无线信道:传播和衰落 - 2

     MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO

  9. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  10. ruby - Arrays Sets 和 SortedSets 在 Ruby 中是如何实现的 - 2

    通常,数组被实现为内存块,集合被实现为HashMap,有序集合被实现为跳跃列表。在Ruby中也是如此吗?我正在尝试从性能和内存占用方面评估Ruby中不同容器的使用情况 最佳答案 数组是Ruby核心库的一部分。每个Ruby实现都有自己的数组实现。Ruby语言规范只规定了Ruby数组的行为,并没有规定任何特定的实现策略。它甚至没有指定任何会强制或至少建议特定实现策略的性能约束。然而,大多数Rubyist对数组的性能特征有一些期望,这会迫使不符合它们的实现变得默默无闻,因为实际上没有人会使用它:插入、前置或追加以及删除元素的最坏情况步骤复

随机推荐