Android開(kāi)發(fā)之響應(yīng)觸摸事件
讓對(duì)象按預(yù)設(shè)程序進(jìn)行移動(dòng)確實(shí)可以吸引一些注意,比如旋轉(zhuǎn)三角形。但如果你想用OpenGL ES制圖實(shí)現(xiàn)用戶交互,又該怎么做呢?讓你的OpenGL ES應(yīng)用具有觸摸交互的關(guān)鍵在于擴(kuò)展對(duì) GLSurfaceView 類的實(shí)現(xiàn),重寫 onTouchEvent() 來(lái)監(jiān)聽(tīng)觸摸事件。
本文主要向你展示如何監(jiān)聽(tīng)觸摸事件,從而讓用戶來(lái)旋轉(zhuǎn)一個(gè)OpenGL ES對(duì)象。
建立一個(gè)觸摸監(jiān)聽(tīng)器 - Setup a Touch Listener
為了讓你的OpenGL ES應(yīng)用程序?qū)τ|摸事件做出響應(yīng),你需要實(shí)現(xiàn) GLSurfaceView 類的 onTouchEvent() 方法。下面的一個(gè)實(shí)現(xiàn)的例子演示了如何監(jiān)聽(tīng) MotionEvent.ACTION_MOVE 事件,并把他們轉(zhuǎn)換成圖形旋轉(zhuǎn)的一個(gè)角度。
- @Override
- public boolean onTouchEvent(MotionEvent e) {
- // MotionEvent提供了觸摸的輸入的細(xì)節(jié)以及其他輸入控制信息。
- //在這種情況下,你只需要關(guān)心觸摸位置改變的事件。
- float x = e.getX();
- float y = e.getY();
- switch (e.getAction()) {
- case MotionEvent.ACTION_MOVE:
- float dx = x - mPreviousX;
- float dy = y - mPreviousY;
- //在中線上反向旋轉(zhuǎn)
- if (y > getHeight() / 2) {
- dx = dx * -1 ;
- }
- //反向旋轉(zhuǎn)至中線左側(cè)
- if (x < getWidth() / 2) {
- dy = dy * -1 ;
- }
- mRenderer.mAngle +180.0f / 320
- requestRender();
- }
- mPreviousX = x;
- mPreviousY = y;
- return true;
- }
需要注意的是,計(jì)算好旋轉(zhuǎn)角度后,這個(gè)方法調(diào)用了 requestRender() 來(lái)通知渲染器渲染畫(huà)面。由于這個(gè)畫(huà)面在沒(méi)有旋轉(zhuǎn)的變化時(shí)無(wú)需重繪,因此在本例中使用這種做法最高效。然而,如果你沒(méi)有用 setRenderMode() 方法請(qǐng)求渲染器僅在數(shù)據(jù)改變時(shí)才重繪,那么這種做法就不會(huì)對(duì)效率有影響了。因此,確保取消掉渲染器里對(duì)這一行代碼的注釋。
- public MyGLSurfaceView(Context context) {
- ...
- //僅當(dāng)繪圖數(shù)據(jù)改變時(shí)繪制視圖
- setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
- }
顯示旋轉(zhuǎn)的角度 - Expose the Rotation Angle
上面的示例代碼需要你在渲染器中添加一個(gè)公共成員來(lái)顯示旋轉(zhuǎn)角度。由于渲染器的代碼所運(yùn)行的線程獨(dú)立于應(yīng)用程序的用戶界面主線程之外,因此,你必須將這個(gè)公共變量聲明為 volatile。參見(jiàn)下面的代碼:
- public class MyGLRenderer implements GLSurfaceView.Renderer {
- ...
- public volatile float mAngle;
應(yīng)用旋轉(zhuǎn) - Apply Rotation
要讓觸摸輸入產(chǎn)生旋轉(zhuǎn),就需要注釋掉生成角度的代碼,改用觸摸輸入生成的角度 mAngle:
- public void onDrawFrame(GL10 gl) {
- ...
- //為三角形創(chuàng)建旋轉(zhuǎn)
- // long time = SystemClock.uptimeMillis() % 4000L;
- // float angle = 0.090f * ((int) time);
- Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, -1.0f);
- //將旋轉(zhuǎn)矩陣與投影和相機(jī)視圖相結(jié)合
- Matrix.multiplyMM(mMVPMatrix, 0, mRotationMatrix, 0, mMVPMatrix, 0);
- //繪制三角形
- mTriangle.draw(mMVPMatrix);
- }
當(dāng)你完成了以上步驟,運(yùn)行程序,就可以在屏幕上拖動(dòng)來(lái)旋轉(zhuǎn)那個(gè)三角形了。
圖1.三角形在觸摸下旋轉(zhuǎn)(圓圈表示觸摸位置)