实现类似Facebook Messenger的全屏滑动效果

9
我已经实现了UIPageviewContoller,支持在屏幕底部显示多个视图控制器。现在我的问题是如何在我的页面视图控制器上支持Facebook样式的平移效果。
我想要实现Facebook消息样式的效果,就像他们在相机中应用的那样,用手指滑动可以使视图全屏。当我们向下滑动同一视图时,它将调整到原始视图的大小。
我附上了一些屏幕截图以便更好地理解。
并且它应该支持集成弹出手势。
我能够获得类似的效果,但是为此我已经将视图添加到主窗口,因此视图可以滑动到全屏状态,但是通过这种方法,我无法实现交互式弹出iOS默认手势,并且这种方法与我的当前pageviewcontoller实现不兼容。
如果视图添加在窗口中,那么如果用户按下返回按钮,窗口元素将不会移动,它将保留在窗口中,因此窗口的方法不好。
是否有其他方法来获得类似的效果? UIViewControllerInteractiveTransitioning是否对此有帮助?
提前致谢。 我知道我会从你们那里得到更好的方法,比将子视图添加到窗口更稳定。

我正在尝试实现类似的功能。你能给我一些建议,关于如何使用PageViewController来实现上述功能吗?谢谢。 - Shirish Kumar
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Parth Patel p1nt0z
2个回答

1

你尝试给子视图A添加滑动手势了吗?

UISwipeGestureRecognizer *swipeUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(didSwipeScreen:)];
swipeUp.direction = UISwipeGestureRecognizerDirectionUp;
[yourSubViewA addGestureRecognizer:swipeUp];

并且它正在处理 -

- (void)didSwipeScreen:(UISwipeGestureRecognizer *)gesture {
switch (gesture.direction) {
    case UISwipeGestureRecognizerDirectionUp: {
        [UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
            [yourSubViewA setFrame:desiredFullScreenFrame];
        } completion:^(BOOL finished) {
        }];
    }
        break;
    default:
        break;
    }
}

要将其恢复为默认位置,您可以添加另一个UISwipeGestureRecognizerDirectionDown滑动手势或者只是一个tap手势。而对于侧边菜单,MFSideMenu 是一个不错的选择。

实际上,我不想要滑动菜单。我已经通过平移手势实现了类似的效果,但我想要一个像子视图在平移时扩展到整个窗口的效果。 - Parth Patel p1nt0z
好的,那么 UISwipeGestureRecognizer 将能够响应 UISwipeGestureRecognizerDirectionUp 事件。 - RoHaN

0
Here, i used same code for my app for video sharing (same as facebook messenger media sharing)  

 Create one Uiview  Name as ViewCamera with one labelHoldText and three buttons
    and download SCRecoder from github

import SCRecoder class here in (.h) file and do same as below

        #import <UIKit/UIKit.h>
        #import "SCRecorder.h"
        #import "SCAudioTools.h"
        #import "SCRecorderFocusView.h"
        #import "SCRecordSessionManager.h"
        #import "SCTouchDetector.h"


        @protocol VideoRecordDelegate <NSObject>

        @optional

        -(void)VideoRecorded:(NSURL *)assetUrl;

        @end

        typedef enum : NSInteger {

            NOTRECORDING = 0,
            RECORDING=1,
            RETAKE,

        } ENUMRecordType;

        @interface ChatScreen : UIViewController<ChatCellDelegate,SCRecorderDelegate,UITableViewDataSource,UITableViewDelegate,,UIGestureRecognizerDelegate>
        {
            IBOutlet UIView *viewbottomForCamera;

            __weak IBOutlet UIButton *btnViewCameraChange;
            __weak IBOutlet UIButton *btnViewFullScree;
            __weak IBOutlet UIButton *btnVideoSend;


            PDColoredProgressView  *progressView;
            NSTimer *timerForVideoSend;
            CGFloat progressValue;
            UILabel *lblHoldtext;
            UILabel *lblCount;
            BOOL isCanceled,isOpen;

            IBOutlet UIView *viewCamera;



            //new

             UIView *previewView;
            CALayer *layerQ;

            SCRecorder *_recorder;
            UIImage *_photo;
            SCRecordSession *_recordSession;
            ENUMRecordType enumRecordType;


        }
        - (IBAction)btnInstantVideoTapped:(id)sender;
        - (IBAction)btnViewCameraTapped:(id)sender;
        - (IBAction)btnViewSendTapped:(id)sender;
        - (IBAction)btnViewFullScreenTapped:(id)sender;

        @property (strong, nonatomic) SCRecorderFocusView *focusView;
        @property (nonatomic) float  progress;
        @property (nonatomic, strong) CAShapeLayer *progressLayer;
        @property (nonatomic,strong) id<VideoRecordDelegate> deleagte;

        @end

            - (void)viewDidLoad {

            [super viewDidLoad];

//lbl hold text for = @"@"Hold send button for video, tap for photo""
            lblHoldtext =[[UILabel alloc]init];
            lblHoldtext.adjustsFontSizeToFitWidth = YES;
            [lblHoldtext setTextAlignment:NSTextAlignmentCenter];

            progressValue = 0;

              // pan for swipable camera view on touch      
            UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
            [panRecognizer setMinimumNumberOfTouches:1];
            [panRecognizer setMaximumNumberOfTouches:1];
            [viewCamera addGestureRecognizer:panRecognizer];

             //for video sharing on hold button       
            UILongPressGestureRecognizer *longGestureForSendImageORVideo = [[UILongPressGestureRecognizer alloc] init];
            [longGestureForSendImageORVideo addTarget:self action:@selector(LongPressForSendVideo:)];
            [longGestureForSendImageORVideo setMinimumPressDuration:1.0];
            [btnVideoSend addGestureRecognizer:longGestureForSendImageORVideo];

            [btnVideoSend.layer setBorderColor:[UIColor whiteColor].CGColor];
            //        UIColor *background = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:@"2Chat"]];
            [lblHoldtext setFrame:CGRectMake(20, 10, SCREENWIDTH-40, 20)];
            [lblHoldtext setText:@"Hold send button for video, tap for photo"];
            [viewCamera setFrame:CGRectMake(0, SCREENHEIGHT, SCREENWIDTH, viewCamera.frame.size.height)];
            [lblHoldtext setTextColor:[UIColor whiteColor]];
            [viewCamera addSubview:lblHoldtext];
            [viewCamera setBackgroundColor:[UIColor grayColor]];

            [self.navigationController.view addSubview:viewCamera];
            progressView = [[PDColoredProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
            progressView.frame =CGRectMake(0,viewCamera.frame.size.height-32, SCREENWIDTH, viewbottomForCamera.frame.size.height);
            [progressView.layer setMasksToBounds:NO];
            [progressView setTrackTintColor:[UIColor clearColor]];
            progressView.progress = 0.0;

            lblCount = [[UILabel alloc]initWithFrame:CGRectMake(40,15, 50, 30)];
            [lblCount setTextColor:[UIColor whiteColor]];
            [progressView addSubview:lblCount];

            //video recording
            _recorder = [SCRecorder recorder];
            _recorder.sessionPreset = AVCaptureSessionPresetMedium;//[SCRecorderTools bestSessionPresetCompatibleWithAllDevices];
            _recorder.maxRecordDuration = CMTimeMake(VIDEODURATIONLIMIT, 1);
            _recorder.delegate = self;
            _recorder.autoSetVideoOrientation = YES;

            self.focusView = [[SCRecorderFocusView alloc] initWithFrame:viewCamera.bounds];
            self.focusView.recorder = _recorder;

            [viewCamera addSubview:self.focusView];

        //    UIView *previewViewDemo = previewView;
            _recorder.previewView = viewCamera;
            [_recorder.videoConfiguration setSizeAsSquare:YES];
            //[_recorder.videoConfiguration setSize:CGSizeMake(SCREENWIDTH/2, SCREENHEIGHT/2)];
            _recorder.initializeRecordSessionLazily = YES;



            [_recorder openSession:^(NSError *sessionError, NSError *audioError, NSError *videoError, NSError *photoError) {

                //NSLog(@"==== Opened session ====");
                //NSLog(@"Session error: %@", sessionError.description);
                //NSLog(@"Audio error : %@", audioError.description);
                //NSLog(@"Video error: %@", videoError.description);
                //NSLog(@"Photo error: %@", photoError.description);
                //NSLog(@"=======================");
                [self prepareCamera];
            }];



        }
        - (void)layoutSubviews {
            // resize your layers based on the view's new bounds
            previewLayer.frame = viewCamera.bounds;
        }

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

        -(void)viewWillAppear:(BOOL)animated
        {
            [super viewWillAppear:YES];    

        }
        -(void)viewWillDisappear:(BOOL)animated
        {
            [super viewWillDisappear:YES];
            [ShareObj setIsChtScreenPresent:NO];
            [self.view endEditing:YES];
            [viewCamera removeFromSuperview];
            [_recorder endRunningSession];

            [[NSNotificationCenter defaultCenter] removeObserver:self];
        }

        -(void)viewDidAppear:(BOOL)animated
        {
            [super viewDidAppear:YES];
            [_recorder startRunningSession];

        }
        - (IBAction)btnInstantVideoTapped:(id)sender {

        [self.view endEditing:YES];
        if (!isOpen) {

            isOpen = YES;
            [UIView animateWithDuration:0.5 animations:^{


                [_recorder.previewView setFrame:CGRectMake(0, SCREENHEIGHT-258,SCREENWIDTH,258)];
                _recorder.previewLayer.frame = _recorder.previewView.bounds;
                layerQ.frame = _recorder.previewView.bounds;
                [chatBottomView setFrame:CGRectMake(0,_recorder.previewView.frame.origin.y-chatBottomView.frame.size.height*2-12, SCREENWIDTH, chatBottomView.frame.size.height)];
                NSLog(@"hide frame = %@",NSStringFromCGRect(chatBottomView.frame));
                demoFrame=chatBottomView.frame;

                UISwipeGestureRecognizer *panView=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handlePan:)];
                [_recorder.previewView addGestureRecognizer:panView];
                [_recorder.previewView bringSubviewToFront:viewbottomForCamera];
                [viewbottomForCamera bringSubviewToFront:btnViewFullScree];
                [viewbottomForCamera bringSubviewToFront:btnViewCameraChange];
                [self.navigationController.view addSubview:viewCamera];


            }completion:^(BOOL finished) {


            }];

        }
        else
        {
            isOpen = NO;

            [UIView animateWithDuration:0.5 animations:^{
                CGRect frame = chatBottomView.frame;
                frame.origin.y = SCREENHEIGHT-frame.size.height-NAVBARHEIGHT;
                [chatBottomView setFrame:frame];
                [_recorder.previewView setFrame:CGRectMake(0, SCREENHEIGHT, SCREENWIDTH, viewCamera.frame.size.height)];
                [tblChatMessage setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
                [tblChatMessage setScrollIndicatorInsets:UIEdgeInsetsMake(0, 0, 0, 0)];


                NSLog(@" hide frame = %@",NSStringFromCGRect(frame));
            } completion:^(BOOL finished) {
                [viewCamera removeFromSuperview];
            }];
        }
    }

        #pragma mark Gesture Event is called here..
    -(void)LongPressForSendVideo: (UILongPressGestureRecognizer*)recognizer
    {

       CGPoint pointOfTouch = [recognizer locationInView:viewbottomForCamera];

        if (recognizer.state == UIGestureRecognizerStateEnded) {

            [progressView setProgress:0.0 animated:YES];
            progressValue=0.0;
            [progressView removeFromSuperview];
            [timerForVideoSend invalidate];
            timerForVideoSend =nil;
            [layerQ removeFromSuperlayer];
            [btnViewCameraChange.layer setOpacity:1];
            [btnViewFullScree.layer setOpacity:1];

            [lblHoldtext setText:@"Hold send button for video, tap for photo"];

        }
        else if (recognizer.state==UIGestureRecognizerStateChanged)
        {
            if ( CGRectContainsPoint(btnVideoSend.frame, pointOfTouch ) ) {
                // inside
                [lblHoldtext setText:@"To cancel, drag your finger off send button"];

                NSLog(@"inside");
                [progressView setTintColor: [UIColor colorWithRed: 43.0/255.0 green: 134.0/255.0 blue: 225.0/255.0 alpha: 1]];
                [layerQ setBackgroundColor:[UIColor clearColor].CGColor];

            } else {
                // outside
                NSLog(@"outside");
                [lblHoldtext setText:@"Let go to delete and start over"];

                [progressView setTintColor:[UIColor redColor]];
                [layerQ setBackgroundColor:[UIColor colorWithRed:255.0/255.0 green:0/255.0 blue:0/255.0 alpha:0.2].CGColor];



            }

        }
        else if (recognizer.state==UIGestureRecognizerStateBegan)
        {
            layerQ = [[CALayer alloc]init];
            [layerQ setFrame:_recorder.previewLayer.frame];
            [viewCamera.layer addSublayer:layerQ];
            [btnViewCameraChange.layer setOpacity:0.3];
            [btnViewFullScree.layer setOpacity:0.3];
            [lblHoldtext setText:@"To cancel, drag your finger off send button"];

            [progressView setProgress:0.0 animated:YES];
            progressValue=0.0;
            if (timerForVideoSend == nil) {
                timerForVideoSend = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(progressChange) userInfo:nil repeats:YES];
            }
            [progressView setTintColor: [UIColor colorWithRed: 43.0/255.0 green: 134.0/255.0 blue: 225.0/255.0 alpha: 1]];
            [viewCamera addSubview:progressView];
            [viewCamera bringSubviewToFront:viewbottomForCamera];

        }

    }
    -(void)progressChange
    {
        progressValue = progressValue + 0.0065;
        [viewCamera bringSubviewToFront:lblCount];
        [lblCount setText:[NSString stringWithFormat:@"%.1f",progressValue]];
        [progressView setProgress:progressValue animated:YES];
    }
    - (void)handlePan:(UIPanGestureRecognizer*)recognizer
    {
        CGPoint vel = [recognizer velocityInView:viewCamera];
        CGFloat velocityFrame = (vel.y/70);

        if (vel.y > 0)
        {
            // user dragged towards the right
            NSLog(@" down");


                velocityFrame = velocityFrame;


            NSLog(@"velocity%f",velocityFrame);

            if (_recorder.previewView.frame.size.height >= 256) {

                    _recorder.previewView.frame=CGRectMake(0, _recorder.previewView.frame.origin.y+velocityFrame, SCREENWIDTH, _recorder.previewView.frame.size.height-velocityFrame);
                    [viewbottomForCamera setBackgroundColor:COLOR_WITH_RGBA(0, 0, 0, 0)];
                    CGFloat alphacolor = _recorder.previewView.frame.size.height/2000;
                    [viewbottomForCamera setFrame:CGRectMake(0, _recorder.previewView.frame.size.height-65, SCREENWIDTH, 65)];
                    [viewbottomForCamera setBackgroundColor:COLOR_WITH_RGBA(37, 37, 38, alphacolor)];
                    [lblHoldtext setFrame:CGRectMake(0, 0, 0, 0)];
                    [progressView.layer setFrame:viewbottomForCamera.frame];
            }

        }
        else
        {

            velocityFrame = -(velocityFrame);
            velocityFrame = velocityFrame;

            NSLog(@"velocity%f",velocityFrame);
            NSLog(@"up");
            if (_recorder.previewView.frame.origin.y >5) {


                [UIView animateWithDuration:0.2 animations:^{


                    _recorder.previewView.frame=CGRectMake(0, _recorder.previewView.frame.origin.y-velocityFrame, SCREENWIDTH, _recorder.previewView.frame.size.height+velocityFrame);
                    _recorder.previewLayer.frame = self.navigationController.view.bounds;
                    [viewbottomForCamera setFrame:CGRectMake(0,_recorder.previewView.frame.size.height-65, SCREENWIDTH, 65)];
                    CGFloat alphacolor = viewCamera.frame.size.height/1000;
                    [lblHoldtext setFrame:CGRectMake(0, 0, 0, 0)];
                    [progressView.layer setFrame:viewbottomForCamera.frame];


                    if (alphacolor <= 0.6) {
                        [viewbottomForCamera setBackgroundColor:COLOR_WITH_RGBA(37, 37, 38, alphacolor)];
                    }
                    [lblHoldtext setFrame:CGRectMake(0, 0, 0, 0)];

                } completion:^(BOOL finished) {

                }];
            }

        }

        if(recognizer.state == UIGestureRecognizerStateEnded)
        {
            if (vel.y < 0) {

                [UIView animateWithDuration:0.2 animations:^{

                    _recorder.previewView.frame=CGRectMake(0, 0, SCREENWIDTH, SCREENHEIGHT);
                    [viewbottomForCamera setFrame:CGRectMake(0, _recorder.previewView.frame.size.height-65, SCREENWIDTH, 65)];
                    CGFloat alphacolor = _recorder.previewView.frame.size.height/1000;
                    if (alphacolor <= 0.6) {
                        [viewbottomForCamera setBackgroundColor:COLOR_WITH_RGBA(37, 37, 38, alphacolor)];

                    }
                    [progressView.layer setFrame:viewbottomForCamera.frame];



                } completion:^(BOOL finished) {
                    _recorder.previewLayer.frame = _recorder.previewView.bounds;

                    [lblHoldtext setFrame:CGRectMake(20, viewbottomForCamera.frame.origin.y-30, SCREENWIDTH-40, 20)];

                }];


            }
            else
            {

                [UIView animateWithDuration:0.1 animations:^{
                    [_recorder.previewView setFrame:CGRectMake(0, SCREENHEIGHT-258,SCREENWIDTH,258)];
                    [viewbottomForCamera setFrame:CGRectMake(0, _recorder.previewView.frame.size.height-65, SCREENWIDTH, 65)];
                    [viewbottomForCamera setBackgroundColor:COLOR_WITH_RGBA(0, 0, 0, 0)];
                    [progressView.layer setFrame:viewbottomForCamera.frame];




                }completion:^(BOOL finished) {
                    _recorder.previewLayer.frame = _recorder.previewView.bounds;

                    [lblHoldtext setFrame:CGRectMake(20, 10, SCREENWIDTH-40, 20)];

                }];
            }
        }
    }
    -(IBAction)btnViewCameraTapped:(id)sender
    {

    }
    //take image
    - (IBAction)btnViewSendTapped:(id)sender {

    //    AVCaptureConnection *videoConnection = nil;
    //    
    //    for (AVCaptureConnection *connection in stillImageOutput.connections) {
    //        
    //        for (AVCaptureInputPort *ports in [connection inputPorts]) {
    //            
    //            if ([[ports mediaType] isEqual:AVMediaTypeVideo]) {
    //                videoConnection = connection;
    //                break;
    //            }
    //        }
    //        if (videoConnection) {
    //            break;
    //        }
    //    }
    //    
    //    [stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
    //       
    //        if (imageDataSampleBuffer !=nil) {
    //            
    //            NSData *imagedata = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
    //            UIImage *image =[UIImage imageWithData:imagedata];
    //        }
    //    }];
    }
    //open/Close view
    - (IBAction)btnViewFullScreenTapped:(id)sender {

        [lblHoldtext setFrame:CGRectMake(0, 0, 0, 0)];
    //    [lblHoldtext setText:@"To cancel, drag your finger off send button"];
    //    [lblHoldtext setText:@"Let go to delete and start over"];

        if (_recorder.previewView.frame.size.height >= SCREENHEIGHT/2+100) {

            [UIView animateWithDuration:0.5 animations:^{

                [viewCamera setFrame:CGRectMake(0, SCREENHEIGHT-256,SCREENWIDTH,258)];
                [lblHoldtext setFrame:CGRectMake(20, 10, SCREENWIDTH-40, 20)];
                [viewbottomForCamera setFrame:CGRectMake(0, _recorder.previewView.frame.size.height-65, SCREENWIDTH, 65)];
                [viewbottomForCamera setBackgroundColor:COLOR_WITH_RGBA(0, 0,0,0)];
                [progressView.layer setFrame:viewbottomForCamera.frame];


            }completion:^(BOOL finished) {
                _recorder.previewLayer.frame = viewCamera.bounds;

            }];
        }
        else
        {
            [UIView animateWithDuration:0.5 animations:^{
                viewCamera.frame=CGRectMake(0, 0, SCREENWIDTH, SCREENHEIGHT);
                _recorder.previewLayer.frame = viewCamera.bounds;
                [viewbottomForCamera setFrame:CGRectMake(0, _recorder.previewView.frame.size.height-65, SCREENWIDTH, 65)];
                CGFloat alphacolor = _recorder.previewView.frame.size.height/1000;
                [progressView.layer setFrame:viewbottomForCamera.frame];

                if (alphacolor <= 0.7) {
                    [viewbottomForCamera setBackgroundColor:COLOR_WITH_RGBA(37, 37, 38, alphacolor)];

                }


            } completion:^(BOOL finished) {

                [lblHoldtext setFrame:CGRectMake(20, viewbottomForCamera.frame.origin.y-30, SCREENWIDTH-40, 20)];

            }];

        }
    }

嘿 Mega,我认为这实际上是答案,但他应该在代码中提供描述或注释..... - Mubin Mall
@MegaTron 嘿,这是我的答案。如果需要更多描述,请查看我代码中的注释(//)。它对我来说完美地工作,并且与 Facebook Messenger 的工作方式相同 :) - Jatin Dave

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接