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.
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
相关问答
更多-
//在视图控制器类中设置委托 class FeedVC: UIViewController,SWRevealViewControllerDelegate,UIGestureRecognizerDelegate override func viewDidLoad() { super.viewDidLoad() self.revealViewController().delegate = self var swl=self.revealViewController() ...
-
正如@eric指出的那样, UIBar按钮只显示菜单。 如果您希望它解除同一IBAction上的菜单,您需要添加更多逻辑: - (IBAction)menuButtonTapped:(id)sender { //Chek the current position if([self.slidingViewController currentTopViewPosition]==2){ //show menu [self.slidingViewController anchor ...
-
plist设置"View controller-based status bar appearance"仅控制是否在iOS 7上应用基于控制器的设置。 如果将此plist选项设置为NO,则必须手动启用和禁用状态栏(直到iOS 6): [[UIApplication sharedApplication] setStatusBarHidden:YES] 如果将此plist选项设置为YES,则可以将此方法添加到每个viewControllers中,以为每个控制器独立设置statusBar(如果您具有viewCo ...
-
这是我最终做的事情: UIViewController *topViewController = self.slidingViewController.topViewController; CGFloat dX = self.view.frame.size.width - self.slidingViewController.anchorRightRevealAmount; // You can replace kSearchAnimationDuration with 0.25 or define i ...
-
你需要使用UIBlurEffect和UIVisualEffectView这是你的代码应该是这样的: - (IBAction)buttonClicked:(id)sender { // Create blur effect UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; // Add effect to an effect view UIVisualEffec ...
-
您可以将nil传递给rightMenuViewController,并且应该这样做。 你应该将nil传递给你不希望拥有的那一面。 MFSideMenuContainerViewController *container = [MFSideMenuContainerViewController containerWithCenterViewController:[self navigationController] ...
-
没有人在这里评论或回答似乎意识到你想模糊用户自己的壁纸并将其用作根视图控制器的背景,就像在Apple自己的应用程序(例如Remote)中实现的那样。 虽然在早期版本的iOS中可能已经存在,但目前无法使用公共API 在您自己的应用程序中实现此效果 。 Nobody who’s commented or answered here seems to realise that you want to blur the user’s own wallpaper and use that as the backgro ...
-
我解决了这个问题。 从示例中获取一些类并更改它: CPSlidingAnimationController: #import "CPSlidingAnimationController.h" #import "ECSlidingAnimationController.h" #import "ECSlidingConstants.h" @interface CPSlidingAnimationController () @property (nonatomic, copy) void (^coordinat ...
-
点击菜单视图后,滑动topViewController左右停止(sliding topViewController left and right stops after tapping on menu view)[2023-10-10]
您添加到应用程序委托中的导航控制器的panGesture将保留该导航控制器的视图。 您使用该导航控制器初始化滑动视图控制器,因此当导航控制器是顶视图控制器时,平移手势会起作用。 更改顶视图控制器后,平移手势将消失(因为它已附加到该导航控制器的视图)。 您需要将panGesture添加回另一个视图(很可能是在新的顶视图控制器视图或其子视图之一)。 一种方法是在viewDidLoad为每个视图控制器创建滑动视图控制器的顶视图控制器。 在First,Second和Home视图控制器中: #import "UIVi ... -
如何使用ECSlidingViewController知道菜单何时“打开”(How to know when menu is “open” using ECSlidingViewController)[2022-04-26]
根据文档,您应该能够查询currentTopViewPosition属性。 这被定义为 typedef NS_ENUM(NSInteger, ECSlidingViewControllerTopViewPosition) { /** The top view is on anchored to the left */ ECSlidingViewControllerTopViewPositionAnchoredLeft, /** The top view is on anchored ...