使用平移手势在CollectionView

时间:2017-12-13 15:36:23

标签: swift xcode uicollectionview uicollectionviewcell uipangesturerecognizer

我只是Swift的初学者,但我试图在我的一个项目中实现这个特殊功能(单词搜索拼图):用平移手势选择多个单元格。我的每个单元格都包含一个包含单个字符的标签。我希望通过平移手势获取用户想要选择的所有字母。目前,我通过计算从每个细胞的中心到经过点a(触摸开始)和b(触摸结束)的线的距离并且仅考虑足够接近该线的细胞来实现此目的。这大部分时间都可以正常工作,但它仍然容易出错,并且肯定会导致用户不满意。你能建议一种更简单的方法吗?

感谢。

一些代码:

func getGridInfo(){

    for i in 0...numberOfCells-1{
        let indPath = IndexPath(row:i, section:0);
        let cell = collectionView?.cellForItem(at: indPath) as? CustomCell;
        let frameRect = collectionView?.convert((cell?.frame)!, to: self.view);
        coordinates[i] =  (cell?.label.text, frameRect?.midX,  frameRect?.midY) as? (String, CGFloat, CGFloat);
    }
}

@objc func handlePan(touch: UIPanGestureRecognizer){

    let touchPoint = touch.location(in: self.view)

    switch touch.state{
    case .began:
        if let line = curLine{
            line.removeFromSuperlayer();
        }
        firstPoint = touchPoint;
    case .ended:
        secondPoint = touchPoint;

        guard let fP = firstPoint,
              let sP = secondPoint else {
                print("Something went wrong..");
            return;
        }

        let word = getCloseLetters(start:fP, end:sP);

        if (words.contains(word) || words.contains(String(word.reversed()))){
            playSound(soundUrl: correctUrlSoundFx);

            foundWordsLabel.text = word;
            foundWordsLabel.textColor = UIColor.green;
            // to do: update score
        }else{
            playSound(soundUrl: incorrectUrlSoundFx);

            let attributedString = NSMutableAttributedString(string:word);
            attributedString.addAttribute(NSAttributedStringKey.strikethroughStyle, value:2, range: NSMakeRange(0, attributedString.length));
            foundWordsLabel.attributedText = attributedString;
            foundWordsLabel.textColor = UIColor.red;
        }
        curLine = addLine(fromPoint: firstPoint!, toPoint: secondPoint!, width:20);
    default:
        return;
    }
  func getCloseLetters(start:CGPoint, end:CGPoint) -> String{
    var letters = "";

    for i in 0...numberOfCells-1{
        let tuple = coordinates[i]!;
        let x = tuple.1;
        let y = tuple.2;
        if (checkIfPointIsCloseOrOnTheLine(start: start, end: end, aPoint: CGPoint(x:x,y:y)) == true){
            letters += tuple.0;
        }
    }

    return letters;
}

func distanceFromPoint(p: CGPoint, v: CGPoint,  w: CGPoint) -> CGFloat {
    let pv_dx = p.x - v.x;
    let pv_dy = p.y - v.y;
    let wv_dx = w.x - v.x;
    let wv_dy = w.y - v.y;

    let dot = pv_dx * wv_dx + pv_dy * wv_dy;
    let len_sq = wv_dx * wv_dx + wv_dy * wv_dy;
    let param = dot / len_sq;

    var int_x, int_y: CGFloat;

    if param < 0 || (v.x == w.x && v.y == w.y) {
        int_x = v.x;
        int_y = v.y;
    } else if param > 1 {
        int_x = w.x;
        int_y = w.y;
    } else {
        int_x = v.x + param * wv_dx;
        int_y = v.y + param * wv_dy;
    }

    let dx = p.x - int_x;
    let dy = p.y - int_y;

    return sqrt(dx * dx + dy * dy);
}

func checkIfPointIsCloseOrOnTheLine(start:CGPoint, end:CGPoint, aPoint:CGPoint, tollerance:CGFloat = 15) -> Bool{

    let barHeight = self.navigationController?.navigationBar.frame.size.height;
    let newStartPoint = CGPoint(x:start.x, y:start.y - barHeight!);
    let newEndPoint = CGPoint(x:end.x, y:end.y - barHeight!);

    let distance = distanceFromPoint(p:aPoint, v:newStartPoint, w:newEndPoint);
    if distance > tollerance{
        return false;
    }

    return true;
}

0 个答案:

没有答案