通过UIScrollView可以查看底层视图

时间:2016-05-18 06:44:28

标签: ios objective-c cocoa-touch uiscrollview

以下是我想要的内容

enter image description here

我所拥有的是ScrollView001& ScrollView002。布局如下。

- View
  - ScrollView001
  - ScrollView002

ScrollView002全屏,因此ScrollView001明显低于ScrollView002

我这样做有一些效果,即当我滚动ScrollView002时,我想滚动ScrollView001但速度较慢,我已成功完成但问题是当我尝试点击Car时对于Gallery,它不是点击。如果我只是隐藏ScrollView002,那么画廊就像往常一样。

任何想法如何将底层视图设为可点击?

对于Gallery,我使用的是UICollectionView。

编辑1

滚动后,我想要下面的内容。

enter image description here

3 个答案:

答案 0 :(得分:1)

Fahim Parkar,

不确定这是你想要的还是我理解你错了:)我相信你可以使用hitTest:解决它:)

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView *hitView = [super hitTest:point withEvent:event];

    if (hitView && CGRectContainsPoint(ScrollView001.frame, point)) {
        return ScrollView001;
    }
    return hitView;
}

工作原理

每当你点击屏幕scorllView002覆盖整个屏幕捕获触摸:)因此scrollView002的hitTest被调用:)如果你无论如何你可以访问ScrollView001(这应该很容易,因为他们在同一个ViewController)你可以验证是否触摸点位于ScrollView001内,如果是,则可以将touchView作为ScrollView001返回。

因此ScrollView001将触摸而不是ScrollView002 :)

修改

正如你所提到的,你确实尝试过我的方法,它仍然为你工作:)我决定自己动手,并意识到它的工作非常好。请看看:))

enter image description here

我相信这就是你的情况:)我已经在彼此的顶部添加了两个scrollView。小scrollView(myScrollView)位于更大的全屏scrollView(TestScrollView)下方。

现在,当我点击屏幕时,myScrollView无法触摸:) 但那就是我们所需要的就是我所做的:)

我创建了一个名为TestScrollView的ScrollView子类,并为顶部scrollView设置了相同的内容:)

<强> TestScrollView.swift

import UIKit

class TestScrollView: UIScrollView {
    var scrollViewBehind : UIView!
    /*
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func drawRect(rect: CGRect) {
        // Drawing code
    }
    */

    override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
        let hitView = super.hitTest(point, withEvent: event)

        if hitView != nil && CGRectContainsPoint(scrollViewBehind.frame,point) {
            return scrollViewBehind
        }
        return hitView;
    }
}

我已经创建了一个名为scrollViewBehind的变量来保存在storyboard中它后面的smallScrollView的引用(我非常清楚,持有像这样的引用来查看背后不是一个很棒的设计:)但我相信它是好的足以解释逻辑)

这是我的ViewController代码:)

import UIKit

class ViewController: UIViewController,UIGestureRecognizerDelegate {

    @IBOutlet var myScrollView: UIScrollView!
    @IBOutlet var testScrollView: TestScrollView!

    override func viewDidLoad() {
        super.viewDidLoad()
        testScrollView.scrollViewBehind = myScrollView
        let tap = UITapGestureRecognizer(target: self, action: Selector("handleTap"))
        tap.delegate = self
        myScrollView .addGestureRecognizer(tap)
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    func handleTap(){
        print("Me tapped")
    }
}

修改

根据我们的讨论,我意识到你在一个较小的ScrollView上有一个collectionView作为一个子视图,它本身就是全屏scrollView的背后:)

我保留了上面的答案,因为它在Swift中,它还解释了如何处理hitTest将控件从上面的scrollView切换到下面的scrollView。虽然它不能完全解决您的问题,但可能会为其他人提供足够的解决方案:)

现在根据您的问题,当用户点击时,上面的scrollView捕获触摸,触摸应该转发到较小的scrollView顶部的collectionView:)

所以遵循上面解释的相同方法:)我创建了一个ScrollView的子类,让我们调用TestScrollView(根据你的要求,答案在目标C中)

TestScrollView.h

#import <UIKit/UIKit.h>

@interface TestScrollView : UIScrollView
@property (nonatomic,strong) UICollectionView *collectionViewBehind;
@property (nonatomic,strong) UIScrollView *scrollViewBehind;

@end

TestScrollView.m

#import "TestScrollView.h"

@implementation TestScrollView

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/

-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    UIView *hitView = [super hitTest:point withEvent:event];

    CGPoint myPoint = [self convertPoint:point toView:self.scrollViewBehind];
    if (hitView != nil && CGRectContainsPoint(self.scrollViewBehind.frame,point)) {
        return self.collectionViewBehind;
    }
    return hitView;
}
@end

如果你注意到正确的话TestScrollView有两个属性,即collectionViewBehind和scrollViewBehind这是保存下面scrollView和collectionView的引用:)

上面已经解释了hitTest的作用。虽然它只是检查触摸点,如果触摸点在scrollView内,它返回collectionView。它的作用是将触摸事件传递给collectionView。

现在转到storyboard选择topScrollView并将其类设置为TestScrollView。

在加载这些scrollViews的ViewController中添加

#import "ViewController.h"
#import "TestScrollView.h"

@interface ViewController ()<UICollectionViewDelegate,UICollectionViewDataSource,UIGestureRecognizerDelegate>
@property (strong, nonatomic) IBOutlet TestScrollView *testScrollView;
@property (strong, nonatomic) IBOutlet UICollectionView *collectionView;
@property (strong, nonatomic) IBOutlet UIScrollView *scrollView;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.testScrollView.collectionViewBehind = self.collectionView;
    self.testScrollView.scrollViewBehind = self.scrollView;

    self.collectionView.delegate = self;
    self.collectionView.dataSource = self;
    [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"test"];


    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
    tapGesture.numberOfTapsRequired = 1;
    tapGesture.delegate = self;
    [self.collectionView addGestureRecognizer:tapGesture];


    // Do any additional setup after loading the view, typically from a nib.
}

是的,如果您注意到它注意到了我正在向UICollectionView添加TapGesture识别器。虽然我们设法将触摸切换到UICollectionView,但我们注意到didSelectItemAtIndexPath从未被触发过。所以这是一个小工作。

虽然在这种情况下将gestureRecognizer添加到collectionView并不是很明智,但它仍然可以,因为我们只是重写单击,所有其他手势都不会改变。

所以现在每当用户点击UICollectionView的gestureRecognizer上面的scrollView并调用我们的选择器:)现在你所要做的就是弄清楚哪个单元被点击并以编程方式选择它:)

-(void)handleTap:(UIGestureRecognizer *)recognizer {
    [self collectionView:self.collectionView didSelectItemAtIndexPath:[self.collectionView indexPathForItemAtPoint:[recognizer locationInView:self.collectionView]]];
}

最后享受

的控制权
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
    NSLog(@"Hi indexPath tapped is %@",indexPath);
}

最后,这是项目的链接:https://github.com/sandeeplearner/UnderlayingClickableViews

答案 1 :(得分:0)

试试这个 拿按钮作为你的车的背景然后是汽车的imageview,这样它可以点击..我认为我没有必要让视图可以看到

答案 2 :(得分:0)

您应该在上方的scrollview上添加tapgesturerecognizer,然后您可以处理类似的内容,

- (void)handleTap:(UITapGestureRecognizer *)recognizer {

// First get the tap gesture recognizers's location in the entire 
// view's window
CGPoint tapPoint = [recognizer locationInView:self.view];

// Then see if it falls within one of your below images' frames
for (UIImageView* image in relevantImages) {

    // If the image's coordinate system isn't already equivalent to
    // self.view, convert it so it has the same coordinate system
    // as the tap.
    CGRect imageFrameInSuperview = [image.superview convertRect:image toView:self.view]

    // If the tap in fact lies inside the image bounds, 
    // perform the appropriate action.
    if (CGRectContainsPoint(imageFrameInSuperview, tapPoint)) {
        // Perhaps call a method here to react to the image tap
        [self reactToImageTap:image];
        break;
    }
  }
}

您可以考虑使用your car或代替imageview。

希望这会有所帮助:)