UIView
通过实现UITextInput
协议,实现单指移动光标手势,双指修改文本选区手势。
分别使用了UIPanGestureRecognizer
和UIPinchGestureRecognizer
手势。
#import "ViewController.h"
#import "JSWebView.h"
#import "UIView+Constriant.h"
#import "JSInputView.h"
#import "UIResponder+FirstResponder.h"
#import "NSObject+SetFrame.h"
#import "WebViewJavascriptBridge.h"
@interface ViewController () <UIWebViewDelegate>
@property (nonatomic, strong) JSWebView *webView;
@property (nonatomic, strong) NSLayoutConstraint *bottomConstraint;
//@property WebViewJavascriptBridge* bridge;
@property (nonatomic, assign) CGPoint lastPoint;
@property (nonatomic, assign) CGPoint startPoint0;
@property (nonatomic, assign) CGPoint startPoint1;
@property (nonatomic, assign) CGRect lastRect0;
@property (nonatomic, assign) CGRect lastRect1;
@property (nonatomic, assign) CGRect startRect0;
@property (nonatomic, assign) CGRect startRect1;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
/*……*/
//单指移动光标手势
UIPanGestureRecognizer *singleFingerPanRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(singleFingerMoveCursor:)];
singleFingerPanRecognizer.maximumNumberOfTouches = 1;
[self.webView.keyboard addGestureRecognizer:singleFingerPanRecognizer];
//双指选择选区手势
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchSelect:)];
[self.webView.keyboard addGestureRecognizer:pinchGesture];
self.lastRect0 = CGRectMake(0, 0, 1, 19);
self.lastRect1 = CGRectMake(0, 0, 1, 19);
self.startPoint0 = CGPointMake(0, 0);
self.startPoint1 = CGPointMake(0, 0);
self.lastPoint = CGPointMake(0, 0);
[self loadWeb];
}
#pragma mark - keyboard gesture
//单个手指移动光标
- (void)singleFingerMoveCursor: (UIPanGestureRecognizer *)sender {
UIResponder <UITextInput>*textInput = [UIResponder currentFirstResponder];
if (sender.state == UIGestureRecognizerStateBegan) {
self.lastPoint = CGPointMake(0, 0);
CGPoint cursorPoint = [textInput caretRectForPosition:textInput.selectedTextRange.start].origin;
self.lastRect0 = CGRectMake(cursorPoint.x, cursorPoint.y, 20, 20);
} else if (sender.state == UIGestureRecognizerStateChanged) {
// NSString *webString = [self.webView stringByEvaluatingJavaScriptFromString:@"document.body.innerText"];
CGRect newFrame = CGRectMake(self.lastRect0.origin.x + [sender translationInView:self.webView.keyboard].x - self.lastPoint.x, self.lastRect0.origin.y + [sender translationInView:self.webView.keyboard].y - self.lastPoint.y, self.lastRect0.size.width, self.lastRect0.size.height);
CGPoint cursorPoint;
if ([sender translationInView:self.webView.keyboard].y > 0) {
cursorPoint = CGPointMake(newFrame.origin.x, newFrame.origin.y);
} else if ([sender translationInView:self.webView.keyboard].y < 0) {
cursorPoint = CGPointMake(newFrame.origin.x, newFrame.origin.y + newFrame.size.height);
} else {
cursorPoint = CGPointMake(newFrame.origin.x, newFrame.origin.y + newFrame.size.height / 2);
}
UITextPosition *pos = [textInput closestPositionToPoint:cursorPoint];
UITextRange *textRange = [textInput textRangeFromPosition:pos toPosition:pos];
textInput.selectedTextRange = textRange;
self.lastRect0 = newFrame;
self.lastPoint = CGPointMake([sender translationInView:self.webView.keyboard].x, [sender translationInView:self.webView.keyboard].y);
}
}
static bool isReverse; //左右手指是否和locationOfTouch:检测结果相反
//双指移动选择文字手势
- (void)pinchSelect:(UIPinchGestureRecognizer *)sender {
UIResponder <UITextInput>*textInput = [UIResponder currentFirstResponder];
if (sender.state == UIGestureRecognizerStateBegan) {
self.startPoint0 = [sender locationOfTouch:0 inView:self.webView.keyboard];
self.startPoint1 = [sender locationOfTouch:1 inView:self.webView.keyboard];
isReverse = false;
if (self.startPoint0.x > self.startPoint1.x) { //左右手指相反
CGPoint temp;
temp = self.startPoint0;
self.startPoint0 = self.startPoint1;
self.startPoint1 = temp;
isReverse = true;
}
if (textInput.selectedTextRange.isEmpty){ //是否有选区
self.startRect0 = [textInput caretRectForPosition:textInput.selectedTextRange.start];
self.startRect1 = [textInput caretRectForPosition:textInput.selectedTextRange.start];
} else {
self.startRect0 = [textInput caretRectForPosition:textInput.selectedTextRange.start];
self.startRect1 = [textInput caretRectForPosition:textInput.selectedTextRange.end];
}
self.lastRect0 = self.startRect0;
self.lastRect1 = self.startRect1;
} else if (sender.state == UIGestureRecognizerStateChanged) {
if ([sender numberOfTouches] == 2) {
float deltaX;
float deltaY;
//左边手指移动距离
if (isReverse) {
deltaX = [sender locationOfTouch:1 inView:self.webView.keyboard].x - self.startPoint0.x;
deltaY = [sender locationOfTouch:1 inView:self.webView.keyboard].y - self.startPoint0.y;
} else {
deltaX = [sender locationOfTouch:0 inView:self.webView.keyboard].x - self.startPoint0.x;
deltaY = [sender locationOfTouch:0 inView:self.webView.keyboard].y - self.startPoint0.y;
}
self.lastRect0 = CGRectMake(self.startRect0.origin.x, self.startRect0.origin.y, self.startRect0.size.width, self.startRect0.size.height);
if (deltaY > 0) {
self.lastRect0 = [self frame:_lastRect0 withPoint:CGPointMake(self.lastRect0.origin.x + deltaX, self.lastRect0.origin.y + deltaY)];//CGRectMake(self.lastRect0.origin.x + deltaX, self.lastRect0.origin.y + deltaY, 20, 20);
} else if (deltaY < 0) {
self.lastRect0 = [self frame:_lastRect0 withPoint:CGPointMake(self.lastRect0.origin.x + deltaX, self.lastRect0.origin.y + deltaY + self.lastRect0.size.height * 0.9)];
} else {
self.lastRect0 = [self frame:_lastRect0 withPoint:CGPointMake(self.lastRect0.origin.x + deltaX, self.lastRect0.origin.y + deltaY + self.lastRect0.size.height * 0.5)];
}
//右边手指移动
if (isReverse) {
deltaX = [sender locationOfTouch:0 inView:self.webView.keyboard].x - self.startPoint1.x;
deltaY = [sender locationOfTouch:0 inView:self.webView.keyboard].y - self.startPoint1.y;
} else {
deltaX = [sender locationOfTouch:1 inView:self.webView.keyboard].x - self.startPoint1.x;
deltaY = [sender locationOfTouch:1 inView:self.webView.keyboard].y - self.startPoint1.y;
}
self.lastRect1 = [self frame:_lastRect1 withPoint:CGPointMake(self.startRect1.origin.x, self.startRect1.origin.y)];
if (deltaY > 0) {
self.lastRect1 = [self frame:_lastRect1 withPoint:CGPointMake(self.lastRect1.origin.x + deltaX, self.lastRect1.origin.y + deltaY)];;
} else if (deltaY < 0) {
self.lastRect1 = [self frame:_lastRect1 withPoint:CGPointMake(self.lastRect1.origin.x + deltaX, self.lastRect1.origin.y + deltaY + self.lastRect1.size.height * 0.9)];;
} else {
self.lastRect1 = [self frame:_lastRect1 withPoint:CGPointMake(self.lastRect1.origin.x + deltaX, self.lastRect1.origin.y + deltaY + self.lastRect1.size.height * 0.5)];;
}
UITextPosition *textPoint0 = [textInput closestPositionToPoint:self.lastRect0.origin];
UITextPosition *textPoint1 = [textInput closestPositionToPoint:self.lastRect1.origin];
textInput.selectedTextRange = [textInput textRangeFromPosition:textPoint0 toPosition:textPoint1];
}
}
}