当前位置: 首页 > news >正文

触摸屏手指滑动方向检测

参考:移动应用滑动屏幕方向判断解决方案

 底层芯片驱动就不写了,每款芯片的寄存器不一样,可是最终要获取的东西都是一样的--触摸坐标。

底层芯片驱动提供能返回触摸坐标的接口就行。

中间层触摸检测的思路是:

1、判断是否有手指触点,当手指触点>=1,进入有手指触点处理,否则进入无手指触点处理;

2、有手指触点处理:首先判断当前触点与上一个触点是否在误差范围内(#define TP_ERR_RANGE 20);

a、在误差范围内并且在防抖时间之外,则确认为手指按下状态;

b、不在误差范围内并且在防抖时间之外,如果上一状态为手指按下状态,则为手指滑动ing状态;否则不做处理,使相应变量及状态复位;

3、无手指触点处理:在有手指触点处理进入到无手指触点处理的第一次为手指松开状态处理;

a、手指松开的坐标与手指按下时的坐标在在误差范围内,确认为手指松开状态;

b、手指松开的坐标与手指按下时的坐标在在误差范围内,确认为手指滑动状态;

最终通过接口返回给应用层4种状态:手指按下,手指松开,手指滑动中,手指滑动。

 

滑动方向检测的核心在于方向的判断:

#include "math.h"

#define PI                3.1415926f


//返回角度
float GetSlideAngle(int dx, int dy) 
{
/*
atan2()接受两个参数x和y:

angel=Math.atan2(y,x)
x 指定两个点横坐标的差
y 指定两个点纵坐标的差

计算出来的结果angel是一个弧度值,要换算成角度,也必须乘以180/PI。
*/
    return(atan2(dy, dx) * 180 / PI);
}

//根据起点和终点返回方向 1:向上,2:向下,3:向左,4:向右, 0:未滑动
MMP_UBYTE GetSlideDirection(MMP_USHORT startX, MMP_USHORT startY, MMP_USHORT endX, MMP_USHORT endY) 
{
    MMP_UBYTE result = TP_SlideDirection_NONE;
    int dy = startY - endY;
    int dx = endX - startX; 
    float angle;
 
    //如果滑动距离太短
    if (abs(dx) < 2 && abs(dy) < 2) 
    {
        return result;
    }
 
    angle = GetSlideAngle(dx, dy);
    if (angle >= -45 && angle < 45) 
    {
        result = TP_SlideDirection_RIGHT;// 4;
    } else if (angle >= 45 && angle < 135) 
    {
        result = TP_SlideDirection_UP;// 1;
    } else if (angle >= -135 && angle < -45) 
    {
        result = TP_SlideDirection_DOWN;// 2;
    }
    else if ((angle >= 135 && angle <= 180) || (angle >= -180 && angle < -135)) 
    {
        result = TP_SlideDirection_LEFT;// 3;
    }
 
    return result;
}

注意:没有 #include "math.h" 也能编译通过,却不能产生正确的结果。

 

TouchPanel.c

#include "math.h"


#define PI                3.1415926f

#define TP_ERR_RANGE    20 //误差范围 

STPBUTTON TPButton = {TOUCH_PANEL_PRESS, TOUCH_PANEL_REL, 0, 15, KEYPAD_NONE, 0, 0, 0, 0, TP_ERR_RANGE, "TouchPanel"};



//返回角度
float GetSlideAngle(int dx, int dy) 
{
/*
atan2()接受两个参数x和y:

angel=Math.atan2(y,x)
x 指定两个点横坐标的差
y 指定两个点纵坐标的差

计算出来的结果angel是一个弧度值,要换算成角度,也必须乘以180/PI。
*/
    return(atan2(dy, dx) * 180 / PI);
}

//根据起点和终点返回方向 1:向上,2:向下,3:向左,4:向右, 0:未滑动
MMP_UBYTE GetSlideDirection(MMP_USHORT startX, MMP_USHORT startY, MMP_USHORT endX, MMP_USHORT endY) 
{
    MMP_UBYTE result = TP_SlideDirection_NONE;
    int dy = startY - endY;
    int dx = endX - startX; 
    float angle;
 
    //如果滑动距离太短
    if (abs(dx) < 2 && abs(dy) < 2) 
    {
        return result;
    }
 
    angle = GetSlideAngle(dx, dy);
    if (angle >= -45 && angle < 45) 
    {
        result = TP_SlideDirection_RIGHT;// 4;
    } else if (angle >= 45 && angle < 135) 
    {
        result = TP_SlideDirection_UP;// 1;
    } else if (angle >= -135 && angle < -45) 
    {
        result = TP_SlideDirection_DOWN;// 2;
    }
    else if ((angle >= 135 && angle <= 180) || (angle >= -180 && angle < -135)) 
    {
        result = TP_SlideDirection_LEFT;// 3;
    }
 
    return result;
}

AHC_BOOL AHC_TouchPanel_CheckUpdate(MMP_ULONG* pulKeyEvent, MMP_ULONG* pulPosition, MMP_UBYTE dir, MMP_UBYTE* finger, MMP_UBYTE* pucSlideDirection)
{
    MMP_ERR status = MMP_ERR_NONE;
    static MMP_ULONG ulPosition = 0;
    MMP_ULONG ulNow;  
    
    if (*pulKeyEvent == TOUCH_PANEL_PRESS   ||
        *pulKeyEvent == TOUCH_PANEL_REL     ||
        *pulKeyEvent == TOUCH_PANEL_MOVE)
    {
        // Read position
        MMP_USHORT uwX = 0;
        MMP_USHORT uwY = 0;
        UINT16 x1, y1;//last pos
        UINT16 x2, y2;//now pos
        
        *finger = AHC_TouchPanel_ReadPosition(&uwX, &uwY, dir);

        *pulKeyEvent = KEYPAD_NONE;
        
        MMPF_OS_GetTime(&ulNow);
        
        if (*finger != 0)
        {
            x1 = TPButton.uwLastPosX;
            y1 = TPButton.uwLastPosY;
            x2 = uwX;
            y2 = uwY;

            if ((((x2 <= x1) && (x1 < x2 + TPButton.uwErrRange)) || ((x1 <= x2) && (x2 < x1 + TPButton.uwErrRange))) && \
                (((y2 <= y1) && (y1 < y2 + TPButton.uwErrRange)) || ((y1 <= y2) && (y2 < y1 + TPButton.uwErrRange))))    
               {    //前后两次采样在+-20内
                if (ulNow - TPButton.ulKeyLastTime > TPButton.ulDebounceTime)
                {
                    if (TPButton.ulKeyLastEvent == KEYPAD_NONE)
                    {
                        *pulKeyEvent = TOUCH_PANEL_PRESS;
                        TPButton.ulKeyLastEvent = *pulKeyEvent;
                        
                        TPButton.uwPressPosX = (x1 + x2) >> 1;
                        TPButton.uwPressPosY = (y1 + y2) >> 1;

                        printc("--Harry-- PRESS: xPos = %d, yPos = %d --1\r\n", TPButton.uwPressPosX, TPButton.uwPressPosY);
                    }

                    TPButton.uwLastPosX = x2;
                    TPButton.uwLastPosY = y2;                    

                    TPButton.ulKeyLastTime = ulNow;
                }
               }
               else
               {    //前后两次采样大于+-20
                if ((ulNow - TPButton.ulKeyLastTime) > (TPButton.ulDebounceTime >> 1))
                {
                    //printc("--Harry-- MOVE: xPos = %d, yPos = %d --2\r\n", uwX, uwY);
                    if (TPButton.ulKeyLastEvent == TOUCH_PANEL_PRESS)
                    {        
                    #if 0//Moveing
                        x1 = TPButton.uwPressPosX;
                        y1 = TPButton.uwPressPosY;

                        if ((x1 > (x2 + TPButton.uwErrRange * 2)) || (x2 > (x1 + TPButton.uwErrRange * 2)) || \
                            (y1 > (y2 + TPButton.uwErrRange * 2)) || (y2 > (y1 + TPButton.uwErrRange * 2)))
                           {
                            *pulKeyEvent = TOUCH_PANEL_MOVE;
                            TPButton.ulKeyLastEvent = *pulKeyEvent;

                            TPButton.uwPressPosX = (x1 + x2) >> 1;
                            TPButton.uwPressPosY = (y1 + y2) >> 1;                            
                           }
                    #endif
                    }
                    else
                    {
                        *pulKeyEvent = KEYPAD_NONE;
                        TPButton.ulKeyLastEvent = *pulKeyEvent;

                        TPButton.uwPressPosX = 0;
                        TPButton.uwPressPosY = 0;    
                    }            

                    TPButton.uwLastPosX = x2;
                    TPButton.uwLastPosY = y2;                
                    
                    TPButton.ulKeyLastTime = ulNow;            
                }        
               }
           }
        else
        {    //按键松开
            x1 = TPButton.uwPressPosX;
            y1 = TPButton.uwPressPosY;
            x2 = TPButton.uwLastPosX;
            y2 = TPButton.uwLastPosY;
        
            if (TPButton.ulKeyLastEvent == TOUCH_PANEL_PRESS)
            {
                if ((((x2 <= x1) && (x1 < x2 + TPButton.uwErrRange)) || ((x1 <= x2) && (x2 < x1 + TPButton.uwErrRange))) && \
                    (((y2 <= y1) && (y1 < y2 + TPButton.uwErrRange)) || ((y1 <= y2) && (y2 < y1 + TPButton.uwErrRange))))    
                {    //按下时的点与松开时的点小于容错范围
                    *pulKeyEvent = TOUCH_PANEL_REL;

                    uwX = (x1 + x2) >> 1;
                    uwY = (y1 + y2) >> 1;
                }
                else
                {    //按下时的点与松开时的点大于容错范围
                    *pulKeyEvent = TOUCH_PANEL_MOVE;

                    //printc("--Harry-- MOVE: x1=%d, y1=%d x2=%d, y2=%d --22\r\n", x1, y1, x2, y2);
                    *pucSlideDirection = GetSlideDirection(x1, y1, x2, y2);
                    
                    uwX = x2;
                    uwY = y2;                    
                }
            }
            else
            {
                *pulKeyEvent = KEYPAD_NONE;
            }

            TPButton.uwLastPosX = 0;
            TPButton.uwLastPosY = 0;
            TPButton.uwPressPosX = 0;
            TPButton.uwPressPosY = 0;            
            TPButton.ulKeyLastTime = ulNow;
            TPButton.ulKeyLastEvent = *pulKeyEvent;
        }

        if (*pulKeyEvent != KEYPAD_NONE)
        {
            ulPosition = uwY;
            ulPosition = (ulPosition << 16) + uwX;

            *pulPosition = ulPosition;
            status = AHC_TOUCHPANEL_RET_TRUE;
        }
        else
        {
            *pulPosition = 0;
            status = AHC_TOUCHPANEL_RET_FALSE;
        }

    }
    
    AHC_TOUCHPANEL_CHECK_RETURE_VALUE(status, AHC_TOUCHPANEL_NO_ERROR, AHC_TOUCHPANEL_RET_TRUE, AHC_TOUCHPANEL_RET_FALSE)
}

 

TouchPanel.h

typedef enum
{
    TP_SlideDirection_NONE    = 0,
    TP_SlideDirection_UP,
    TP_SlideDirection_DOWN,
    TP_SlideDirection_LEFT,
    TP_SlideDirection_RIGHT
    
} TP_SlideDirection_Enum;

/* For Touch Panel Button */
typedef struct tagTPButton
{
    int            iPressId;
    int            iReleaseId;
    unsigned int   ulKeyLastTime;
    unsigned int   ulDebounceTime;
    unsigned int   ulKeyLastEvent;
    unsigned short uwLastPosX;
    unsigned short uwLastPosY;
    unsigned short uwPressPosX;
    unsigned short uwPressPosY;
    unsigned short uwErrRange;
    unsigned char  ubkeyname[16];
} STPBUTTON;

应用层通过接口获取中间层所得的触摸状态做相应事件处理。

typedef struct _TP_Position
{
    unsigned short xPos;
    unsigned short yPos;
} TP_Position;

/* For Touch Panel Event */
typedef struct _TouchPanel
{
    TP_Position   PrevPosition;
    TP_Position   CurrPosition;
    unsigned char SlideDirection;
    void (*PressEvent)(void);
    void (*ReleaseEvent)(void);
    void (*MoveEvent)(void);
} TouchPanelEvent;

static TouchPanelEvent TouchPanel;



static void TouchPanel_PressEvent(void)
{
    printc("--Harry-- %s Line:%d\r\n", __func__, __LINE__);

    TouchPanel.PrevPosition.xPos = TouchPanel.CurrPosition.xPos;
    TouchPanel.PrevPosition.yPos = TouchPanel.CurrPosition.yPos;    
}

static void TouchPanel_ReleaseEvent(void)
{
    printc("--Harry-- %s Line:%d\r\n", __func__, __LINE__);
    

    TouchPanel.PrevPosition.xPos = TouchPanel.CurrPosition.xPos;
    TouchPanel.PrevPosition.yPos = TouchPanel.CurrPosition.yPos;
}

static void TouchPanel_MoveEvent(void)
{
    //printc("--Harry-- %s Line:%d\r\n", __func__, __LINE__);
    
}

static void TouchPanelEventInit(void)
{
    TouchPanel.PrevPosition.xPos = 0;
    TouchPanel.PrevPosition.yPos = 0;
    TouchPanel.CurrPosition.xPos = 0;
    TouchPanel.CurrPosition.yPos = 0;
    TouchPanel.SlideDirection = 0;
    TouchPanel.PressEvent = TouchPanel_PressEvent;
    TouchPanel.ReleaseEvent = TouchPanel_ReleaseEvent;
    TouchPanel.MoveEvent = TouchPanel_MoveEvent;
}

void UIKeyTask(void)
{
    MMP_ULONG      ulKeyEvent;
    MMPF_OS_FLAGS  flags;
    MMPF_OS_FLAGS  waitflags;
    MMP_ULONG      ulNow;
    MMP_ULONG      ulPosition;

#if (KEYPAD_DETECT_METHOD == KEYPAD_DETECT_TASK)
    UITaskReady = MMP_TRUE;
#endif

#if (TASK_MONITOR_ENABLE)
    memcpy(&gsTaskMonitorUIKey.TaskName[0], __func__, TASK_MONITOR_MAXTASKNAMELEN);
    gsTaskMonitorUIKey.sTaskMonitorStates = MMPF_TASK_MONITOR_STATES_WAITING;
    gsTaskMonitorUIKey.ulExecTime = 0;
    memset((void *)gsTaskMonitorUIKey.ParaArray, 0x0, sizeof(gsTaskMonitorUIKey.ParaArray)); 
    gsTaskMonitorUIKey.ulParaLength = 0;    
    gsTaskMonitorUIKey.pTimeoutCB = (TASK_MONITOR_TimeoutCallback *)NULL;       
    MMPF_TaskMonitor_RegisterTask(&gsTaskMonitorUIKey);
#endif

    waitflags = CDV_KEYPAD_FLAG | CDV_TIME_FLAG;
#if (UPDATE_UI_USE_MULTI_TASK)
    waitflags |= CDV_UI_FLAG;
#endif

#if (SUPPORT_TOUCH_PANEL)
    TouchPanelEventInit();
#endif
    
    while(1){
        MMPF_OS_WaitFlags(CDV_UI_Flag, waitflags, MMPF_OS_FLAG_WAIT_SET_ANY|MMPF_OS_FLAG_CONSUME, 0, &flags);

    #if (TASK_MONITOR_ENABLE)
        MMPF_OS_GetTime(&gsTaskMonitorUIKey.ulExecTime);
        gsTaskMonitorUIKey.sTaskMonitorStates = MMPF_TASK_MONITOR_STATES_RUNNING;    
        *(MMP_ULONG *)(gsTaskMonitorUIKey.ParaArray) = (MMP_ULONG)flags;
        gsTaskMonitorUIKey.ulParaLength = sizeof(MMP_ULONG); 
    #endif

        if (flags & CDV_TIME_FLAG) {
            // The KeyTask priority is higher then NETWORK to update Video Time Stamp for better performance.
            UpdateVideoCurrentTimeStamp();
        }

    #if (UPDATE_UI_USE_MULTI_TASK)
        if (flags & CDV_UI_FLAG) {
            DrawStateVideoRecUpdate(EVENT_VIDREC_UPDATE_MESSAGE);
        }        
    #endif

        if (flags & CDV_KEYPAD_FLAG) {
            MMPF_OS_GetTime(&ulNow);

            GetKeyPadEvent(&ulKeyEvent);

        #if (SUPPORT_TOUCH_PANEL)
            if ((ulKeyEvent == TOUCH_PANEL_PRESS) || (ulKeyEvent == TOUCH_PANEL_REL))
            {
                UINT32 dir;
                MMP_UBYTE finger;
                MMP_ERR status;
                MMP_UBYTE slide = 0;

                AHC_GetParam(PARAM_ID_LCD_STATUS, &dir);
                status = AHC_TouchPanel_CheckUpdate(&ulKeyEvent, &ulPosition, dir, &finger, &slide);

                if (ulKeyEvent != KEYPAD_NONE) 
                {            
                    if (ulKeyEvent == TOUCH_PANEL_PRESS)
                    {
                        TouchPanel.CurrPosition.xPos = ulPosition & 0x0000FFFF;
                        TouchPanel.CurrPosition.yPos = ulPosition >> 16;    
                    
                        TouchPanel.PressEvent();
                    }
                    else if (ulKeyEvent == TOUCH_PANEL_REL)
                    {                        
                        TouchPanel.CurrPosition.xPos = ulPosition & 0x0000FFFF;
                        TouchPanel.CurrPosition.yPos = ulPosition >> 16;
                        
                        TouchPanel.ReleaseEvent();
                    }
                    else if (ulKeyEvent == TOUCH_PANEL_MOVE)
                    {
                        TouchPanel.CurrPosition.xPos = ulPosition & 0x0000FFFF;
                        TouchPanel.CurrPosition.yPos = ulPosition >> 16;

                        TouchPanel.SlideDirection = slide;
                        
                        TouchPanel.MoveEvent();                        
                    }
                    ulKeyEvent = KEYPAD_NONE;
                } 
            }
        #endif

            if (ulKeyEvent != KEYPAD_NONE) {
                AHC_SendAHLMessage(AHLM_GPIO_BUTTON_NOTIFICATION, ulKeyEvent, ulNow);
            }
        }

#if (TASK_MONITOR_ENABLE)
        gsTaskMonitorUIKey.sTaskMonitorStates = MMPF_TASK_MONITOR_STATES_WAITING;
#endif
    }
}

 注意:TouchPanel 事件在调用前必须先初始化 TouchPanelEventInit();

相关文章:

  • jQuery EasyUI快速入门实战教程(一)-入门
  • oracle业务硬盘出现故障无法访问,提示需要重新格式化后解决方法
  • 阿里云,为寄递业务探索创新升级
  • SkinSB皮肤滚动条库的一个帮助头文件
  • xmanager运行报错:bash: /usr/bin/xterm: No such file or directory
  • Android 音视频开发入门指南
  • 8.html表格相关的标记9.html表格实战《简单的网页布局》
  • 如何添加mysql到环境变量
  • 24、C#:按钮的属性和事件
  • c++ 软件下载 Dev cpp下载
  • 字符流、字节流、二进制及其在HTTP协议传输
  • Rxjs基础--Subject
  • Uber 机器学习平台 — 米开朗基罗
  • 使用forever让node.js持久运行
  • 系统安装
  • go语言学习初探(一)
  • HashMap ConcurrentHashMap
  • Median of Two Sorted Arrays
  • mongo索引构建
  • Tornado学习笔记(1)
  • 阿里云应用高可用服务公测发布
  • 服务器之间,相同帐号,实现免密钥登录
  • 面试遇到的一些题
  • 那些被忽略的 JavaScript 数组方法细节
  • 实战:基于Spring Boot快速开发RESTful风格API接口
  • 数据库写操作弃用“SELECT ... FOR UPDATE”解决方案
  • 通过git安装npm私有模块
  • 做一名精致的JavaScripter 01:JavaScript简介
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • JavaScript 新语法详解:Class 的私有属性与私有方法 ...
  • shell使用lftp连接ftp和sftp,并可以指定私钥
  • 微龛半导体获数千万Pre-A轮融资,投资方为国中创投 ...
  • 选择阿里云数据库HBase版十大理由
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • (BFS)hdoj2377-Bus Pass
  • (c语言版)滑动窗口 给定一个字符串,只包含字母和数字,按要求找出字符串中的最长(连续)子串的长度
  • (Matlab)使用竞争神经网络实现数据聚类
  • (办公)springboot配置aop处理请求.
  • (附源码)ssm高校运动会管理系统 毕业设计 020419
  • (利用IDEA+Maven)定制属于自己的jar包
  • (四)c52学习之旅-流水LED灯
  • (新)网络工程师考点串讲与真题详解
  • (转)Linq学习笔记
  • .net core 源码_ASP.NET Core之Identity源码学习
  • .NET Core、DNX、DNU、DNVM、MVC6学习资料
  • .net 反编译_.net反编译的相关问题
  • .Net 中的反射(动态创建类型实例) - Part.4(转自http://www.tracefact.net/CLR-and-Framework/Reflection-Part4.aspx)...
  • .net实现头像缩放截取功能 -----转载自accp教程网
  • @RequestMapping用法详解
  • [ai笔记9] openAI Sora技术文档引用文献汇总
  • [android] 手机卫士黑名单功能(ListView优化)
  • [codevs 1296] 营业额统计
  • [Editor]Unity Editor类常用方法
  • [GXYCTF2019]BabyUpload1 -- 题目分析与详解
  • [HDU5685]Problem A