android ndk queue,Android NDK处理用户交互事件

在 Android_main(struct android_app* state)函数里面设置输入事件处理函数:state->onInputEvent = &handleInput;//设置输入事件的处理函数,如触摸响应

函数介绍:

AMotionEvent_getX():以屏幕左上角为原点,是绝对坐标

AMotionEvent_getY():以屏幕左上角为原点,是绝对坐标

AMotionEvent_getPointerCount();多点触摸函数,返回触摸的点数量,跟硬件有关系

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "native-activity", __VA_ARGS__))

#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))

/**

* Our saved state data.

*/

struct saved_state {

float angle;

int32_t x;

int32_t y;

};

/**

* Shared state for our app.

*/

struct engine {

struct android_app* app;

ASensorManager* sensorManager;

const ASensor* accelerometerSensor;

ASensorEventQueue* sensorEventQueue;

int        animating;

EGLDisplay    display;

EGLSurface    surface;

EGLContext    context;

int32_t    width;

int32_t    height;

struct saved_state state;

};

class float3

{

public:

float x,y,z;

};

std::vector g_arVertex;

/**

* Initialize an EGL context for the current display.

*/

static int engine_init_display(struct engine* engine) {

// initialize OpenGL ES and EGL

/*

* Here specify the attributes of the desired configuration.

* Below, we select an EGLConfig with at least 8 bits per color

* component compatible with on-screen windows

*/

const EGLint attribs[] =

{

EGL_SURFACE_TYPE, EGL_WINDOW_BIT,

EGL_BLUE_SIZE, 8,

EGL_GREEN_SIZE, 8,

EGL_RED_SIZE, 8,

EGL_NONE

};

EGLint w, h, dummy, format;

EGLint        numConfigs;

EGLConfig    config;

EGLSurface    surface;

EGLContext    context;

EGLDisplay    display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

eglInitialize(display, 0, 0);

/* Here, the application chooses the configuration it desires. In this

* sample, we have a very simplified selection process, where we pick

* the first EGLConfig that matches our criteria */

eglChooseConfig(display, attribs, &config, 1, &numConfigs);

/* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is

* guaranteed to be accepted by ANativeWindow_setBuffersGeometry().

* As soon as we picked a EGLConfig, we can safely reconfigure the

* ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */

eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);

ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format);

surface = eglCreateWindowSurface(display, config, engine->app->window, NULL);

context = eglCreateContext(display, config, NULL, NULL);

if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {

LOGW("Unable to eglMakeCurrent");

return -1;

}

eglQuerySurface(display, surface, EGL_WIDTH, &w);

eglQuerySurface(display, surface, EGL_HEIGHT, &h);

engine->display    = display;

engine->context    = context;

engine->surface    = surface;

engine->width        = w;

engine->height        = h;

engine->state.angle = 0;

// Initialize GL state.

glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);

glEnable(GL_CULL_FACE);

glShadeModel(GL_SMOOTH);

glDisable(GL_DEPTH_TEST);

glViewport(0,0,w,h);

glOrthof(0,w,h,0,-100,100);

return 0;

}

/**

* Just the current frame in the display.

*/

static void engine_draw_frame(struct engine* engine) {

if (engine->display == NULL) {

// No display.

return;

}

// Just fill the screen with a color.

glClearColor(((float)engine->state.x)/engine->width, engine->state.angle,

((float)engine->state.y)/engine->height, 1);

glClear(GL_COLOR_BUFFER_BIT);

glEnableClientState(GL_VERTEX_ARRAY);

if(g_arVertex.size() >= 2)

{

glColor4f(1,1,1,1);

glVertexPointer(3,GL_FLOAT,0,&g_arVertex[0]);

glDrawArrays(GL_LINE_STRIP,0,g_arVertex.size());

}

eglSwapBuffers(engine->display, engine->surface);

}

/**

* Tear down the EGL context currently associated with the display.

*/

static void engine_term_display(struct engine* engine) {

if (engine->display != EGL_NO_DISPLAY) {

eglMakeCurrent(engine->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);

if (engine->context != EGL_NO_CONTEXT) {

eglDestroyContext(engine->display, engine->context);

}

if (engine->surface != EGL_NO_SURFACE) {

eglDestroySurface(engine->display, engine->surface);

}

eglTerminate(engine->display);

}

engine->animating = 0;

engine->display = EGL_NO_DISPLAY;

engine->context = EGL_NO_CONTEXT;

engine->surface = EGL_NO_SURFACE;

}

/**

* Process the next input event.

*/

static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)

{

struct engine* engine = (struct engine*)app->userData;

int32_t    evtType    =    AInputEvent_getType(event);

switch(evtType)

{

case AINPUT_EVENT_TYPE_KEY:

break;

case AINPUT_EVENT_TYPE_MOTION:

{

switch(AInputEvent_getSource(event))

{

case AINPUT_SOURCE_TOUCHSCREEN:

{

int32_t id = AMotionEvent_getAction(event);

switch(id)

{

case AMOTION_EVENT_ACTION_MOVE:

{

size_t    cnt = AMotionEvent_getPointerCount(event);

for( int i = 0 ;i < cnt; ++ i )

{

float x = AMotionEvent_getX(event,i);

float y = AMotionEvent_getY(event,i);

char  szBuf[64];

LOGI("x = %f  y = %f",x,y);

float3 pt;

pt.x = x;

pt.y = y;

pt.z = 0;

g_arVertex.push_back(pt);

}

}

break;

case AMOTION_EVENT_ACTION_DOWN:

{

float x = AMotionEvent_getX(event,0);

float y = AMotionEvent_getY(event,0);

char  szBuf[64];

LOGI("x = %f  y = %f",x,y);

float3 pt;

pt.x = x;

pt.y = y;

pt.z = 0;

g_arVertex.push_back(pt);

}

break;

case AMOTION_EVENT_ACTION_UP:

break;

}

}

break;

case AINPUT_SOURCE_TRACKBALL:

break;

}

}

break;

}

if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION)

{

engine->animating = 1;

engine->state.x = AMotionEvent_getX(event, 0);

engine->state.y = AMotionEvent_getY(event, 0);

return 1;

}

return 0;

}

/**

* Process the next main command.

*/

static void engine_handle_cmd(struct android_app* app, int32_t cmd) {

struct engine* engine = (struct engine*)app->userData;

switch (cmd) {

case APP_CMD_SAVE_STATE:

break;

case APP_CMD_INIT_WINDOW:

// The window is being shown, get it ready.

if (engine->app->window != NULL) {

engine_init_display(engine);

}

break;

case APP_CMD_TERM_WINDOW:

// The window is being hidden or closed, clean it up.

engine_term_display(engine);

break;

case APP_CMD_GAINED_FOCUS:

break;

case APP_CMD_LOST_FOCUS:

break;

}

}

/**

* This is the main entry point of a native application that is using

* android_native_app_glue.  It runs in its own thread, with its own

* event loop for receiving input events and doing other things.

*/

void android_main(struct android_app* state) {

struct engine engine;

// Make sure glue isn't stripped.

app_dummy();

memset(&engine, 0, sizeof(engine));

state->userData = &engine;

state->onAppCmd = engine_handle_cmd;

state->onInputEvent = engine_handle_input;

engine.app = state;

// Prepare to monitor accelerometer

engine.sensorManager = ASensorManager_getInstance();

engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,

ASENSOR_TYPE_ACCELEROMETER);

if (state->savedState != NULL) {

// We are starting with a previous saved state; restore from it.

engine.state = *(struct saved_state*)state->savedState;

}

int ident, events;

struct android_poll_source* source;

while (true)

{

while ((ident = ALooper_pollAll(0, NULL, &events, (void**)&source)) >= 0)

{

if (source != NULL)

source->process(state, source);

if (state->destroyRequested != 0)

return;

}

engine_draw_frame(&engine);

}

}

效果如图所示。

7ee400a32c7c50993f18bf4541d45535.png

0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值