一旦移动到另一个自定义视图,自定义视图就会停止识别手势

Custom view stops recognize gestures as soon as it moved into another custom view

我有以下两个 classes:

LongUpperView.swift

class LongUpperView: UIView, UIGestureRecognizerDelegate {

let TAG: String = "BannerView"

weak var mPredictionViewDelegate: PredictionViewDelegate!
weak var mUrlManagerDelegate: URLManagerdelegate!
weak var mLongUpperViewDelegate: LongUpperViewDelegate!
var panRecognizer: UIPanGestureRecognizer?

var mLogoView: LogoView!
var mPredictionView: PredictionView!
var mRunningNewsView: RunningNewsView!

var mCurrentCircleViewIndex: Int! = 0
var resUpdated: Array<String>!
var mWidth: CGFloat!
var mFeedsArray: Array<News>!

var mModelManager: ModelManager!
var mURLManager: UrlManager!
var mGetNewsTimer: NSTimer?
var mMovementBeginPoint: CGPoint!

let velocityFactor = 5
var mPreVelocity: CGPoint!

required init(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

init(aFrame: CGRect, aWidth: CGFloat, activeIndex: Int, aIsAccessGranted: Bool, context: NSExtensionContext?, aPredictionViewDelegate: PredictionViewDelegate, aUrlManagerDelegate: URLManagerdelegate, aAllowFullAccessDelegate: AllowFullAccessViewDelegate, aLongUpperViewDelegate: LongUpperViewDelegate) {
    super.init(frame: aFrame)

    self.mWidth = aWidth
    self.mPredictionViewDelegate = aPredictionViewDelegate
    self.mUrlManagerDelegate = aUrlManagerDelegate
    self.mLongUpperViewDelegate = aLongUpperViewDelegate

    self.backgroundColor = UIColor.clearColor()
    self.mFeedsArray = Array<News>()

    if aIsAccessGranted == false {
        let AllowFullAccessButtonsView = AllowFullAccessView(frame: CGRectMake(0, 0, aFrame.size.width, 52), aWidth: self.mWidth, context: context, delegate: aAllowFullAccessDelegate)
        self.addSubview(AllowFullAccessButtonsView)
    } else {
        self.createLogoView(self.mWidth)
        self.createCompletionPredictionView(self.mWidth, aWidth: self.mWidth)
        self.createRunningFeedsView(self.mWidth * 2, aWidth: self.mWidth)
    }
}

func changeFrame(aParentWidth: CGFloat) {
    self.frame = CGRectMake(0, 0, aParentWidth, self.frame.size.height)
    //self.mLogoView.frame = CGRectMake(0, 0, aParentWidth, self.mLogoView.frame.size.height)
    //self.mPr

    self.cleanLongUpperViewViewsOnly()
    self.createLogoView(aParentWidth)
    self.createCompletionPredictionView(aParentWidth, aWidth: aParentWidth)
    self.createRunningFeedsView(aParentWidth * 2, aWidth: aParentWidth)
}

func setupGestures() {
    self.panRecognizer = UIPanGestureRecognizer(target: self, action: "movePanel:")
    self.panRecognizer!.minimumNumberOfTouches = 1
    self.panRecognizer!.maximumNumberOfTouches = 1
    self.addGestureRecognizer(self.panRecognizer!)
}

func createLogoView(aWidth: CGFloat) {
    let logoImage = UIImage(named: "Logo.png")
    self.mLogoView = LogoView(aFrame: CGRectMake(0, 0, aWidth, logoImage!.size.height), aWidth: aWidth, aFeedsArray: mFeedsArray)
    self.addSubview(self.mLogoView)
    self.mCurrentCircleViewIndex = 0
}

func createCompletionPredictionView(aOffset: CGFloat, aWidth: CGFloat) {
    self.mPredictionView = PredictionView(frame: CGRectMake(aOffset + 0, 8.5, aWidth, 30))
    self.mPredictionView.createButtons(Theme.sharedInstance.getKeyTheme(KiboConstants.ThemeKeys.THEME_KEY_MODIFIER), aCurrentScreenWidth: aWidth)
    self.mPredictionView.delegate = self.mPredictionViewDelegate
    self.addSubview(self.mPredictionView)
    self.mCurrentCircleViewIndex = 1
}

func createRunningFeedsView(aOffset: CGFloat, aWidth: CGFloat) {
    self.mRunningNewsView = RunningNewsView(aFrame: CGRectMake(aOffset, 0, aWidth, self.frame.height), aWidth: aWidth, aRunningFeedsArray: SystemUtils.KeyboardTasks.initMRunNewsArray(self.mFeedsArray))
    self.addSubview(self.mRunningNewsView)
    self.mCurrentCircleViewIndex = 2
}

func updateNewsDone(newsIdsArr: [News]) {
    let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.CachesDirectory, NSSearchPathDomainMask.UserDomainMask, true)
    let documentsDirectory: AnyObject = paths[0] // Get documents folder
    let newsImagesPath = documentsDirectory.stringByAppendingPathComponent(KiboConstants.CommonStrings.JSON_KEY_DATA_NEWS_IMAGES_CACHE)
    self.updateFeeds(newsIdsArr)
}

func updateFeeds(mnewManagedObjectsArrary: Array<News>) {
    var managedObjectItemsCount = mnewManagedObjectsArrary.count

    for var i = managedObjectItemsCount - 1; i >= 0; i-- {

        mFeedsArray.insert(mnewManagedObjectsArrary[i], atIndex: 0)
    }
    self.mLogoView.updateNewsIndicator(self.mFeedsArray)
    self.mRunningNewsView.updateRunningNewsArray(SystemUtils.KeyboardTasks.initMRunNewsArray(self.mFeedsArray))
}

func updateSourcesDone() {
    if let val = mURLManager {

    } else {
        mURLManager = UrlManager()
        mURLManager.delegate = self.mUrlManagerDelegate
    }
    mURLManager.doGetNewsRequest()
}

//EMIL: method to handle the upper long view swipe gestures.
func movePanel(sender: UIPanGestureRecognizer) {
    sender.view!.layer.removeAllAnimations()

    let translatedPoint = sender.translationInView(self)
    let velocity = sender.velocityInView(sender.view)
    let upperViewxPos = self.frame.origin.x
    let compVelocity = Float(velocity.x) / Float(self.velocityFactor)
    let totalXPos = Float(compVelocity) + Float(upperViewxPos)

    if sender.state == UIGestureRecognizerState.Began {
        self.mMovementBeginPoint = translatedPoint
    }

    if sender.state == UIGestureRecognizerState.Ended {
        let upperViewxPos = self.frame.origin.x
        let animationOffsetFloat: Float = Float(totalXPos) / (-1.0 * Float(self.mWidth))

        var animationOffset: Int = Int(round(animationOffsetFloat)) * (-1 * Int(self.mWidth)) // (round(320/upperViewxPos)) * 320

        if (animationOffset > 0) {
            animationOffset = 0
        } else if (CGFloat(animationOffset) < (-1 * self.frame.size.width) + CGFloat(self.mWidth)) {
            animationOffset = -1 * Int(self.frame.size.width) + Int(self.mWidth)
        }

        self.mCurrentCircleViewIndex = Int(animationOffset / (-1 * Int(self.mWidth)))

        let animationOffsetCGFLoat: CGFloat = CGFloat(animationOffset)
        playMoveBackAnimation(CGFloat(animationOffsetCGFLoat), aduration_time: KiboConstants.UserDefaultsValues.DEFAULT_SWIPE_DURATION_VAL)
    }

    if sender.state == UIGestureRecognizerState.Changed {
        sender.view!.center = CGPointMake(sender.view!.center.x + translatedPoint.x, sender.view!.center.y);
        sender.setTranslation(CGPointMake(0, 0), inView: self)
        self.mPreVelocity = velocity;
    }
}

func playMoveBackAnimation(aOffset: CGFloat, aduration_time: Double) {
    UIView.animateWithDuration(aduration_time, delay: 0, options: UIViewAnimationOptions.BeginFromCurrentState, animations: {
        () -> Void in
        self.frame = CGRectMake(aOffset, 0, self.frame.size.width, self.frame.size.height)

        /*/TODO: EMIL: This part updates the space button with the Chelsea logo image when logo is swipped.
        if ((self.mCurrentCircleViewIndex == 0) && (self.spaceButtonPointer.imageView.frame.origin.x < self.spaceOriginXVal)) {
            self.spaceButtonPointer.imageView.frame = CGRectMake(self.spaceOriginXVal, 0, self.spaceButtonPointer.imageView.frame.width, self.spaceButtonPointer.imageView.frame.height)
        } else if ((self.mCurrentCircleViewIndex > 0) && (self.spaceButtonPointer.imageView.frame.origin.x == self.spaceOriginXVal)) {
            self.spaceButtonPointer.imageView.frame = CGRectMake(-1 * self.spaceButtonPointer.imageView.frame.width / 2, 0, self.spaceButtonPointer.imageView.frame.width, self.spaceButtonPointer.imageView.frame.height)
        } */

    }, completion: {
        (Bool) -> Void in
        self.mLongUpperViewDelegate.updateActiveCircleIndex(self.mCurrentCircleViewIndex)
        if aOffset == self.mWidth * -2 {
            self.mRunningNewsView.startRunNewsTimer()
        } else {
            self.mRunningNewsView.stopRunNewsTimer()
        }
    })
}
}

此 class 是以下 class 的一部分:

BannerView.swift:

class BannerView: UIView, LongUpperViewDelegate {

weak var mController: KeyboardViewController?
var mWidth: CGFloat!
var mCircleView: CirclesView!
var mLongUpperView: LongUpperView!

init(aFrame: CGRect, aWidth: CGFloat, aIsAccessGranted: Bool, context: NSExtensionContext?, aPredictionViewDelegate: PredictionViewDelegate, aUrlManagerDelegate: URLManagerdelegate, aAllowFullAccessDelegate: AllowFullAccessViewDelegate, aGestureRecognizerDelegate: UIGestureRecognizerDelegate, aController: KeyboardViewController) {

    self.mController = aController

    super.init(frame: aFrame)

    self.mWidth = aWidth

    self.mCircleView = CirclesView(aYPos: 50, aCirclesNum: 3, aActiveCircleIndex: 0, aMywidth: self.mWidth)
    self.addSubview(self.mCircleView)

    self.mLongUpperView = LongUpperView(aFrame: CGRectMake(0, 0, self.mWidth * 3, 52), aWidth: self.mWidth, activeIndex: 0, aIsAccessGranted: aIsAccessGranted, context: context, aPredictionViewDelegate: aPredictionViewDelegate, aUrlManagerDelegate: aUrlManagerDelegate, aAllowFullAccessDelegate: aAllowFullAccessDelegate, aLongUpperViewDelegate: self)
    self.addSubview(self.mLongUpperView)
}

func changeFrame(aParentWidth: CGFloat) {
    self.frame = CGRectMake(0, 0, aParentWidth * 3, 52)

    let currentActiveCircleIndex = self.mCircleView.mActiveCircleIndex
    self.mCircleView.changeFrame(aParentWidth)
    self.mCircleView.updateActiveCircleIndex(currentActiveCircleIndex)

    self.mLongUpperView.changeFrame(aParentWidth)
}

required init(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

func updateActiveCircleIndex(aIndex: Int) {
    self.mCircleView.updateActiveCircleIndex(aIndex)
}
}

问题:只要我直接在我的UIInputViewController[=]中使用BannerViewclass 35=] 手势被识别,没有问题。

只要我将此 class 移动到另一个自定义视图并在我的控制器中使用此自定义视图,手势和点击就会停止响应。

这是使用 BannerView 的第三个 class:

class KeyboardView: UIView, KeyPressedDelegate, UIGestureRecognizerDelegate {

weak var mDelegate: KeyboardViewController!

var currentKeyboard: Keyboard!
var currentLayout: LayoutKeyboard!
//var panRecognizer: UIPanGestureRecognizer?

    .....

required init(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

init(aFrame: CGRect, aWidth: CGFloat, aDelegate: KeyboardViewController, aPlatformSuffix: String) {
    self.mDelegate = aDelegate
    self.mLanguageCountryCode = aDelegate.mLanguageCountryCode
    self.mLayoutType = aDelegate.mLayoutType
    self.mPlatformSuffix = aPlatformSuffix
    self.mWidth = aWidth

    self.mJsonParser = JsonParser()
    self.mAbcKeyboard = Keyboard()
    self.m123Keyboard = Keyboard()
    self.mSignKeyboard = Keyboard()

    self.mBannerView = BannerView(aFrame: CGRectMake(0, 0, self.mWidth * 3, 52), aWidth: self.mWidth, aIsAccessGranted: mDelegate.mAccessIsGrantedFlag, context: self.mDelegate.extensionContext, aPredictionViewDelegate: self.mDelegate, aUrlManagerDelegate: self.mDelegate, aAllowFullAccessDelegate: self.mDelegate, aGestureRecognizerDelegate: self.mDelegate, aController: self.mDelegate)
    self.mShortView = ShortView(frame: CGRectMake(0, 0, 30, 45))
    super.init(frame: aFrame)
    self.setupDataAndView()
}

func setupDataAndView() {
    self.currentKeyboard = self.mAbcKeyboard
    var pathName: String!

    if self.mIsNumericKeyboardFlag == true {
        pathName = "number_logic"
    } else {
        pathName = self.mLanguageCountryCode + "_logic_abc" + "_" + self.mLayoutType
    }

    self.initKeyboardModel(self.mJsonParser.parseFile(pathName, aFileType: KiboConstants.FileType.FILE_TYPE_JSON))
    self.currentLayout = self.currentKeyboard.mKeyboardLayoutPortrait
    self.initViews()
}

func initViews() {

    if self.mDelegate.mNoBannerFlag == false {
        self.addSubview(self.mBannerView)
    }

    self.mKeysView = KeysView(aFrame: CGRectMake(0, 0, self.frame.size.width, self.frame.size.height), aKeyboardView: self)
    self.addSubview(self.mKeysView)

    self.mShortView.hidden = true
    self.addSubview(self.mShortView)
    //self.setupGestures()
}
....

所以问题是:如何将自定义视图移动到另一个自定义视图,并且仍然只在具有手势识别器的自定义视图上获取滑动事件?

最终问题是添加到自定义视图 (KeysView) 的第二个视图占用了父自定义视图 (KeyboardView) 的所有 space,因此第二个视图自定义视图 (BannerView) 被第一个视图 (KeysView) 覆盖,它把所有的点击事件都交给自己,而不将它们传递给下一个视图。

我为解决这个问题所做的是: 1.更改KeyboardView(父视图)中两个自定义视图的初始化顺序。所以基本上首先我实例化较大的视图 (KeysView) 然后我实例化较小的视图 (BannerView)。

  1. 此外,我在 BannerView 中添加了以下方法:

    override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
        let contains: Bool = CGRectContainsPoint(self.frame, point)
        if contains {
            return true
        } else {
            return false
        }
    }
    

所以 BannerView(最顶层的视图)只处理自己的事件(事件点的检查包含在视图中)并将不为自己的事件传递到视图层次结构中。