Until we are,For example, third-party input method Sogou input method has a classic gesture - paddling around on the keyboard to move the cursor。And this feature I am also very common,so,I want to implement it yourself。
The first thing I think of is UISwipeGestureRecognizer ,However, with predictable results,Paddling can only move the cursor one space,This is not what I want。
It seems the only way is to use UIPanGestureRecognizer To yourself achieving。
Original idea
Very beginning,I think that like to capture dragging down to the position of the finger on the keyboard,I just need to get the x-axis,If it is positive to the right,Negative on the left。
The code might look like this:
1 2 3 4 5 6 7 |
@IBAction func moveCurser(sender: UIPanGestureRecognizer) { if sender.translationInView(keyboardView).x < 0 { self.textDocumentProxy.adjustTextPositionByCharacterOffset(-1) } else { self.textDocumentProxy.adjustTextPositionByCharacterOffset(1) } } |
Because I only have permission to move the cursor in the opposite direction in accordance with,So I had so。of course,The disadvantage is that regardless of the speed of movement,The moving speed of the cursor is consistent with the frequency of function calls。
Another fatal flaw is that if my finger in one direction paddling distant,Then move back - this process will still innocently cursor over the previous direction to continue moving!
Use acceleration instead of coordinates as judge
Ok,This time I switch UIPanGestureRecognizer Built-in velocityInView To obtain acceleration,Because there is acceleration direction! Clear,Cursor silly move in one direction, but the problem has been solved ......,It still relies on the system to determine the frequency of calls moving speed,This leads to move the cursor quickly。
Frequency filtering system calls
Fortunately,Call frequency of the system is fixed,So we can easily realize the filter,Add a property,Calls for the number of storage,When the number reaches a specified value such as 100 calls,We really perform a function:
1 2 3 4 5 6 7 8 9 10 11 |
var recognizerCount = 0 @IBAction func moveCurser(sender: UIPanGestureRecognizer) { recognizerCount += 1 guard recognizerCount > 100 else {return} recognizerCount = 0 if sender.velocityInView(keyboardView).x < 0 { self.textDocumentProxy.adjustTextPositionByCharacterOffset(-1) } else { self.textDocumentProxy.adjustTextPositionByCharacterOffset(1) } } |
Dynamically change the cursor movement speed according to the speed of movement
This cursor movement finally seem more appropriate,So the next question is the moving speed of the cursor changes,Now moving speed is fixed,Whether you want to move a little faster or slower movement,Will not work。To achieve this goal,We have to make a fuss acceleration。
Acceleration will be based on your finger on the screen to change the speed of movement,In a nutshell is your paddling faster,So the greater the acceleration - that way we will have two options:
- According to the acceleration once to move the cursor to change the number of words;
- According to the frequency with the acceleration side function calls。
Program 1 easier,Calculate the acceleration to single digits and then directly throw adjustTextPositionByCharacterOffset(_:) Enough,But this has a problem - the positioning accuracy will decline。I chose a more similar Sogou input method of the latter,I still move the cursor every time 1 Distance characters,Only need to change to call a function of frequency - that,Change our filtering algorithm like。
Now simply filtering each 100 Take time 1 Secondary,So once we get ahead acceleration,Reckon it a try,Because there is an acceleration direction - you can not go back to the filter Incremental Save?we use abs Global mathematical function to find the absolute value of about,Processing then,At the same time due to the huge acceleration change,After several tests,Reduced 10 times more appropriate,So the code looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 |
var recognizerCount = 0 @IBAction func moveCurser(sender: UIPanGestureRecognizer) { let v = Int(sender.velocityInView(keyboardView).x) recognizerCount += Int(abs(v)/10) guard recognizerCount > 100 else {return} recognizerCount = 0 if sender.velocityInView(keyboardView).x < 0 { self.textDocumentProxy.adjustTextPositionByCharacterOffset(-1) } else { self.textDocumentProxy.adjustTextPositionByCharacterOffset(1) } } |
Such,The actual function call frequency will be determined by the filter,The incremental filter and the acceleration you actually paddling on the screen generated by the decision,Thus achieving almost simultaneously moving the cursor with your finger results。
Misuse compatible
At last,We like some finishing work。Since the discriminating layer buttons below the keyboard,Then we will let them close co-operation for the job - UIPanGestureRecognizer Immediately canceled UIButton Click operation,That is,If a user typing faster,The fingers on the keyboard without accidentally rubbing a bit,Then the system will be recognized as a small but significant acceleration of paddling instead of clicking。
so,first step,We need to cancel cancelsTouchesInView ,It evaluates to false or to cancel the check in the graphical configuration。
This alone is not enough,We have to continue to increase the corresponding threshold,And then get dragged in front of the absolute value of the filter,If the drag is less than a certain distance,It does not perform the same function,Left to the user some buffer space,Only when the user really wants to paddling to move the cursor to move the cursor to,Then,The final function should be like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var recognizerCount = 0 @IBAction func moveCurser(sender: UIPanGestureRecognizer) { guard abs(sender.translationInView(keyboardView).x) > 70 else {return} let v = Int(sender.velocityInView(keyboardView).x) recognizerCount += Int(abs(v)/10) guard recognizerCount > 100 else {return} recognizerCount = 0 if sender.velocityInView(keyboardView).x < 0 { self.textDocumentProxy.adjustTextPositionByCharacterOffset(-1) } else { self.textDocumentProxy.adjustTextPositionByCharacterOffset(1) } } |
Original article written by LogStudio:R0uter's Blog » iOS custom keyboard around the keyboard to move the cursor implement
Reproduced Please keep the source and description link:https://www.logcg.com/archives/1987.html