主要实现的类:

package com.ws.wsvod.opengl;import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;import com.ws.wsvod.converflow.BitmapCanvas;
import com.ws.wsvod.converflow.DataCache;import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.opengl.GLUtils;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.animation.AnimationUtils;public class CoverFlowOpenGL extends GLSurfaceViewimplements GLSurfaceView.Renderer {private static final String TAG = "AnotherCoverFlow";private static final int TOUCH_MINIMUM_MOVE = 5;private static final int IMAGE_SIZE = 128; // the bitmap size we use for the textureprivate static final int MAX_TILES = 48; // the maximum tiles in the cacheprivate static final int VISIBLE_TILES = 3; // the visble tiles left and rightprivate static final float SCALE = 0.5f; // the scale of surface viewprivate static final float SPREAD_IMAGE = 0.24f;private static final float FLANK_SPREAD = 0.20f;private static final float FRICTION = 10.0f;private static final float MAX_SPEED = 6.0f;private static final float[] GVertices = new float[]{-1.0f, -1.0f, 0.0f,1.0f, -1.0f, 0.0f,-1.0f, 1.0f, 0.0f,1.0f, 1.0f, 0.0f,};private static final float[] GTextures = new float[]{0.0f, 1.0f,1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f,};private GL10 mGLContext;private FloatBuffer mVerticesBuffer;private FloatBuffer mTexturesBuffer;private float[] mMatrix;private int mBgTexture;private FloatBuffer mBgVerticesBuffer;private FloatBuffer mBgTexturesBuffer;private int mBgBitmapId;private boolean mInitBackground;private float mOffset;private int mLastOffset;private RectF mTouchRect;private int mWidth;private int mHeight;private boolean mTouchMoved;private float mTouchStartPos;private float mTouchStartX;private float mTouchStartY;private float mStartOffset;private long mStartTime;private float mStartSpeed;private float mDuration;private Runnable mAnimationRunnable;private VelocityTracker mVelocity;private boolean mStopBackgroundThread;private CoverFlowListener mListener;private DataCache<Integer, CoverFlowRecord> mCache;public CoverFlowOpenGL(Context context) {super(context);setEGLConfigChooser(8, 8, 8, 8, 16, 0);setRenderer(this);
//        setRenderMode(RENDERMODE_WHEN_DIRTY);getHolder().setFormat(PixelFormat.TRANSLUCENT);
//        setZOrderMediaOverlay(true);
//        setZOrderOnTop(true);mCache = new DataCache<Integer, CoverFlowRecord>(MAX_TILES);mLastOffset = 0;mOffset = 0;mInitBackground = false;mBgBitmapId = 0;}public void setCoverFlowListener(CoverFlowListener listener) {mListener = listener;}private float checkValid(float off) {int max = mListener.getCount(this) - 1;if (off < 0)return 0;else if (off > max)return max;return off;}public void setSelection(int position) {endAnimation();mOffset = position;requestRender();}@Overridepublic boolean onTouchEvent(MotionEvent event) {int action = event.getAction();switch (action) {case MotionEvent.ACTION_DOWN:touchBegan(event);return true;case MotionEvent.ACTION_MOVE:touchMoved(event);return true;case MotionEvent.ACTION_UP:touchEnded(event);return true;}return false;}private void touchBegan(MotionEvent event) {endAnimation();float x = event.getX();mTouchStartX = x;mTouchStartY = event.getY();mStartTime = System.currentTimeMillis();mStartOffset = mOffset;mTouchMoved = false;mTouchStartPos = (x / mWidth) * 10 - 5;mTouchStartPos /= 2;mVelocity = VelocityTracker.obtain();mVelocity.addMovement(event);}private void touchMoved(MotionEvent event) {float pos = (event.getX() / mWidth) * 10 - 5;pos /= 2;if (!mTouchMoved) {float dx = Math.abs(event.getX() - mTouchStartX);float dy = Math.abs(event.getY() - mTouchStartY);if (dx < TOUCH_MINIMUM_MOVE && dy < TOUCH_MINIMUM_MOVE)return;mTouchMoved = true;}mOffset = checkValid(mStartOffset + mTouchStartPos - pos);requestRender();mVelocity.addMovement(event);}private void touchEnded(MotionEvent event) {float pos = (event.getX() / mWidth) * 10 - 5;pos /= 2;if (mTouchMoved) {mStartOffset += mTouchStartPos - pos;mStartOffset = checkValid(mStartOffset);mOffset = mStartOffset;mVelocity.addMovement(event);mVelocity.computeCurrentVelocity(1000);double speed = mVelocity.getXVelocity();speed = (speed / mWidth) * 10;if (speed > MAX_SPEED)speed = MAX_SPEED;else if (speed < -MAX_SPEED)speed = -MAX_SPEED;startAnimation(-speed);} else {if (mTouchRect.contains(event.getX(), event.getY())) {mListener.topTileClicked(this, (int) (mOffset + 0.01));}}}private void startAnimation(double speed) {if (mAnimationRunnable != null)return;double delta = speed * speed / (FRICTION * 2);if (speed < 0)delta = -delta;double nearest = mStartOffset + delta;nearest = Math.floor(nearest + 0.5);nearest = checkValid((float) nearest);mStartSpeed = (float) Math.sqrt(Math.abs(nearest - mStartOffset) * FRICTION * 2);if (nearest < mStartOffset)mStartSpeed = -mStartSpeed;mDuration = Math.abs(mStartSpeed / FRICTION);mStartTime = AnimationUtils.currentAnimationTimeMillis();mAnimationRunnable = new Runnable() {public void run() {driveAnimation();}};post(mAnimationRunnable);}private void driveAnimation() {float elapsed = (AnimationUtils.currentAnimationTimeMillis() - mStartTime) / 1000.0f;if (elapsed >= mDuration)endAnimation();else {updateAnimationAtElapsed(elapsed);post(mAnimationRunnable);}}private void endAnimation() {if (mAnimationRunnable != null) {mOffset = (float) Math.floor(mOffset + 0.5);mOffset = checkValid(mOffset);requestRender();removeCallbacks(mAnimationRunnable);mAnimationRunnable = null;}}private void updateAnimationAtElapsed(float elapsed) {if (elapsed > mDuration)elapsed = mDuration;float delta = Math.abs(mStartSpeed) * elapsed - FRICTION * elapsed * elapsed / 2;if (mStartSpeed < 0)delta = -delta;mOffset = checkValid(mStartOffset + delta);requestRender();}public void onSurfaceCreated(GL10 gl, EGLConfig config) {mCache.clear();mGLContext = gl;mVerticesBuffer = makeFloatBuffer(GVertices);mTexturesBuffer = makeFloatBuffer(GTextures);Log.d("CoverFlowOpenGL", "onSurfaceCreated");}private GL10 gl;public void onSurfaceChanged(GL10 gl, int w, int h) {/*if (getAnimation() != null)return;*/this.gl = gl;mWidth = w;mHeight = h;float imagew = w * 0.45f / SCALE / 2.0f;float imageh = h * 0.45f / SCALE / 2.0f;mTouchRect = new RectF(w / 2 - imagew, h / 2 - imageh, w / 2 + imagew, h / 2 + imageh);gl.glViewport(0, 0, w, h);float ratio = ((float) w) / h;gl.glMatrixMode(GL10.GL_PROJECTION);gl.glLoadIdentity();gl.glOrthof(-ratio * SCALE, ratio * SCALE, -1 * SCALE, 1 * SCALE, 1, 3);float[] vertices = new float[]{-ratio * SCALE, -SCALE, 0,ratio * SCALE, -SCALE, 0,-ratio * SCALE, SCALE, 0,ratio * SCALE, SCALE, 0};mBgVerticesBuffer = makeFloatBuffer(vertices);Log.d("CoverFlowOpenGL", "onSurfaceChanged");}@Overridepublic void onResume() {super.onResume();Log.d("CoverFlowOpenGL", "onResume");}@Overridepublic void onPause() {super.onPause();Log.d("CoverFlowOpenGL", "onPause");}@Overrideprotected void onDetachedFromWindow() {
//        super.onDetachedFromWindow();}@Overridepublic void onAttachedToWindow() {super.onAttachedToWindow();requestRender();}public void setBackgroundTexture(int res) {mBgBitmapId = res;mInitBackground = true;}public void clearTileCache() {mCache.clear();}public void onDrawFrame(GL10 gl) {gl.glMatrixMode(GL10.GL_MODELVIEW);gl.glLoadIdentity();GLU.gluLookAt(gl, 0, 0, 2, 0f, 0f, 0f, 0f, 1.0f, 0.0f);gl.glDisable(GL10.GL_DEPTH_TEST);gl.glClearColor(0, 0, 0, 0);gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);draw(gl);//        Log.d("CoverFlowOpenGL", "onDrawFrame");}@Overrideprotected void dispatchDraw(Canvas canvas) {super.dispatchDraw(canvas);if (canvas instanceof BitmapCanvas) {Bitmap bitmap = savePixels();canvas.drawBitmap(bitmap, 0, 0, new Paint());}}private void draw(GL10 gl) {mStopBackgroundThread = true;gl.glPushMatrix();gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVerticesBuffer); // vertices of squaregl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTexturesBuffer); // texture verticesgl.glEnable(GL10.GL_TEXTURE_2D);gl.glEnable(GL10.GL_BLEND);gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);final float offset = mOffset;int i = 0;int max = mListener.getCount(this) - 1;int mid = (int) Math.floor(offset + 0.5);int iStartPos = mid - VISIBLE_TILES;if (iStartPos < 0)iStartPos = 0;// draw the left tilesfor (i = iStartPos; i < mid; ++i) {drawTile(i, i - offset, gl);}// draw the right tilesint iEndPos = mid + VISIBLE_TILES;if (iEndPos > max)iEndPos = max;for (i = iEndPos; i >= mid; --i) {drawTile(i, i - offset, gl);}if (mLastOffset != (int) offset) {mListener.tileOnTop(this, (int) offset);mLastOffset = (int) offset;}gl.glPopMatrix();mStopBackgroundThread = false;//preLoadCache(iStartPos - 3, iEndPos + 3);}private void drawTile(int position, float off, GL10 gl) {final CoverFlowRecord fcr = getTileAtIndex(position, gl);if (fcr != null && fcr.mTexture != 0) {if (mMatrix == null) {mMatrix = new float[16];mMatrix[15] = 1;mMatrix[10] = 1;mMatrix[5] = 1;mMatrix[0] = 1;}float trans = off * SPREAD_IMAGE;float f = off * FLANK_SPREAD;if (f > FLANK_SPREAD)f = FLANK_SPREAD;else if (f < -FLANK_SPREAD)f = -FLANK_SPREAD;mMatrix[3] = -f;mMatrix[0] = 1 - Math.abs(f);float sc = 0.25f * mMatrix[0];trans += f * 1;gl.glPushMatrix();gl.glBindTexture(GL10.GL_TEXTURE_2D, fcr.mTexture); // bind texture// draw bitmapgl.glTranslatef(trans, Math.abs(trans / 3) - 0.2f, Math.abs(trans / 2)); // translate the picture to the right positiongl.glScalef(sc, sc, 1.0f); // scale the picturegl.glMultMatrixf(mMatrix, 0); // rotate the picturegl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);// draw the reflectiongl.glTranslatef(0, -1.6f, 0);gl.glScalef(0.9f, -0.9f, 1);gl.glColor4f(1f, 1f, 1f, 0.1f);gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);gl.glColor4f(1, 1, 1, 1);gl.glPopMatrix();}}private CoverFlowRecord getTileAtIndex(int position, GL10 gl) {synchronized (this) {CoverFlowRecord fcr = mCache.objectForKey(position);if (fcr == null) {long bitmapDuration = 0;Bitmap bm = mListener.getImage(this, position);if (bm == null)return null;int texture = imageToTexture(bm, gl);fcr = new CoverFlowRecord(texture, gl);mCache.putObjectForKey(position, fcr);}return fcr;}}private static Bitmap createTextureBitmap(Bitmap bitmap) {if (bitmap != null) {return bitmap;}int width = bitmap.getWidth();int height = bitmap.getHeight();final Bitmap bm = Bitmap.createBitmap(IMAGE_SIZE, IMAGE_SIZE, Bitmap.Config.ARGB_8888);Canvas cv = new Canvas(bm);if (width > IMAGE_SIZE || height > IMAGE_SIZE) {// scale the bitmap, make the width or height to the IMAGE_SIZERect src = new Rect(0, 0, width, height);float scale = 1.0f;if (width > height)scale = ((float) IMAGE_SIZE) / width;elsescale = ((float) IMAGE_SIZE) / height;width = (int) (width * scale);height = (int) (height * scale);float left = (IMAGE_SIZE - width) / 2.0f;float top = (IMAGE_SIZE - height) / 2.0f;RectF dst = new RectF(left, top, left + width, top + height);cv.drawBitmap(bitmap, src, dst, new Paint());} else {float left = (IMAGE_SIZE - width) / 2.0f;float top = (IMAGE_SIZE - height) / 2.0f;cv.drawBitmap(bitmap, left, top, new Paint());}return bm;}private int imageToTexture(Bitmap bitmap, GL10 gl) {// generate textureint[] texture = new int[1];gl.glGenTextures(1, texture, 0);gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]);final Bitmap bm = createTextureBitmap(bitmap);
//        bitmap.recycle();GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bm, 0); // draw the bitmap in the texture
//        bm.recycle();// some texture settingsgl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);//gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_REPLACE);gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_MODULATE);return texture[0];}// preload the cache from startindex(including) to endIndex(exclusive)// you just can preload the cache after the view has been attached to the windowpublic void preLoadCache(final int startIndex, final int endIndex) {mStopBackgroundThread = false;if (mGLContext != null) {new Thread(new Runnable() {public void run() {int start = startIndex;if (start < 0)start = 0;int max = mListener.getCount(CoverFlowOpenGL.this);int end = endIndex > max ? max : endIndex;for (int i = start; i < end && !mStopBackgroundThread; ++i) {getTileAtIndex(i, mGLContext);}}}).run();}}private static FloatBuffer makeFloatBuffer(final float[] arr) {ByteBuffer bb = ByteBuffer.allocateDirect(arr.length * 4);bb.order(ByteOrder.nativeOrder());FloatBuffer fb = bb.asFloatBuffer();fb.put(arr);fb.position(0);return fb;}public static class CoverFlowRecord {private int mTexture;private GL10 gl;public CoverFlowRecord(int texture, GL10 gl) {mTexture = texture;this.gl = gl;}@Overrideprotected void finalize() throws Throwable {if (mTexture != 0) {gl.glDeleteTextures(1, new int[]{mTexture}, 0);}super.finalize();}}public Bitmap savePixels() {return savePixels(getLeft(), getTop(), getWidth(), getHeight(), gl);}public Bitmap savePixels(int x, int y, int width, int height, GL10 gl) {IntBuffer pixelBuffer = IntBuffer.allocate(width * height);pixelBuffer.position(0);gl.glReadPixels(x, y, width, height, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, pixelBuffer);pixelBuffer.position(0);int pix[] = new int[width * height];pixelBuffer.get(pix);//杩欐槸灏唅ntbuffer涓殑鏁版嵁璧嬪�鍒皃ix鏁扮粍涓�Bitmap bmp = Bitmap.createBitmap(pix, width, height, Bitmap.Config.ARGB_8888);//pix鏄笂闈㈣鍒扮殑鍍忕礌return bmp;}public static interface CoverFlowListener {public int getCount(CoverFlowOpenGL view);                // Number of images to displaypublic Bitmap getImage(CoverFlowOpenGL anotherCoverFlow, int position);    // Image at positionpublic void tileOnTop(CoverFlowOpenGL view, int position); // Notify what tile is on top after scroll or startpublic void topTileClicked(CoverFlowOpenGL view, int position);}
}

Android 真正的3D Gallery相关推荐

  1. android 3d渲染动画效果吗,Android如何实现3D效果

    前言 前段时间读到一篇文章,作者通过自定义View实现了一个高仿小米时钟,其中的3D效果很是吸引我,于是抽时间学习了一下,现在总结出来,和大家分享. 正文 想要在Android上实现3D效果,其实并没 ...

  2. Android的GridView和Gallery结合Demo

    Demo介绍:首页是一个GridView加载图片,竖屏时显示3列图片,横屏时显示4列图片;并且对图片进行大小限制和加灰色边框处理. 点击某一张图片,会链接到Gallery页面,由于Android自带的 ...

  3. android 滑动翻转动画,Android编程实现3D滑动旋转效果的方法

    本文实例讲述了Android编程实现3D滑动旋转效果的方法.分享给大家供大家参考,具体如下: 这里我们通过代码实现一些滑动翻页的动画效果. Animation实现动画有两个方式:帧动画(frame-b ...

  4. Android做3D旋转动画,Android编程实现3D旋转效果实例

    本文实例讲述了Android编程实现3D旋转效果的方法.分享给大家供大家参考,具体如下: 下面的示例是在Android中实现图片3D旋转的效果. 实现3D效果一般使用OpenGL,但在Android平 ...

  5. Android UI设计:Gallery

    Gallery Gallery效果: 用于图片的横屏滑动,效果如下: Gallery用法: Gallery用法与ListView相同,需要自定义BaseAdapter和Item_layout Main ...

  6. android 结构光,3D 结构光还没来得及普及,智能手机的光学革命又高潮了

    一年前,iPhone X 发布前夕,业界传出了"全新 iPhone 会用上 3D 传感器和深度摄像头"的消息. 在这则传闻中,当时还没有发布的 iPhone X 可以通过深度摄像头 ...

  7. Android TV Menu 3D星体旋转效果

    在Android中,如果想要实现3D动画效果一般有两种选择:一是使用Open GL ES,二是使用Camera.Open GL ES使用起来太过复杂,一般是用于比较高级的3D特效或游戏,并且这个也不是 ...

  8. android 脸部识别之3D,2018年高通将推出整合3D脸部识别功能的Android手机芯片

    根据国外科技网站CNET的报导,手机芯片大厂高通(Qualcomm)目前打算在针对Android手机设计的处理器产品中,加入支持红外线3D传感技术.也就是说,未来Android手机从处理器方面就会支持 ...

  9. Android攻城狮Gallery和ImageSwitcher制作图片浏览器

    使用Gallery 和 ImageSwitcher 制作图片浏览器 Gallery介绍 我们有时候在手机上或者PC上看到动态的图片,可以通过鼠标或者手指触摸来移动它,产生动态的图片滚动效果,还可以根据 ...

最新文章

  1. [C#学习笔记]C#中的decimal类型——《CLR via C#》
  2. Java ByteBuffer –速成课程
  3. springCloud - 第6篇 - 网关的实现:ZUUL
  4. 音视频应用驶入快车道 开发者如何快速追赶这波技术红利?
  5. 顺序表之元素位置互换(改进版)
  6. PIL 图片压缩处理
  7. MAC苹果电脑装单win10系统
  8. 如何配置NSSA区域?
  9. C++ 相关职位的要求
  10. Linux上 如何查找yum安装包所缺缺少的依赖包及报错处理
  11. 横向导航条页面居中的方法
  12. 兔子与狐狸c语言,狐狸和兔子
  13. Xilinx FPGA输入输出缓冲 BUF 的使用
  14. 新东方java开发面试经历---现场面试(2021年1月)
  15. Google卫星地图定位(Resources)
  16. 网络分析仪E5071C 使用
  17. 6种最常用恒流源电路的分析与比较
  18. agv ti 毫米波雷达_在毫米波雷达领域,TI构建起了一条完整的护城河
  19. 针对safecast数据集的数据清洗
  20. 付呗聚合支付快速教程 基础篇①——基本介绍和配置

热门文章

  1. linux 创建线程 execvp,execvp使用实例
  2. macbook android 屏幕共享,苹果设备小技巧:iPhone,iPad,Mac进行屏幕共享和远程控制...
  3. Acrel-6000/B电气火灾监控系统麻城广场设计与应用
  4. Unexpected exception parsing XML document from class path resource处理
  5. 元宇宙 - 圈里的百科
  6. 电精2 android,安卓街机模拟器|街机电精2(街机模拟器)安卓版 - 系统天堂
  7. Surface Slim Pen吸附在Pro 8上的尝试
  8. 学习Nginx看这篇就够了
  9. MySql 循环执行语句,循环执行update,详细介绍【游标嵌套】
  10. 注释(单行注释、多行注释、文档注释)