Gesture monitoring and UI implementation for iOS Xiaomi remote control

Source: Internet
Author: User


This article implements a function page similar to the MI gesture remote control through an example.

As shown below:






The response of the touch event is performed through the touch practice monitoring of the system.

The collection of points is cached and parsed through an array.


-(void) Touchesbegan: (Nsset *) touches withevent: (uievent *) event{    if (!self.allowsinteraction) return;    Uitouch *touch = [touches anyobject];    Cgpoint start = [Touch LocationInView:self.view];        [_gesturemanager Beginmonitorwithpoint:start];    [Self showlightatpoint:start];        NSLog (@ "touch Begin");} -(void) touchesmoved: (Nsset *) touches withevent: (uievent *) event{    if (!self.allowsinteraction) return;        Uitouch *touch = [touches anyobject];    Cgpoint point = [Touch LocationInView:self.view];        __weak typeof (&*self) weakself = self;    [_gesturemanager updatemonitorwithpoint:point action:^{        [weakself showlightatpoint:point];    }];}

When touch starts and moves, a class is used to trigger and manage gestures-related methods and other behaviors. That is, the member _gesturemanager.


-(void) Beginmonitorwithpoint: (cgpoint) point{    [self addpoint:point];} -(void) Updatemonitorwithpoint: (cgpoint) Point action: (dispatch_block_t) actionblock{    _curtime++;    int delta = (int) (_curtime-_lastspawntime);        if (Delta >= time_gap) {        if (actionblock) {            actionblock ();        }                _lastspawntime = _curtime;        [Self addpoint:point];}    }

After starting to listen, we do not need to transfer each point of the system to trigger the map display point trajectory, so set up a member to set the gap bit, has reached the intensity of the point control.

-(void) endmonitor{    _curtime = 0;    _lastspawntime = 0;    [Self pathanalysis];    [Self.pointpath removeallobjects];}


At the end of the touch, the members were reset, the gestures were analyzed, and the point groups were emptied.

The following is the beginning of the analysis gesture, the analysis of the idea is relatively simple.

Calculates the difference between the starting and ending points, analyzes the x, Y, determines the direction, and then determines if there is any prominence (return, function, etc.)


-(void) pathanalysis{int count = Self.pointPath.count;        NSLog (@ "points count:%d", count);    if (Count > Judge_contain) {goto sendnone;    } else if (count = = 1) {[Self Senddelegateresult:monitorresulttypechosen];        } else {Cgpoint start = ValueToPoint ([Self.pointpath firstobject]);        Cgpoint end = ValueToPoint ([Self.pointpath lastobject]);        int deltax = Psub (start, end). x;                int deltay = Psub (start, end). Y;        int midindex = COUNT/2;                Cgpoint mid = ValueToPoint (Self.pointpath[midindex]); if (ABS (deltax) > judge_x && abs (DeltaY) < judge_y) {//Horizontal direction if (Del Tax < 0) {//right direction if (![                Self checkisalwayscorrectdirection:monitorresulttyperight start:0 end:self.pointpath.count-1]) goto SendNone; if (Psub (Start, mid). Y > Judge_y/2) {if ([self checktrackismenu]) [Self senddelegateresult:mOnitorresulttypemenu];                else Goto Sendnone;                } else if (ABS (Psub (Start, mid), y) < judge_y) {[Self senddelegateresult:monitorresulttyperight];            } else goto Sendnone; } else {//left if (![                                Self checkisalwayscorrectdirection:monitorresulttypeleft start:0 end:self.pointpath.count-1]) goto SendNone;                        if (Psub (Start, mid). Y > Judge_y/2) {if ([self checktrackismenu]) {                    [Self senddelegateresult:monitorresulttypemenu];                } else goto Sendnone;                } else if (ABS (Psub (Start, mid), y) < judge_y) {[Self senddelegateresult:monitorresulttypeleft];                            } else goto Sendnone;                        }} else if (ABS (DeltaX) < judge_x && ABS (DeltaY) > Judge_y) {//Vertical direction              if (DeltaY < 0) {//Down  if (![                Self checkisalwayscorrectdirection:monitorresulttypedownwards start:0 end:self.pointpath.count-1]) goto SendNone; if (Psub (Start, mid). x > Judge_x/2) {if ([self checktrackisback]) [Self Senddelegateresult:                    Monitorresulttypeback];                else Goto Sendnone; } else if (ABS (Psub (Start, mid). x) < judge_x) {[Self senddelegateresult:monitorresulttypedownwards]                ;            } else goto Sendnone; } else {//up if (![                Self checkisalwayscorrectdirection:monitorresulttypeupwards start:0 end:self.pointpath.count-1]) goto SendNone;                if (ABS (Psub (Start, mid), X) < judge_x) [self senddelegateresult:monitorresulttypeupwards];            else Goto Sendnone;    }} else goto Sendnone;    } return;    Sendnone: [Self senddelegateresult:monitorresulttypenone]; return;}

There are some functions that need to be used

Uikit_static_inline Uiimageview * Quickimageview (NSString * imgname) {    Uiimageview *iv = [[Uiimageview alloc] InitWit Himage:imagecache (imgname)];    return IV;} Uikit_static_inline cgpoint psub (Cgpoint A, cgpoint b) {    return Cgpointmake (a.x-b.x, a.y-b.y);} Uikit_static_inline Nsvalue * Pointtovalue (Cgpoint a) {    return [Nsvalue valuewithcgpoint:a];} Uikit_static_inline cgpoint valuetopoint (Nsvalue *v) {    return [v Cgpointvalue];}

Because these function calls are relatively high in frequency, they are declared as inline static.


The methods that verify whether a direction or not are highlighted are as follows:

-(BOOL) Checkisalwayscorrectdirection: (monitorresulttype) direct start: (int) Start end: (int) end{Pathlogicblock block    ;  Switch (direct) {case Monitorresulttyperight: {block = ^ (Cgpoint v) {BOOL ret = (v.x >= 0)?                No:yes;            return ret;        };        } break; Case Monitorresulttypeleft: {block = ^ (Cgpoint v) {BOOL ret = (v.x <= 0)?                No:yes;            return ret;        };        } break; Case Monitorresulttypeupwards: {block = ^ (Cgpoint v) {BOOL ret = (v.y <= 0)?                No:yes;            return ret;        };        } break; Case Monitorresulttypedownwards: {block = ^ (Cgpoint v) {BOOL ret = (v.y >= 0)?                No:yes;            return ret;        };        } break;            Default: {return NO;}    Break } for (int i = start; I+point_gap < end;        i + = point_gap) {cgpoint s = valuetopoint (Self.pointpath[i]);                Cgpoint e = ValueToPoint (Self.pointpath[i+point_gap]);                Cgpoint d = psub (S, e);    if (!block (d)) {return NO;} } return YES;

The condition is set by the block and then checked and the bool value is returned in the traversal.


Others also use traversal to make judgments, most of which are within a single traversal. For example, check whether pop-up menu gestures or return gestures.

-(BOOL) checktrackismenu{    int start = 0;    int end = Self.pointpath.count-1;    BOOL flag = NO;            while (ValueToPoint (Self.pointpath[start]). Y >= ValueToPoint (self.pointpath[start+1]). Y) {start++;}    while (ValueToPoint (Self.pointpath[end]). Y >= ValueToPoint (self.pointpath[end-1]). Y) {end--;}        if (ABS (Start-end) < 2*point_gap) {flag = YES;}        return flag;} -(BOOL) checktrackisback{    int start = 0;    int end = Self.pointpath.count-1;    BOOL flag = NO;        while (ValueToPoint (Self.pointpath[start]). x >= ValueToPoint (self.pointpath[start+1]). x) {start++;}    while (ValueToPoint (Self.pointpath[end]). x >= ValueToPoint (Self.pointpath[end-1]). x) {end--;}        if (ABS (Start-end) < 2*point_gap) {flag = YES;}        return flag;}


In the aspect of picture display, I have preloaded the picture I want to use after the controller has been loaded.

-(void) loadgesturemanager{_gesturemanager = [Migesturemanager Sharedmanager];    _gesturemanager.delegate = self; [_gesturemanager preloadresources];}  Gesture Manager method-(void) preloadresources{for (int i = 0; i < Initial_count; i++) {Uiimageview *iv =        Quickimageview (Pointimage);    [Self.imageset Addobject:iv];    } _upimageview = Quickimageview (upwardsimage);    _downimageview = Quickimageview (downwardsimage);    _leftimageview = Quickimageview (leftimage);    _rightimageview = Quickimageview (rightimage);    _homeimageview = Quickimageview (homeimage);    _backimageview = Quickimageview (backimage);    _menuimageview = Quickimageview (menuimage);        _chosenimageview = Quickimageview (Chosenimages[0]);    Nsmutablearray *aniarr = [Nsmutablearray array];        for (int i = 0; i < 4; i++) {UIImage *image = Imagecache (Chosenimages[i]);    [Aniarr Addobject:image];    } _chosenimageview.animationimages = Aniarr; _choseNimageview.animationduration = 0.7; _chosenimageview.animationrepeatcount = 1;}

View hierarchy Issues:


We look at the effect of the Millet remote control is all under a grid, here is the view of the display point trajectory overlay a layer of grid view, to achieve that effect.


Source code Address: Rannie/miremotecontrol


Of course, there are a lot of problems to be solved in this project, also mentioned in the project readme.md:


1. The collection of points is maintained by the nsmutablearray of the system itself, and due to the inability to keep the structure, it is necessary to continue the packet unpacking action as follows:

Static inline Nsvalue * Pointtovalue (Cgpoint a) {
return [Nsvalue valuewithcgpoint:a];
}

Static inline Cgpoint valuetopoint (Nsvalue *v) {
return [v Cgpointvalue];
}
You can maintain point order collections by implementing your own data structures.


2. Stickers use Uiimageview, which can be implemented by using a lightweight layer to set the content.


3. The monitor is the touch event in the controller, or you can listen to the Uitouch through the subclass Uigesturerecognizer, you need to import a Uigesturerecognizer sub-class header file to listen to the touch event. The using Uigesturerecognizer with Swift Tutorial can be seen in detail


4. The path analysis of the point is relatively simple, if the statistics have a better analytical formula.



The above is the entire content of this blog, welcome to correct and comment.

Gesture monitoring and UI implementation for iOS Xiaomi remote control

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.