結合上一節的內容,分享完整代碼。
先畫一個cube,然后通過OnGestureListener去觸發onFling使它旋轉起來。
OnGestureListener相關的方法我已經都加了注釋,可以參考注釋去了解有關的方法是干什么的。
旋轉相關隨便復制了一個,主要說明OnGestureListener。
簡單的觸摸操作會用一些OnTouchListener復雜的還是需要用到OnGestureListener。
Acivity & Render:
import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.egl.EGLConfig; import android.app.Activity; import android.content.Context; import android.opengl.GLSurfaceView; import android.opengl.GLU; import android.os.Bundle; import android.view.GestureDetector; import android.view.GestureDetector.OnGestureListener; import android.view.MotionEvent; import android.view.Window; public class OpenGL extends Activity implements OnGestureListener { // 定義旋轉角度 private float anglex = 0f; private float angley = 0f; static final float ROTATE_FACTOR = 180f; // 定義手勢檢測器實例 GestureDetector detector; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 去標題欄 requestWindowFeature(Window.FEATURE_NO_TITLE); // 創建一個GLSurfaceView,用於顯示OpenGL繪制的圖形 GLSurfaceView glView = new GLSurfaceView(this); // 創建GLSurfaceView的內容繪制器 GLRenderer myRender = new GLRenderer(this); // 為GLSurfaceView設置繪制器 glView.setRenderer(myRender); setContentView(glView); // 創建手勢檢測器 detector = new GestureDetector(this); } @Override public boolean onTouchEvent(MotionEvent event) { // 將該Activity上的觸碰事件交給GestureDetector處理 return detector.onTouchEvent(event); } // 用戶輕觸觸摸屏,由1個MotionEvent ACTION_DOWN觸發 public boolean onDown(MotionEvent e) { // TODO Auto-generated method stub System.out.println("onDown"); return false; } /* * 用戶按下觸摸屏、快速移動后松開,由1個MotionEvent ACTION_DOWN, 多個ACTION_MOVE, * 1個ACTION_UP觸發(non-Javadoc) * Fling事件的處理代碼:除了第一個觸發Fling的ACTION_DOWN和最后一個ACTION_MOVE中包含的坐標等信息外 * ,我們還可以根據用戶在X軸或者Y軸上的移動速度作為條件 * 比如下面的代碼中我們就在用戶移動超過100個像素,且X軸上每秒的移動速度大於200像素時才進行處理。 * * @see android.view.GestureDetector.OnGestureListener#onFling(android.view. * MotionEvent, android.view.MotionEvent, float, float) * 這個例子中,tv.setLongClickable( true )是必須的,因為 * 只有這樣,view才能夠處理不同於Tap(輕觸)的hold(即ACTION_MOVE,或者多個ACTION_DOWN) * ,我們同樣可以通過layout定義中的android:longClickable來做到這一點 */ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { System.out.println("onFling"); // 參數解釋: // e1:第1個ACTION_DOWN MotionEvent // e2:最后一個ACTION_MOVE MotionEvent // velocityX:X軸上的移動速度,像素/秒 // velocityY:Y軸上的移動速度,像素/秒 velocityX = e1.getX() - e2.getX(); velocityY = e1.getY() - e2.getY(); velocityX = velocityX > 4000 ? 4000 : velocityX; velocityX = velocityX < -4000 ? -4000 : velocityX; velocityY = velocityY > 4000 ? 4000 : velocityY; velocityY = velocityY < -4000 ? -4000 : velocityY; // 根據橫向上的速度計算沿Y軸旋轉的角度 angley += -velocityX * ROTATE_FACTOR / 4000; // 根據縱向上的速度計算沿X軸旋轉的角度 anglex += -velocityY * ROTATE_FACTOR / 4000; return true; } // Touch了不移動一直Touch down時觸發 public void onLongPress(MotionEvent arg0) { // TODO Auto-generated method stub System.out.println("onLongPress"); } // 用戶按下觸摸屏,並拖動,由1個MotionEvent ACTION_DOWN, 多個ACTION_MOVE觸發 public boolean onScroll(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // TODO Auto-generated method stub System.out.println("onScroll"); return false; } /* * Touch了還沒有滑動時觸發 (1)onDown只要Touch Down一定立刻觸發 (2)Touch * Down后過一會沒有滑動先觸發onShowPress再觸發onLongPress So: Touch Down后一直不滑動,onDown -> * onShowPress -> onLongPress這個順序觸發。 */ public void onShowPress(MotionEvent arg0) { // TODO Auto-generated method stub System.out.println("onShowPress"); } /* * 兩個函數都是在Touch Down后又沒有滑動(onScroll),又沒有長按(onLongPress),然后Touch Up時觸發 * 點擊一下非常快的(不滑動)Touch Up: onDown->onSingleTapUp->onSingleTapConfirmed * 點擊一下稍微慢點的(不滑動)Touch Up://確認是單擊事件觸發 * onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed */ public boolean onSingleTapUp(MotionEvent arg0) { // TODO Auto-generated method stub System.out.println("onSingleTopUp"); return false; } class GLRenderer implements GLSurfaceView.Renderer { private final Context context; private final GLCube cube = new GLCube(); GLRenderer(Context context) { this.context = context; } public void onSurfaceCreated(GL10 gl, EGLConfig config) { // Define the lighting float lightAmbient[] = new float[] { 0.2f, 0.2f, 0.2f, 1 }; float lightDiffuse[] = new float[] { 1, 1, 1, 1 }; float[] lightPos = new float[] { 1, 1, 1, 1 }; gl.glEnable(GL10.GL_LIGHTING); gl.glEnable(GL10.GL_LIGHT0); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lightAmbient, 0); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightDiffuse, 0); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPos, 0); // What is the cube made of? float matAmbient[] = new float[] { 1, 1, 1, 1 }; float matDiffuse[] = new float[] { 1, 1, 1, 1 }; gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, matAmbient, 0); gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, matDiffuse, 0); // Set up any OpenGL options we need gl.glEnable(GL10.GL_DEPTH_TEST); gl.glDepthFunc(GL10.GL_LEQUAL); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisable(GL10.GL_DEPTH_TEST); gl.glEnable(GL10.GL_BLEND); gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); // Enable textures gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); gl.glEnable(GL10.GL_TEXTURE_2D); // Load the cube's texture from a bitmap GLCube.loadTexture(gl, context, R.drawable.android); } public void onSurfaceChanged(GL10 gl, int width, int height) { // Define the view frustum gl.glViewport(0, 0, width, height); gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); float ratio = (float) width / height; GLU.gluPerspective(gl, 45.0f, ratio, 1, 100f); } public void onDrawFrame(GL10 gl) { // Clear the screen to black gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); // Position model so we can see it gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); gl.glTranslatef(0, 0, -3.0f); gl.glRotatef(angley, 0, 1, 0); gl.glRotatef(anglex, 1, 0, 0); // Draw the model cube.draw(gl); } } }
然后是一個Cube:
import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.IntBuffer; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.opengl.GLUtils; class GLCube { private final IntBuffer mVertexBuffer; private final IntBuffer mTextureBuffer; public GLCube() { int one = 65536; int half = one / 2; int vertices[] = { // FRONT -half, -half, half, half, -half, half, -half, half, half, half, half, half, // BACK -half, -half, -half, -half, half, -half, half, -half, -half, half, half, -half, // LEFT -half, -half, half, -half, half, half, -half, -half, -half, -half, half, -half, // RIGHT half, -half, -half, half, half, -half, half, -half, half, half, half, half, // TOP -half, half, half, half, half, half, -half, half, -half, half, half, -half, // BOTTOM -half, -half, half, -half, -half, -half, half, -half, half, half, -half, -half, }; int texCoords[] = { // FRONT 0, one, one, one, 0, 0, one, 0, // BACK one, one, one, 0, 0, one, 0, 0, // LEFT one, one, one, 0, 0, one, 0, 0, // RIGHT one, one, one, 0, 0, one, 0, 0, // TOP one, 0, 0, 0, one, one, 0, one, // BOTTOM 0, 0, 0, one, one, 0, one, one, }; ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4); vbb.order(ByteOrder.nativeOrder()); mVertexBuffer = vbb.asIntBuffer(); mVertexBuffer.put(vertices); mVertexBuffer.position(0); ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4); tbb.order(ByteOrder.nativeOrder()); mTextureBuffer = tbb.asIntBuffer(); mTextureBuffer.put(texCoords); mTextureBuffer.position(0); } public void draw(GL10 gl) { gl.glVertexPointer(3, GL10.GL_FIXED, 0, mVertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, mTextureBuffer); gl.glColor4f(1, 1, 1, 1); gl.glNormal3f(0, 0, 1); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glNormal3f(0, 0, -1); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4); gl.glColor4f(1, 1, 1, 1); gl.glNormal3f(-1, 0, 0); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4); gl.glNormal3f(1, 0, 0); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4); gl.glColor4f(1, 1, 1, 1); gl.glNormal3f(0, 1, 0); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4); gl.glNormal3f(0, -1, 0); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4); } static void loadTexture(GL10 gl, Context context, int resource) { Bitmap bmp = BitmapFactory.decodeResource( context.getResources(), resource); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0); gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); bmp.recycle(); } }
運行:鼠標滑動屏幕,cube會旋轉。