簡體   English   中英

通過UIScrollView使基礎視圖可單擊

[英]making underlying views clickable through UIScrollView

以下是我想做的

在此處輸入圖片說明

我所擁有的是ScrollView001ScrollView002 布局如下。

- View
  - ScrollView001
  - ScrollView002

ScrollView002 ,需要全屏顯示,因此ScrollView001顯然在ScrollView002下面。

我這樣做是為了達到某種效果,即當我滾動ScrollView002 ,我想以較低的速度滾動ScrollView001 ,這已經成功完成了,但問題是當我嘗試單擊Car for Gallery時,它沒有單擊。 如果我只是簡單地隱藏ScrollView002 ,則圖庫將照常工作。

知道如何使基礎視圖可點擊嗎?

對於Gallery,我使用的是UICollectionView。


編輯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 :)

編輯

正如您所提到的,您確實嘗試了我的方法,但它仍然對您有用:)我決定自己試一下,並意識到它絕對可以用。 請看一看 :)

在此處輸入圖片說明

我相信這就是您的情況:)我在彼此之上添加了兩個scrollViews。 小的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的變量,以保存情節提要中位於它后面的smallerScrollView的引用(我非常清楚,擁有像這樣的引用以在后面查看不是一個很好的設計:),但是我相信它足以解釋邏輯)

這是我的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")
    }
}

編輯

根據我們的討論,我意識到您有一個collectionView作為較小的ScrollView上的子視圖,它本身位於全屏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。

現在轉到情節提要中,選擇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

嘗試將此“取景”按鈕作為汽車的背景,然后將其作為汽車的imageview,以便可以單擊。。我認為我不需要使視圖可點擊

您應該在上方的滾動tapgesturerecognizer上添加tapgesturerecognizer ,然后可以處理類似tap的操作,

- (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。

希望這會有所幫助:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM