首页 \ 问答 \ Horizontal RecycleView不显示其完整内容(Horizontal RecycleView doesn't display its full content)

Horizontal RecycleView不显示其完整内容(Horizontal RecycleView doesn't display its full content)

我有一个ListView,在里面我想要水平的RecyclerView与自定义项目。 问题是不会显示每个图像下的TextView。

在此处输入图像描述

使用RecyclerView的主ListView项

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView android:id="@+id/category_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="start"
        android:textSize="20sp"
        android:layout_marginRight="10dp"/>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/horizontal_recycler_view"
        android:scrollbars="vertical"
        android:layout_width="match_parent"
        android:layout_height="110dp" />
</LinearLayout>

RecyclerView的单项

<LinearLayout
    android:layout_width="100dp"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    xmlns:android="http://schemas.android.com/apk/res/android" >

    <ImageView android:id="@+id/horizontal_list_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" />

    <TextView android:id="@+id/horizontal_list_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="FFFFFFFF"
        android:textSize="15sp"/>
</LinearLayout>

I have a ListView and inside it I want horizontal RecyclerView with custom items. Problem is that somehow TextView under each image isn't displayed.

enter image description here

Main ListView item with RecyclerView

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView android:id="@+id/category_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="start"
        android:textSize="20sp"
        android:layout_marginRight="10dp"/>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/horizontal_recycler_view"
        android:scrollbars="vertical"
        android:layout_width="match_parent"
        android:layout_height="110dp" />
</LinearLayout>

Single item of RecyclerView

<LinearLayout
    android:layout_width="100dp"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    xmlns:android="http://schemas.android.com/apk/res/android" >

    <ImageView android:id="@+id/horizontal_list_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" />

    <TextView android:id="@+id/horizontal_list_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="FFFFFFFF"
        android:textSize="15sp"/>
</LinearLayout>

原文:https://stackoverflow.com/questions/30942341
更新时间:2023-06-05 13:06

最满意答案

我解决了这个问题。 从示例中获取一些类并更改它:

CPSlidingAnimationController:

#import "CPSlidingAnimationController.h"
#import "ECSlidingAnimationController.h"
#import "ECSlidingConstants.h"

@interface CPSlidingAnimationController ()
@property (nonatomic, copy) void (^coordinatorAnimations)(id<UIViewControllerTransitionCoordinatorContext>context);
@property (nonatomic, copy) void (^coordinatorCompletion)(id<UIViewControllerTransitionCoordinatorContext>context);
@end

@implementation CPSlidingAnimationController
@synthesize transition, animationFinishCallback;

#pragma mark - UIViewControllerAnimatedTransitioning

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
     return 0.25;
}

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
    UIViewController *topViewController = [transitionContext viewControllerForKey:ECTransitionContextTopViewControllerKey];
    UIViewController *toViewController  = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIView *containerView = [transitionContext containerView];
    CGRect topViewInitialFrame = [transitionContext initialFrameForViewController:topViewController];
    CGRect topViewFinalFrame   = [transitionContext finalFrameForViewController:topViewController];

    topViewController.view.frame = topViewInitialFrame;

    if (topViewController != toViewController) {
        CGRect toViewFinalFrame = [transitionContext finalFrameForViewController:toViewController];
        toViewController.view.frame = toViewFinalFrame;
        [containerView insertSubview:toViewController.view belowSubview:topViewController.view];
    }

    NSTimeInterval duration = [self transitionDuration:transitionContext];
    [UIView animateWithDuration:duration
                     animations:^{
                         [UIView setAnimationCurve:UIViewAnimationCurveLinear];
                         if (self.coordinatorAnimations) self.coordinatorAnimations((id<UIViewControllerTransitionCoordinatorContext>)transitionContext);
                         topViewController.view.frame = topViewFinalFrame;
                     } completion:^(BOOL finished) {
                         if ([transitionContext transitionWasCancelled]) {
                             topViewController.view.frame = [transitionContext initialFrameForViewController:topViewController];
                         }

                         if (self.coordinatorCompletion) self.coordinatorCompletion((id<UIViewControllerTransitionCoordinatorContext>)transitionContext);
                         [transitionContext completeTransition:finished];

                         if (transition) {
                             if ([(NSObject*) transition respondsToSelector:animationFinishCallback]) {
                                 [transition performSelector:animationFinishCallback];
                             }
                         }
                     }];
}

@end

MEDynamicTransition.h:

#import "MEDynamicTransition.h"
#import "CPSlidingAnimationController.h"

@interface MEDynamicTransition () {
    UIVisualEffectView * effectView;
}

@property (nonatomic, strong) CPSlidingAnimationController * defaultAnimationController;
@property (nonatomic, strong) NSMutableArray *leftEdgeQueue;
@property (nonatomic, assign) id<UIViewControllerContextTransitioning> transitionContext;
@property (nonatomic, strong) UIDynamicAnimator *animator;
@property (nonatomic, strong) UICollisionBehavior *collisionBehavior;
@property (nonatomic, strong) UIGravityBehavior *gravityBehavior;
@property (nonatomic, strong) UIPushBehavior *pushBehavior;
@property (nonatomic, strong) UIDynamicItemBehavior *topViewBehavior;
@property (nonatomic, strong) UIDynamicBehavior *compositeBehavior;
@property (nonatomic, assign) BOOL positiveLeftToRight;
@property (nonatomic, assign) BOOL isPanningRight;
@property (nonatomic, assign) BOOL isInteractive;
@property (nonatomic, assign) CGFloat fullWidth;
@property (nonatomic, assign) CGRect initialTopViewFrame;
@end

@implementation MEDynamicTransition

#pragma mark - ECSlidingViewControllerDelegate

- (id<UIViewControllerAnimatedTransitioning>)slidingViewController:(ECSlidingViewController *)slidingViewController
                                   animationControllerForOperation:(ECSlidingViewControllerOperation)operation
                                                 topViewController:(UIViewController *)topViewController {

    return self.defaultAnimationController;
}

- (id<UIViewControllerInteractiveTransitioning>)slidingViewController:(ECSlidingViewController *)slidingViewController
                          interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>)animationController {
    self.slidingViewController = slidingViewController;
    return self;
}

#pragma mark - Properties

- (CPSlidingAnimationController *)defaultAnimationController {
    if (_defaultAnimationController) return _defaultAnimationController;

    _defaultAnimationController = [[CPSlidingAnimationController alloc] init];
    _defaultAnimationController.transition = self;
    _defaultAnimationController.animationFinishCallback = @selector(blurControl);

    return _defaultAnimationController;
}

- (NSMutableArray *)leftEdgeQueue {
    if (_leftEdgeQueue) return _leftEdgeQueue;

    _leftEdgeQueue = [NSMutableArray arrayWithCapacity:5];

    return _leftEdgeQueue;
}

- (UIDynamicAnimator *)animator {
    if (_animator) return _animator;

    _animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.slidingViewController.view];
    _animator.delegate = self;
    [_animator updateItemUsingCurrentState:self.slidingViewController.topViewController.view];

    return _animator;
}

- (UICollisionBehavior *)collisionBehavior {
    if (_collisionBehavior) return _collisionBehavior;

    _collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[self.slidingViewController.topViewController.view]];

    CGFloat containerHeight = self.slidingViewController.view.bounds.size.height;
    CGFloat containerWidth  = self.slidingViewController.view.bounds.size.width;
    CGFloat revealAmount    = self.slidingViewController.anchorRightRevealAmount;

    [_collisionBehavior addBoundaryWithIdentifier:@"LeftEdge" fromPoint:CGPointMake(-1, 0) toPoint:CGPointMake(-1, containerHeight)];
    [_collisionBehavior addBoundaryWithIdentifier:@"RightEdge" fromPoint:CGPointMake(revealAmount + containerWidth + 1, 0) toPoint:CGPointMake(revealAmount + containerWidth + 1, containerHeight)];

    return _collisionBehavior;
}

- (UIGravityBehavior *)gravityBehavior {
    if (_gravityBehavior) return _gravityBehavior;

    _gravityBehavior = [[UIGravityBehavior alloc] initWithItems:@[self.slidingViewController.topViewController.view]];

    return _gravityBehavior;
}

- (UIPushBehavior *)pushBehavior {
    if (_pushBehavior) return _pushBehavior;

    _pushBehavior = [[UIPushBehavior alloc] initWithItems:@[self.slidingViewController.topViewController.view] mode:UIPushBehaviorModeInstantaneous];

    return _pushBehavior;
}

- (UIDynamicItemBehavior *)topViewBehavior {
    if (_topViewBehavior) return _topViewBehavior;

    UIView *topView = self.slidingViewController.topViewController.view;
    _topViewBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[topView]];
    // the density ranges from 1 to 5 for iPad to iPhone
    _topViewBehavior.density = 908800 / (topView.bounds.size.width * topView.bounds.size.height);
    _topViewBehavior.elasticity = 0;
    _topViewBehavior.resistance = 1;

    return _topViewBehavior;
}

- (UIDynamicBehavior *)compositeBehavior {
    if (_compositeBehavior) return _compositeBehavior;

    _compositeBehavior = [[UIDynamicBehavior alloc] init];
    [_compositeBehavior addChildBehavior:self.collisionBehavior];
    [_compositeBehavior addChildBehavior:self.gravityBehavior];
    [_compositeBehavior addChildBehavior:self.pushBehavior];
    [_compositeBehavior addChildBehavior:self.topViewBehavior];
    __weak typeof(self)weakSelf = self;
    _compositeBehavior.action = ^{
        // stop the dynamic animation when the value of the left edge is the same 5 times in a row.
        NSNumber *leftEdge = [NSNumber numberWithFloat:weakSelf.slidingViewController.topViewController.view.frame.origin.x];
        [weakSelf.leftEdgeQueue insertObject:leftEdge atIndex:0];
        if (weakSelf.leftEdgeQueue.count == 6) [weakSelf.leftEdgeQueue removeLastObject];

        if (weakSelf.leftEdgeQueue.count == 5 &&
            ((NSArray *)[weakSelf.leftEdgeQueue valueForKeyPath:@"@distinctUnionOfObjects.self"]).count == 1) {
            [weakSelf.animator removeAllBehaviors];
        }
    };

    return _compositeBehavior;
}

#pragma mark - UIViewControllerInteractiveTransitioning

- (void)startInteractiveTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
    self.transitionContext = transitionContext;

    UIViewController *topViewController = [transitionContext viewControllerForKey:ECTransitionContextTopViewControllerKey];
    topViewController.view.userInteractionEnabled = NO;

    if (_isInteractive) {
        UIViewController *underViewController = [transitionContext viewControllerForKey:ECTransitionContextUnderLeftControllerKey];
        CGRect underViewInitialFrame = [transitionContext initialFrameForViewController:underViewController];
        CGRect underViewFinalFrame   = [transitionContext finalFrameForViewController:underViewController];
        UIView *containerView = [transitionContext containerView];
        CGFloat finalLeftEdge = CGRectGetMinX([transitionContext finalFrameForViewController:topViewController]);
        CGFloat initialLeftEdge = CGRectGetMinX([transitionContext initialFrameForViewController:topViewController]);
        CGFloat fullWidth = fabs(finalLeftEdge - initialLeftEdge);

        CGRect underViewFrame;
        if (CGRectIsEmpty(underViewInitialFrame)) {
            underViewFrame = underViewFinalFrame;
        } else {
            underViewFrame = underViewInitialFrame;
        }

        underViewController.view.frame = underViewFrame;

        [containerView insertSubview:underViewController.view belowSubview:topViewController.view];

        self.positiveLeftToRight = initialLeftEdge < finalLeftEdge;
        self.fullWidth           = fullWidth;
    } else {
        [self.defaultAnimationController animateTransition:transitionContext];
    }
}

#pragma mark - UIPanGestureRecognizer action

- (void)handlePanGesture:(UIPanGestureRecognizer *)recognizer {
    if ([self.animator isRunning]) return;

    UIView *topView       = self.slidingViewController.topViewController.view;
    CGFloat translationX  = [recognizer translationInView:self.slidingViewController.view].x;
    CGFloat velocityX     = [recognizer velocityInView:self.slidingViewController.view].x;

    // Blur effect
    [self blurControl];

    switch (recognizer.state) {
        case UIGestureRecognizerStateBegan: {
            BOOL isMovingRight = velocityX > 0;

            CALayer *presentationLayer = (CALayer *)topView.layer.presentationLayer;
            self.initialTopViewFrame = presentationLayer.frame;

            _isInteractive = YES;

            if (self.slidingViewController.currentTopViewPosition == ECSlidingViewControllerTopViewPositionCentered && isMovingRight && self.slidingViewController.underLeftViewController) {
                [self.slidingViewController anchorTopViewToRightAnimated:YES];
            } else if (self.slidingViewController.currentTopViewPosition == ECSlidingViewControllerTopViewPositionCentered && !isMovingRight && self.slidingViewController.underRightViewController) {
                [self.slidingViewController anchorTopViewToLeftAnimated:YES];
            } else if (self.slidingViewController.currentTopViewPosition == ECSlidingViewControllerTopViewPositionAnchoredLeft) {
                [self.slidingViewController resetTopViewAnimated:YES];
            } else if (self.slidingViewController.currentTopViewPosition == ECSlidingViewControllerTopViewPositionAnchoredRight) {
                [self.slidingViewController resetTopViewAnimated:YES];
            } else {
                _isInteractive = NO;
            }

            break;
        }
        case UIGestureRecognizerStateChanged: {
            if (!_isInteractive) return;

            CGRect topViewInitialFrame = self.initialTopViewFrame;
            CGFloat newLeftEdge = topViewInitialFrame.origin.x + translationX;

            if (newLeftEdge < 0) {
                newLeftEdge = 0;
            } else if (newLeftEdge > self.slidingViewController.anchorRightRevealAmount) {
                newLeftEdge = self.slidingViewController.anchorRightRevealAmount;
            }

            topViewInitialFrame.origin.x = newLeftEdge;
            topView.frame = topViewInitialFrame;

            if (!self.positiveLeftToRight) translationX = translationX * -1.0;
            CGFloat percentComplete = (translationX / self.fullWidth);
            if (percentComplete < 0) percentComplete = 0;
            if (percentComplete > 100) percentComplete = 100;
            [self.transitionContext updateInteractiveTransition:percentComplete];
            break;
        }
        case UIGestureRecognizerStateEnded:
        {
            [self blurControl];
        };
        case UIGestureRecognizerStateCancelled: {
            if (!_isInteractive) return;

            _isInteractive = NO;

            self.isPanningRight = velocityX > 0;

            if (self.isPanningRight) {
                [self blurControl];
            } else {
                [self disableBlur];
            }

            self.gravityBehavior.gravityDirection = self.isPanningRight ? CGVectorMake(2, 0) : CGVectorMake(-2, 0);

            self.pushBehavior.angle = 0; // velocity may be negative
            self.pushBehavior.magnitude = velocityX;
            self.pushBehavior.active = YES;

            [self.animator addBehavior:self.compositeBehavior];

            break;
        }
        default:
            break;
    }
}

#pragma mark - UIDynamicAnimatorDelegate

- (void)dynamicAnimatorDidPause:(UIDynamicAnimator*)animator {
    [self.animator removeAllBehaviors];

    _collisionBehavior = nil;
    _topViewBehavior = nil;
    _pushBehavior = nil;
    _gravityBehavior = nil;
    _compositeBehavior = nil;
    _animator = nil;

    self.slidingViewController.topViewController.view.userInteractionEnabled = YES;
    UIViewController *topViewController = [self.transitionContext viewControllerForKey:ECTransitionContextTopViewControllerKey];
    if ((self.isPanningRight && self.positiveLeftToRight) || (!self.isPanningRight && !self.positiveLeftToRight)) {
        topViewController.view.frame = [self.transitionContext finalFrameForViewController:topViewController];
        [self.transitionContext finishInteractiveTransition];
    } else if ((self.isPanningRight && !self.positiveLeftToRight) || (!self.isPanningRight && self.positiveLeftToRight)) {
        topViewController.view.frame = [self.transitionContext initialFrameForViewController:topViewController];
        [self.transitionContext cancelInteractiveTransition];
    }

    [self.transitionContext completeTransition:YES];
}

#pragma mark - Blur

- (void) setBlurOffset:(CGFloat) offset {
    UIView *topView = self.slidingViewController.topViewController.view;

    if (!effectView) {
        UIBlurEffect * blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
        effectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
        effectView.frame = topView.bounds;
        effectView.alpha = 0.1f;
        [topView addSubview:effectView];

        [effectView setTranslatesAutoresizingMaskIntoConstraints:false];
        [topView addConstraint:[NSLayoutConstraint constraintWithItem:effectView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:topView attribute:NSLayoutAttributeTop multiplier:1 constant:0]];
        [topView addConstraint:[NSLayoutConstraint constraintWithItem:effectView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:topView attribute:NSLayoutAttributeBottom multiplier:1 constant:0]];
        [topView addConstraint:[NSLayoutConstraint constraintWithItem:effectView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:topView attribute:NSLayoutAttributeLeading multiplier:1 constant:0]];
        [topView addConstraint:[NSLayoutConstraint constraintWithItem:effectView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:topView attribute:NSLayoutAttributeTrailing multiplier:1 constant:0]];
    }

    CGFloat c = offset / 100;
    if (c < 0.1f) c = 0.1f; else if (c > 0.5f) c = 0.5f;
    effectView.alpha = c;
}

- (void) disableBlur{
    if (effectView != NULL) {
        [effectView removeFromSuperview];
        effectView = NULL;
    }
}

- (void) blurControl{
    UIView *topView = self.slidingViewController.topViewController.view;
    NSLog(@"X: %f", topView.frame.origin.x);

    if (topView.frame.origin.x >= 15) {
        [self setBlurOffset:topView.frame.origin.x];
    } else {
        [self disableBlur];
    }

}
@end

I solved this issue. Just get some classes from example and changed it:

CPSlidingAnimationController:

#import "CPSlidingAnimationController.h"
#import "ECSlidingAnimationController.h"
#import "ECSlidingConstants.h"

@interface CPSlidingAnimationController ()
@property (nonatomic, copy) void (^coordinatorAnimations)(id<UIViewControllerTransitionCoordinatorContext>context);
@property (nonatomic, copy) void (^coordinatorCompletion)(id<UIViewControllerTransitionCoordinatorContext>context);
@end

@implementation CPSlidingAnimationController
@synthesize transition, animationFinishCallback;

#pragma mark - UIViewControllerAnimatedTransitioning

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
     return 0.25;
}

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
    UIViewController *topViewController = [transitionContext viewControllerForKey:ECTransitionContextTopViewControllerKey];
    UIViewController *toViewController  = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIView *containerView = [transitionContext containerView];
    CGRect topViewInitialFrame = [transitionContext initialFrameForViewController:topViewController];
    CGRect topViewFinalFrame   = [transitionContext finalFrameForViewController:topViewController];

    topViewController.view.frame = topViewInitialFrame;

    if (topViewController != toViewController) {
        CGRect toViewFinalFrame = [transitionContext finalFrameForViewController:toViewController];
        toViewController.view.frame = toViewFinalFrame;
        [containerView insertSubview:toViewController.view belowSubview:topViewController.view];
    }

    NSTimeInterval duration = [self transitionDuration:transitionContext];
    [UIView animateWithDuration:duration
                     animations:^{
                         [UIView setAnimationCurve:UIViewAnimationCurveLinear];
                         if (self.coordinatorAnimations) self.coordinatorAnimations((id<UIViewControllerTransitionCoordinatorContext>)transitionContext);
                         topViewController.view.frame = topViewFinalFrame;
                     } completion:^(BOOL finished) {
                         if ([transitionContext transitionWasCancelled]) {
                             topViewController.view.frame = [transitionContext initialFrameForViewController:topViewController];
                         }

                         if (self.coordinatorCompletion) self.coordinatorCompletion((id<UIViewControllerTransitionCoordinatorContext>)transitionContext);
                         [transitionContext completeTransition:finished];

                         if (transition) {
                             if ([(NSObject*) transition respondsToSelector:animationFinishCallback]) {
                                 [transition performSelector:animationFinishCallback];
                             }
                         }
                     }];
}

@end

MEDynamicTransition.h:

#import "MEDynamicTransition.h"
#import "CPSlidingAnimationController.h"

@interface MEDynamicTransition () {
    UIVisualEffectView * effectView;
}

@property (nonatomic, strong) CPSlidingAnimationController * defaultAnimationController;
@property (nonatomic, strong) NSMutableArray *leftEdgeQueue;
@property (nonatomic, assign) id<UIViewControllerContextTransitioning> transitionContext;
@property (nonatomic, strong) UIDynamicAnimator *animator;
@property (nonatomic, strong) UICollisionBehavior *collisionBehavior;
@property (nonatomic, strong) UIGravityBehavior *gravityBehavior;
@property (nonatomic, strong) UIPushBehavior *pushBehavior;
@property (nonatomic, strong) UIDynamicItemBehavior *topViewBehavior;
@property (nonatomic, strong) UIDynamicBehavior *compositeBehavior;
@property (nonatomic, assign) BOOL positiveLeftToRight;
@property (nonatomic, assign) BOOL isPanningRight;
@property (nonatomic, assign) BOOL isInteractive;
@property (nonatomic, assign) CGFloat fullWidth;
@property (nonatomic, assign) CGRect initialTopViewFrame;
@end

@implementation MEDynamicTransition

#pragma mark - ECSlidingViewControllerDelegate

- (id<UIViewControllerAnimatedTransitioning>)slidingViewController:(ECSlidingViewController *)slidingViewController
                                   animationControllerForOperation:(ECSlidingViewControllerOperation)operation
                                                 topViewController:(UIViewController *)topViewController {

    return self.defaultAnimationController;
}

- (id<UIViewControllerInteractiveTransitioning>)slidingViewController:(ECSlidingViewController *)slidingViewController
                          interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>)animationController {
    self.slidingViewController = slidingViewController;
    return self;
}

#pragma mark - Properties

- (CPSlidingAnimationController *)defaultAnimationController {
    if (_defaultAnimationController) return _defaultAnimationController;

    _defaultAnimationController = [[CPSlidingAnimationController alloc] init];
    _defaultAnimationController.transition = self;
    _defaultAnimationController.animationFinishCallback = @selector(blurControl);

    return _defaultAnimationController;
}

- (NSMutableArray *)leftEdgeQueue {
    if (_leftEdgeQueue) return _leftEdgeQueue;

    _leftEdgeQueue = [NSMutableArray arrayWithCapacity:5];

    return _leftEdgeQueue;
}

- (UIDynamicAnimator *)animator {
    if (_animator) return _animator;

    _animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.slidingViewController.view];
    _animator.delegate = self;
    [_animator updateItemUsingCurrentState:self.slidingViewController.topViewController.view];

    return _animator;
}

- (UICollisionBehavior *)collisionBehavior {
    if (_collisionBehavior) return _collisionBehavior;

    _collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[self.slidingViewController.topViewController.view]];

    CGFloat containerHeight = self.slidingViewController.view.bounds.size.height;
    CGFloat containerWidth  = self.slidingViewController.view.bounds.size.width;
    CGFloat revealAmount    = self.slidingViewController.anchorRightRevealAmount;

    [_collisionBehavior addBoundaryWithIdentifier:@"LeftEdge" fromPoint:CGPointMake(-1, 0) toPoint:CGPointMake(-1, containerHeight)];
    [_collisionBehavior addBoundaryWithIdentifier:@"RightEdge" fromPoint:CGPointMake(revealAmount + containerWidth + 1, 0) toPoint:CGPointMake(revealAmount + containerWidth + 1, containerHeight)];

    return _collisionBehavior;
}

- (UIGravityBehavior *)gravityBehavior {
    if (_gravityBehavior) return _gravityBehavior;

    _gravityBehavior = [[UIGravityBehavior alloc] initWithItems:@[self.slidingViewController.topViewController.view]];

    return _gravityBehavior;
}

- (UIPushBehavior *)pushBehavior {
    if (_pushBehavior) return _pushBehavior;

    _pushBehavior = [[UIPushBehavior alloc] initWithItems:@[self.slidingViewController.topViewController.view] mode:UIPushBehaviorModeInstantaneous];

    return _pushBehavior;
}

- (UIDynamicItemBehavior *)topViewBehavior {
    if (_topViewBehavior) return _topViewBehavior;

    UIView *topView = self.slidingViewController.topViewController.view;
    _topViewBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[topView]];
    // the density ranges from 1 to 5 for iPad to iPhone
    _topViewBehavior.density = 908800 / (topView.bounds.size.width * topView.bounds.size.height);
    _topViewBehavior.elasticity = 0;
    _topViewBehavior.resistance = 1;

    return _topViewBehavior;
}

- (UIDynamicBehavior *)compositeBehavior {
    if (_compositeBehavior) return _compositeBehavior;

    _compositeBehavior = [[UIDynamicBehavior alloc] init];
    [_compositeBehavior addChildBehavior:self.collisionBehavior];
    [_compositeBehavior addChildBehavior:self.gravityBehavior];
    [_compositeBehavior addChildBehavior:self.pushBehavior];
    [_compositeBehavior addChildBehavior:self.topViewBehavior];
    __weak typeof(self)weakSelf = self;
    _compositeBehavior.action = ^{
        // stop the dynamic animation when the value of the left edge is the same 5 times in a row.
        NSNumber *leftEdge = [NSNumber numberWithFloat:weakSelf.slidingViewController.topViewController.view.frame.origin.x];
        [weakSelf.leftEdgeQueue insertObject:leftEdge atIndex:0];
        if (weakSelf.leftEdgeQueue.count == 6) [weakSelf.leftEdgeQueue removeLastObject];

        if (weakSelf.leftEdgeQueue.count == 5 &&
            ((NSArray *)[weakSelf.leftEdgeQueue valueForKeyPath:@"@distinctUnionOfObjects.self"]).count == 1) {
            [weakSelf.animator removeAllBehaviors];
        }
    };

    return _compositeBehavior;
}

#pragma mark - UIViewControllerInteractiveTransitioning

- (void)startInteractiveTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
    self.transitionContext = transitionContext;

    UIViewController *topViewController = [transitionContext viewControllerForKey:ECTransitionContextTopViewControllerKey];
    topViewController.view.userInteractionEnabled = NO;

    if (_isInteractive) {
        UIViewController *underViewController = [transitionContext viewControllerForKey:ECTransitionContextUnderLeftControllerKey];
        CGRect underViewInitialFrame = [transitionContext initialFrameForViewController:underViewController];
        CGRect underViewFinalFrame   = [transitionContext finalFrameForViewController:underViewController];
        UIView *containerView = [transitionContext containerView];
        CGFloat finalLeftEdge = CGRectGetMinX([transitionContext finalFrameForViewController:topViewController]);
        CGFloat initialLeftEdge = CGRectGetMinX([transitionContext initialFrameForViewController:topViewController]);
        CGFloat fullWidth = fabs(finalLeftEdge - initialLeftEdge);

        CGRect underViewFrame;
        if (CGRectIsEmpty(underViewInitialFrame)) {
            underViewFrame = underViewFinalFrame;
        } else {
            underViewFrame = underViewInitialFrame;
        }

        underViewController.view.frame = underViewFrame;

        [containerView insertSubview:underViewController.view belowSubview:topViewController.view];

        self.positiveLeftToRight = initialLeftEdge < finalLeftEdge;
        self.fullWidth           = fullWidth;
    } else {
        [self.defaultAnimationController animateTransition:transitionContext];
    }
}

#pragma mark - UIPanGestureRecognizer action

- (void)handlePanGesture:(UIPanGestureRecognizer *)recognizer {
    if ([self.animator isRunning]) return;

    UIView *topView       = self.slidingViewController.topViewController.view;
    CGFloat translationX  = [recognizer translationInView:self.slidingViewController.view].x;
    CGFloat velocityX     = [recognizer velocityInView:self.slidingViewController.view].x;

    // Blur effect
    [self blurControl];

    switch (recognizer.state) {
        case UIGestureRecognizerStateBegan: {
            BOOL isMovingRight = velocityX > 0;

            CALayer *presentationLayer = (CALayer *)topView.layer.presentationLayer;
            self.initialTopViewFrame = presentationLayer.frame;

            _isInteractive = YES;

            if (self.slidingViewController.currentTopViewPosition == ECSlidingViewControllerTopViewPositionCentered && isMovingRight && self.slidingViewController.underLeftViewController) {
                [self.slidingViewController anchorTopViewToRightAnimated:YES];
            } else if (self.slidingViewController.currentTopViewPosition == ECSlidingViewControllerTopViewPositionCentered && !isMovingRight && self.slidingViewController.underRightViewController) {
                [self.slidingViewController anchorTopViewToLeftAnimated:YES];
            } else if (self.slidingViewController.currentTopViewPosition == ECSlidingViewControllerTopViewPositionAnchoredLeft) {
                [self.slidingViewController resetTopViewAnimated:YES];
            } else if (self.slidingViewController.currentTopViewPosition == ECSlidingViewControllerTopViewPositionAnchoredRight) {
                [self.slidingViewController resetTopViewAnimated:YES];
            } else {
                _isInteractive = NO;
            }

            break;
        }
        case UIGestureRecognizerStateChanged: {
            if (!_isInteractive) return;

            CGRect topViewInitialFrame = self.initialTopViewFrame;
            CGFloat newLeftEdge = topViewInitialFrame.origin.x + translationX;

            if (newLeftEdge < 0) {
                newLeftEdge = 0;
            } else if (newLeftEdge > self.slidingViewController.anchorRightRevealAmount) {
                newLeftEdge = self.slidingViewController.anchorRightRevealAmount;
            }

            topViewInitialFrame.origin.x = newLeftEdge;
            topView.frame = topViewInitialFrame;

            if (!self.positiveLeftToRight) translationX = translationX * -1.0;
            CGFloat percentComplete = (translationX / self.fullWidth);
            if (percentComplete < 0) percentComplete = 0;
            if (percentComplete > 100) percentComplete = 100;
            [self.transitionContext updateInteractiveTransition:percentComplete];
            break;
        }
        case UIGestureRecognizerStateEnded:
        {
            [self blurControl];
        };
        case UIGestureRecognizerStateCancelled: {
            if (!_isInteractive) return;

            _isInteractive = NO;

            self.isPanningRight = velocityX > 0;

            if (self.isPanningRight) {
                [self blurControl];
            } else {
                [self disableBlur];
            }

            self.gravityBehavior.gravityDirection = self.isPanningRight ? CGVectorMake(2, 0) : CGVectorMake(-2, 0);

            self.pushBehavior.angle = 0; // velocity may be negative
            self.pushBehavior.magnitude = velocityX;
            self.pushBehavior.active = YES;

            [self.animator addBehavior:self.compositeBehavior];

            break;
        }
        default:
            break;
    }
}

#pragma mark - UIDynamicAnimatorDelegate

- (void)dynamicAnimatorDidPause:(UIDynamicAnimator*)animator {
    [self.animator removeAllBehaviors];

    _collisionBehavior = nil;
    _topViewBehavior = nil;
    _pushBehavior = nil;
    _gravityBehavior = nil;
    _compositeBehavior = nil;
    _animator = nil;

    self.slidingViewController.topViewController.view.userInteractionEnabled = YES;
    UIViewController *topViewController = [self.transitionContext viewControllerForKey:ECTransitionContextTopViewControllerKey];
    if ((self.isPanningRight && self.positiveLeftToRight) || (!self.isPanningRight && !self.positiveLeftToRight)) {
        topViewController.view.frame = [self.transitionContext finalFrameForViewController:topViewController];
        [self.transitionContext finishInteractiveTransition];
    } else if ((self.isPanningRight && !self.positiveLeftToRight) || (!self.isPanningRight && self.positiveLeftToRight)) {
        topViewController.view.frame = [self.transitionContext initialFrameForViewController:topViewController];
        [self.transitionContext cancelInteractiveTransition];
    }

    [self.transitionContext completeTransition:YES];
}

#pragma mark - Blur

- (void) setBlurOffset:(CGFloat) offset {
    UIView *topView = self.slidingViewController.topViewController.view;

    if (!effectView) {
        UIBlurEffect * blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
        effectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
        effectView.frame = topView.bounds;
        effectView.alpha = 0.1f;
        [topView addSubview:effectView];

        [effectView setTranslatesAutoresizingMaskIntoConstraints:false];
        [topView addConstraint:[NSLayoutConstraint constraintWithItem:effectView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:topView attribute:NSLayoutAttributeTop multiplier:1 constant:0]];
        [topView addConstraint:[NSLayoutConstraint constraintWithItem:effectView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:topView attribute:NSLayoutAttributeBottom multiplier:1 constant:0]];
        [topView addConstraint:[NSLayoutConstraint constraintWithItem:effectView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:topView attribute:NSLayoutAttributeLeading multiplier:1 constant:0]];
        [topView addConstraint:[NSLayoutConstraint constraintWithItem:effectView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:topView attribute:NSLayoutAttributeTrailing multiplier:1 constant:0]];
    }

    CGFloat c = offset / 100;
    if (c < 0.1f) c = 0.1f; else if (c > 0.5f) c = 0.5f;
    effectView.alpha = c;
}

- (void) disableBlur{
    if (effectView != NULL) {
        [effectView removeFromSuperview];
        effectView = NULL;
    }
}

- (void) blurControl{
    UIView *topView = self.slidingViewController.topViewController.view;
    NSLog(@"X: %f", topView.frame.origin.x);

    if (topView.frame.origin.x >= 15) {
        [self setBlurOffset:topView.frame.origin.x];
    } else {
        [self disableBlur];
    }

}
@end

相关问答

更多

相关文章

更多

最新问答

更多
  • 获取MVC 4使用的DisplayMode后缀(Get the DisplayMode Suffix being used by MVC 4)
  • 如何通过引用返回对象?(How is returning an object by reference possible?)
  • 矩阵如何存储在内存中?(How are matrices stored in memory?)
  • 每个请求的Java新会话?(Java New Session For Each Request?)
  • css:浮动div中重叠的标题h1(css: overlapping headlines h1 in floated divs)
  • 无论图像如何,Caffe预测同一类(Caffe predicts same class regardless of image)
  • xcode语法颜色编码解释?(xcode syntax color coding explained?)
  • 在Access 2010 Runtime中使用Office 2000校对工具(Use Office 2000 proofing tools in Access 2010 Runtime)
  • 从单独的Web主机将图像传输到服务器上(Getting images onto server from separate web host)
  • 从旧版本复制文件并保留它们(旧/新版本)(Copy a file from old revision and keep both of them (old / new revision))
  • 西安哪有PLC可控制编程的培训
  • 在Entity Framework中选择基类(Select base class in Entity Framework)
  • 在Android中出现错误“数据集和渲染器应该不为null,并且应该具有相同数量的系列”(Error “Dataset and renderer should be not null and should have the same number of series” in Android)
  • 电脑二级VF有什么用
  • Datamapper Ruby如何添加Hook方法(Datamapper Ruby How to add Hook Method)
  • 金华英语角.
  • 手机软件如何制作
  • 用于Android webview中图像保存的上下文菜单(Context Menu for Image Saving in an Android webview)
  • 注意:未定义的偏移量:PHP(Notice: Undefined offset: PHP)
  • 如何读R中的大数据集[复制](How to read large dataset in R [duplicate])
  • Unity 5 Heighmap与地形宽度/地形长度的分辨率关系?(Unity 5 Heighmap Resolution relationship to terrain width / terrain length?)
  • 如何通知PipedOutputStream线程写入最后一个字节的PipedInputStream线程?(How to notify PipedInputStream thread that PipedOutputStream thread has written last byte?)
  • python的访问器方法有哪些
  • DeviceNetworkInformation:哪个是哪个?(DeviceNetworkInformation: Which is which?)
  • 在Ruby中对组合进行排序(Sorting a combination in Ruby)
  • 网站开发的流程?
  • 使用Zend Framework 2中的JOIN sql检索数据(Retrieve data using JOIN sql in Zend Framework 2)
  • 条带格式类型格式模式编号无法正常工作(Stripes format type format pattern number not working properly)
  • 透明度错误IE11(Transparency bug IE11)
  • linux的基本操作命令。。。