Android界面效果大全


(一)Activity 页面切换的效果 Android 2.0 之后有了 overridePendingTransition() ,其中里面两个参 数,一个是前一个 activity 的退出两一个 activity 的进入, Java 代码 1. @Override public void onCreate(Bundle savedInstanceState) { 2. super.onCreate(savedInstanceState); 3. 4. setContentView(R.layout.SplashScreen); 5. 6. new Handler().postDelayed(new Runnable() { 7. @Override 8. public void run() { 9. Intent mainIntent = new Intent(SplashScreen.this, AndroidNews.class); 10. SplashScreen.this.startActivity(mainIntent); 11. SplashScreen.this.finish(); 12. 13. overridePendingTransition(R.anim.mainfadein, 14. R.anim.splashfadeout); 15. } 16.}, 3000); } 上面的代码只是闪屏的一部分。 Java 代码 1. getWindow (). setWindowAnimations ( int ); 这可没有上个好但是也可以 。 实现淡入淡出的效果 Java 代码 1. overridePendingTransition(Android.R.anim.fade_in,android.R.anim .fade_out); 由左向右滑入的效果 Java 代码 1. overridePendingTransition(Android.R.anim.slide_in_left,android. R.anim.slide_out_right); 实现 zoomin 和 zoomout,即类似 iphone 的进入和退出时的效果 Java 代码 1. overridePendingTransition(R.anim.zoomin, R.anim.zoomout); 新建 zoomin.xml 文件 Xml 代码 1. 2. 新建 zoomout.xml 文件 Xml 代码 1. 2. 6. 10. 12. (二)android 菜单动画 先请注意,这里的菜单并不是按机器上的 MENU 出现在那种菜单,而是基于 Android SDK 提供的 android.view.animation.TranslateAnimation(extends android.view.animation.Animation)类实例后附加到一个 Layout 上使之产生的 有动画出现和隐藏效果的菜单。 原理:Layout(菜单)从屏幕内(挨着屏 幕边沿,其实并非一定,视需要的初态和末态而定)动态 的移动到屏幕外(在外面可以挨着边沿,也可以离远点, 这个无所谓了),这样就可以达到动态菜单的效果了。但 是由于 Animation 的一些奇怪特性(setFill**() 函数的作用效果,这个在我使 用的某几个 Animation 当中出现了没有想明白的效果),就暂不理会这个东西了, 所以使得我们还需要用上 XML 属性 android:visibility。当 Layout(菜单)显 示的时候,设置 android:visibility="visible",当 Layout(菜单)隐藏的时 候,设置 android:visibility="gone",这里 android:visibility 可以有 3 个 值,"visible"为可见,"invisible"为不可见但占空间,"gone"为不可见且不占 空间(所谓的占不占空间,这个可以自己写个 XML 来试试就明白了)。 Class TranslateAnimation 的使用:Animation 有两种定义方 法,一种是用 Java code,一种是用 XML,这里只介绍用 code 来定义(因为用 XML 来定义的那种我没用过。。嘿嘿。。)。多的不说,看代码。 这里是 TranslateAnimationMenu.java(我在里面还另加入了 ScaleAnimation 产生的动画,各位朋友可以照着 SDK 以及程序效果来理解): package com.TranslateAnimation.Menu; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.view.animation.Animation; import android.view.animation.TranslateAnimation; import android.widget.Button; import android.widget.LinearLayout; public class TranslateAnimationMenu extends Activity { /** Called when the activity is first created. */ //TranslateAnimation showAction, hideAction; Animation showAction, hideAction; LinearLayout menu; Button button; boolean menuShowed; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); menu = (LinearLayout) findViewById(R.id.menu); button = (Button) findViewById(R.id.button); // 这里是 TranslateAnimation 动画 showAction = new TranslateAnimation( Animation.RELATIVE_TO_SELF,0.0f,Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, -1.0f, Animation.RELATIVE_TO_SELF, 0.0f); // 这里是 ScaleAnimation 动画 //showAction = new ScaleAnimation( // 1.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.0f, // Animation.RELATIVE_TO_SELF, 0.0f); showAction.setDuration(500); // 这里是 TranslateAnimation 动画 hideAction = new TranslateAnimation( Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, -1.0f); // 这里是 ScaleAnimation 动画 //hideAction = new ScaleAnimation( // 1.0f, 1.0f, 1.0f, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f); hideAction.setDuration(500); menuShowed = false; menu.setVisibility(View.GONE); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub if (menuShowed) { menuShowed = false; menu.startAnimation(hideAction); menu.setVisibility(View.GONE); } else { menuShowed = true; menu.startAnimation(showAction); menu.setVisibility(View.VISIBLE); } } }); } } 这里是 main.xml: 16. 19. 22. 23. 24. BrowserInfo 用于提供一个项的信息 Java 代码 1. public class BrowserInfo { 2. 3. private int appInfoId; 4. private int imageId; 5. private boolean checked; 6. 7. public BrowserInfo(int appInfoId, int imageId, boolean checked) { 8. this.appInfoId = appInfoId; 9. this.imageId = imageId; 10. this.checked = checked; 11. } 12. 13. public boolean isChecked() { 14. return checked; 15. } 16. 17. public void setChecked(boolean checked) { 18. this.checked = checked; 19. } 20. 21. public int getAppInfoId() { 22. return appInfoId; 23. } 24. 25. public void setAppInfoId(int appInfoId) { 26. this.appInfoId = appInfoId; 27. } 28. 29. public int getImageId() { 30. return imageId; 31. } 32. 33. public void setImageId(int imageId) { 34. this.imageId = imageId; 35. } 36. 37. } GroupInfo 用于显示一个组的信息 Java 代码 1. import java.util.List; 2. 3. public class GroupInfo { 4. 5. private BrowserInfo group; 6. private List child; 7. 8. public GroupInfo(BrowserInfo group, List child) { 9. 10. this.group = group; 11. this.child = child; 12. } 13. 14. public void add(BrowserInfo info){ 15. child.add(info); 16. } 17. 18. public void remove(BrowserInfo info){ 19. child.remove(info); 20. } 21. 22. public void remove(int index){ 23. child.remove(index); 24. } 25. 26. public int getChildSize(){ 27. return child.size(); 28. } 29. 30. public BrowserInfo getChild(int index){ 31. return child.get(index); 32. } 33. 34. public BrowserInfo getBrowserInfo() { 35. return group; 36. } 37. 38. public void setBrowserInfo(BrowserInfo group) { 39. this.group = group; 40. } 41. 42. public List getChild() { 43. return child; 44. } 45. 46. public void setChild(List child) { 47. this.child = child; 48. } 49. 50. } ClearBrowserActivity 最后就是把要显示的内容显示出来的。 Java 代码 1. public class ClearBrowserActivity extends Activity implements ExpandableListView.OnGr oupClickListener,ExpandableListView.OnChildClickListener{ 2. 3. private List group; 4. 5. private ClearExpandableListAdapter listAdapter = null; 6. private ExpandableListView appList; 7. 8. public void onCreate(Bundle savedInstanceState) { 9. super.onCreate(savedInstanceState); 10. setContentView(R.layout.browserlayout); 11. appList = (ExpandableListView) findViewById(R.id.appList); 12. init(); 13. BrowserInfo browsingHistoryParents = newBrowserInfo( 14. R.string.browsinghistory, R.drawable.browser_image,true); 15. List browsingHistoryChild = new ArrayList(); 16. BrowserInfo browser = newBrowserInfo(R.string.browser, 17. R.drawable.browser_image, true); 18. browsingHistoryChild.add(browser); 19. 20. BrowserInfo operaClear = newBrowserInfo(R.string.opera_clear, 21. R.drawable.browser_image,true); 22. browsingHistoryChild.add(operaClear); 23. 24. BrowserInfo firefoxClear = newBrowserInfo(R.string.firefox_clear, 25. R.drawable.browser_image,true); 26. browsingHistoryChild.add(firefoxClear); 27. 28. BrowserInfo ucwebClear = newBrowserInfo(R.string.ucweb_clear, 29. R.drawable.browser_image,false); 30. browsingHistoryChild.add(ucwebClear); 31. 32. GroupInfo browserGroup = new GroupInfo(browsingHistoryParents, 33. browsingHistoryChild); 34. addGroup(browserGroup); 35. 36. listAdapter = new ClearExpandableListAdapter(this, group); 37. appList.setOnChildClickListener(this); 38. appList.setOnGroupClickListener(this); 39. appList.setAdapter(listAdapter); 40. } 41. 42. private void init() { 43. group = new ArrayList(); 44. } 45. 46. private void addGroup(GroupInfo info) { 47. group.add(info); 48. } 49. 50. private static BrowserInfo newBrowserInfo(int infoId, int imageId,boolean checked) { 51. return new BrowserInfo(infoId, imageId,checked); 52. } 53. 54. @Override 55. public boolean onGroupClick(ExpandableListView parent, View v, 56. int groupPosition, long id) { 57. return false; 58. } 59. 60. @Override 61. public boolean onChildClick(ExpandableListView parent, View v, 62. int groupPosition, int childPosition, long id) { 63. return false; 64. } 65. } android 3d 旋转 文章分类:Java 编程 在 javaeye 里看到了关于 3d 旋转的文章,可是博主没有透入什么技术细节。 由于一直想做出那种旋转效果,所以就想啊想,终于想出来了( 我是个小菜 鸟)。呵呵,不管怎样,希望对想做还没做出来的朋友一些帮助。 先上一个效果图: 这是你想要的吗?如果是就继续往下看吧。 其实,这个效果是用 animation 配合 camera 做出来的,相信大家在 apidemo 里面看过类似的。 那么先写一个继承 animation 的类:Rotate3d Rotate3d 代码 1. public class Rotate3d extends Animation { 2. private float mFromDegree; 3. private float mToDegree; 4. private float mCenterX; 5. private float mCenterY; 6. private float mLeft; 7. private float mTop; 8. private Camera mCamera; 9. private static final String TAG = "Rotate3d"; 10. 11. public Rotate3d(float fromDegree, float toDegree, float left, float top, 12. float centerX, float centerY) { 13. this.mFromDegree = fromDegree; 14. this.mToDegree = toDegree; 15. this.mLeft = left; 16. this.mTop = top; 17. this.mCenterX = centerX; 18. this.mCenterY = centerY; 19. 20. } 21. 22. @Override 23. public void initialize(int width, int height, int parentWidth, 24. int parentHeight) { 25. super.initialize(width, height, parentWidth, parentHeight); 26. mCamera = new Camera(); 27. } 28. 29. @Override 30. protected void applyTransformation(float interpolatedTime, Transformation t) { 31. final float FromDegree = mFromDegree; 32. float degrees = FromDegree + (mToDegree - mFromDegree) 33. * interpolatedTime; 34. final float centerX = mCenterX; 35. final float centerY = mCenterY; 36. final Matrix matrix = t.getMatrix(); 37. 38. if (degrees <= -76.0f) { 39. degrees = -90.0f; 40. mCamera.save(); 41. mCamera.rotateY(degrees); 42. mCamera.getMatrix(matrix); 43. mCamera.restore(); 44. } else if(degrees >=76.0f){ 45. degrees = 90.0f; 46. mCamera.save(); 47. mCamera.rotateY(degrees); 48. mCamera.getMatrix(matrix); 49. mCamera.restore(); 50. }else{ 51. mCamera.save(); 52. //这里很重要哦。 53. mCamera.translate(0, 0, centerX); 54. mCamera.rotateY(degrees); 55. mCamera.translate(0, 0, -centerX); 56. mCamera.getMatrix(matrix); 57. mCamera.restore(); 58. } 59. 60. matrix.preTranslate(-centerX, -centerY); 61. matrix.postTranslate(centerX, centerY); 62. } 63. } 有了这个类一切都会变得简单的,接着只要在 activity 中写两个 Rotate3d 的对象,让两个 view,分别做这两个对象的 animation 就好了。( 原来就这么 简单啊!无语) Activity 代码 1. //下面两句很关键哦,呵呵,心照不宣。 2. Rotate3d leftAnimation = new Rotate3d(-0, -90, 0, 0, mCenterX, mCenterY); 3. Rotate3d rightAnimation = new Rotate3d(-0+90, -90+90, 0.0f, 0.0f, mCenterX, mCent erY); 4. 5. leftAnimation.setFillAfter(true); 6. leftAnimation.setDuration(1000); 7. rightAnimation.setFillAfter(true); 8. rightAnimation.setDuration(1000); 9. 10. mImageView1.startAnimation(leftAnimation); 11. mImageView2.startAnimation(rightAnimation); 还要写一下 mImageView1,mImageView2 的 xml, Xml 代码 1. 2. 7. 8. 11. 12. 19. 27. 28. 29. 写完收工。如果有不足之处,还请朋友们不吝指教。 Android File Explorer 展示图片 文章分类:移动开发 res/layout/row.xml /res/layout/main.xml /res/layout/jpgdialog.xml /> 12. 3.image_show.xml ImageSwitcher 是用来图片显示那块区域的控件 Gallery 是来控制 底下那个图标列表索引用的 Java 代码 1. 2. 6. 7. 12. 13. 14. 15. 24. 25. 4.ImageShowActivity R.drawable.sample_thumb_0 为图片的标识 图片放在 res/drawable/目录下 图片名称为 sample_thumb_0.gif Java 代码 1. package com.small.photos; 2. 3. import android.app.Activity; 4. import android.content.Context; 5. import android.os.Bundle; 6. import android.view.View; 7. import android.view.ViewGroup; 8. import android.view.Window; 9. import android.view.animation.AnimationUtils; 10. import android.widget.AdapterView; 11. import android.widget.BaseAdapter; 12. import android.widget.Gallery; 13. import android.widget.ImageSwitcher; 14. import android.widget.ImageView; 15. import android.widget.AdapterView.OnItemSelectedListener; 16. import android.widget.RelativeLayout.LayoutParams; 17. import android.widget.ViewSwitcher.ViewFactory; 18. 19. public class ImageShowActivity extends Activity implements ViewFactory, 20. OnItemSelectedListener { 21. /** Called when the activity is first created. */ 22. ImageSwitcher mSwitcher; 23. private Integer[] mThumbIds = { R.drawable.sample_thumb_0, 24. R.drawable.sample_thumb_1, R.drawable.sample_0, R.drawable.sample_1 }; 25. 26. private Integer[] mImageIds = { R.drawable.sample_thumb_0, 27. R.drawable.sample_thumb_1, R.drawable.sample_0, R.drawable.sample_1 }; 28. 29. @Override 30. public void onCreate(Bundle savedInstanceState) { 31. super.onCreate(savedInstanceState); 32. requestWindowFeature(Window.FEATURE_NO_TITLE); 33. 34. setContentView(R.layout.image_show); 35. setTitle("ImageShowActivity"); 36. 37. mSwitcher = (ImageSwitcher) findViewById(R.id.ImageSwitcher01); 38. // 系统的 anim 中的 fade_in.xml 39. mSwitcher.setFactory(this); 40. mSwitcher.setInAnimation(AnimationUtils.loadAnimation(this, 41. android.R.anim.fade_in)); 42. mSwitcher.setOutAnimation(AnimationUtils.loadAnimation(this, 43. android.R.anim.fade_out)); 44. 45. Gallery g = (Gallery) findViewById(R.id.gallery); 46. // 为缩略图浏览器指定一个适配器 47. g.setAdapter(new ImageAdapter(this)); 48. // 响应 在缩略图列表上选中某个缩略图后的 事件 49. g.setOnItemSelectedListener(this); 50. 51. } 52. 53. @SuppressWarnings("unchecked") 54. public void onItemSelected(AdapterView parent, View v, int position, long id) { 55. mSwitcher.setImageResource(mImageIds[position]); 56. } 57. 58. @SuppressWarnings("unchecked") 59. public void onNothingSelected(AdapterView parent) { 60. } 61. 62. @Override 63. public View makeView() { 64. ImageView i = new ImageView(this); 65. i.setBackgroundColor(0xFF000000); 66. i.setScaleType(ImageView.ScaleType.FIT_CENTER); 67. i.setLayoutParams(new ImageSwitcher.LayoutParams( 68. LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); 69. return i; 70. } 71. 72. public class ImageAdapter extends BaseAdapter { 73. private Context mContext; 74. 75. public ImageAdapter(Context c) { 76. mContext = c; 77. } 78. 79. public int getCount() { 80. return mThumbIds.length; 81. } 82. 83. public Object getItem(int position) { 84. return position; 85. } 86. 87. public long getItemId(int position) { 88. return position; 89. } 90. 91. //getView 方法动态生成一个 ImageView,然后利用 setLayoutParams、 setImageResource、 92. //setBackgroundResource 分别设定图片大小、图片源文件和图片背景。当图片被 显示到当前 93. //屏幕的时候,这个函数就会被自动回调来提供要显示的 ImageView 94. public View getView(int position, View convertView, ViewGroup parent) { 95. ImageView i = new ImageView(mContext); 96. 97. i.setImageResource(mThumbIds[position]); 98. i.setAdjustViewBounds(true); 99. i.setLayoutParams(new Gallery.LayoutParams( 100. LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 101. i.setBackgroundResource(R.drawable.picture_frame); 102. return i; 103. } 104. 105. } 106. 107. } 5.AndroidManifest.xml 标识 MainActivity 为一个程序的开始 Java 代码 1. 2. 6. 7. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 基本上就是这些了,然后启动吧! opengl es 雾 文章分类:移动开发 雾效果在某种场合很重要,想象你正在游戏中穿过城市的边缘,显然你并没有渲 染场景中很远距的物体,因为代价很大。当然你不愿意突然出现的场景或物体。 雾可以解决这个问题。 雾同样可以使场景更加逼真,例如一个山谷中的场景,往往会云气缭绕。 这一章依据第 17 章的代码。 程序代码: 雾可以指定一个颜色,我们创建一个灰色的颜色。 float fogColor[] = { 0.5f, 0.5f, 0.5f, 1.0f }; 雾又三种模式,下面列表给出: 模式 描述 GL_EXP 雾的最简单的一种模式. 物体并没有真正的存在雾中,仅仅是 一种阴霾的效果。 GL_EXP2 比第一种模式高级. 比第一种逼真些,但远近距离效果不够真 实。 GL_LINEAR 最逼真的一种模式. 模拟现实中的场景。 由上可以看出,GL_LINEAR 是最好的一种效果,但并不意味着你要使用它。显然 越好的效果,性能的损失就越大,根据你的需要选择哪种模式。 创建一个数组,保存雾的所有模式,用于即使切换。fogType 指明当前使用的哪 种模式。 float fogTypes[] = { GL_EXP, GL_EXP2, GL_LINEAR }; int fogType = 0; 设置雾的效果,需要使用 glFogf 或 glFogfv 函数。glFogf 函数有两个参数,第 一个是指定要修改的雾的属性标志,第二个是修改的值。 下表描述了雾的各种属性。 标记 浮点 值 描述 GL_FOG_MODE GL_EXP, GL_EXP2 or GL_LINEAR 雾的效果模式. GL_FOG_DENSITY > 0.0f (default 1.0f) 雾的密度, 值越大密度越高。 GL_FOG_START Any float (default 0.0f) 指定雾的近 面距离,在此距离内不渲染. GL_FOG_END Any float (default 1.0f) 指定雾的 远面距离,超过此距离不渲染. 了解了属性参数,下面设置雾的属性,初始化雾的模式为 GL_EXP. bool init() { . . glFogf(GL_FOG_MODE, GL_EXP); //指定雾的颜色,灰色 glFogfv(GL_FOG_COLOR, fogColor); //雾的密度 glFogf(GL_FOG_DENSITY, 0.35f); //系统如何计算雾气,这里设置不关心 glHint(GL_FOG_HINT, GL_DONT_CARE); glFogf(GL_FOG_START, 1.0f); glFogf(GL_FOG_END, 5.0f); glEnable(GL_FOG); . . } void display() { . . glTranslatef(0.0f, 0.0f, -5.0f); . . } menu 函数中动态改变雾的模式。 case 3 : ++fogType %= 3; glFogf(GL_FOG_MODE, fogTypes[fogType]); break; 至此,雾已经加入到你的场景了,观察效果吧。 Opengl 归纳 文章分类:移动开发 1.雾 Java 代码 1. // fog opengles 2. 3. gl.glFogfv(GL10.GL_FOG_COLOR, fogColorBfr); 4. gl.glFogf(GL10.GL_FOG_DENSITY, 0.35f); 5. gl.glHint(GL10.GL_FOG_HINT, GL10.GL_DONT_CARE); 6. gl.glFogf(GL10.GL_FOG_START, 2.0f); 7. gl.glFogf(GL10.GL_FOG_END, 6.0f); 8. gl.glEnable(GL10.GL_FOG); Java 代码 1. glClearColor(0.5f,0.5f,0.5f,1.0f); // 设置背景的颜色为雾气的颜色 2. glFogi(GL_FOG_MODE, fogMode[fogfilter]); // 设置雾气的模式 3. glFogfv(GL_FOG_COLOR, fogColor); // 设置雾的颜色 4. glFogf(GL_FOG_DENSITY, 0.35f); // 设置雾的密度 5. glHint(GL_FOG_HINT, GL_DONT_CARE); // 设置系统如何计算雾气 6. glFogf(GL_FOG_START, 1.0f); // 雾气的开始位置 7. glFogf(GL_FOG_END, 5.0f); // 雾气的结束位置 8. glEnable(GL_FOG); // 使用雾气 2.混合 Blend Java 代码 1. gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); 2. gl.glEnable(GL10.GL_BLEND); 3.纹理 Java 代码 1. // create textures 2. gl.glEnable(GL10.GL_TEXTURE_2D); 3. texturesBuffer = IntBuffer.allocate(3); 4. gl.glGenTextures(3, texturesBuffer); 5. 6. // load bitmap 7. Bitmap texture = Utils.getTextureFromBitmapResource(context, R.drawable.glas s); 8. 9. // setup texture 0 10. gl.glBindTexture(GL10.GL_TEXTURE_2D, texturesBuffer.get(0)); 11. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL1 0.GL_NEAREST); 12. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL1 0.GL_NEAREST); 13. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.G L_CLAMP_TO_EDGE); 14. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.G L_CLAMP_TO_EDGE); 15. GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, texture, 0); 16. 17. // setup texture 1 18. gl.glBindTexture(GL10.GL_TEXTURE_2D, texturesBuffer.get(1)); 19. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL1 0.GL_LINEAR); 20. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL1 0.GL_LINEAR); 21. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.G L_CLAMP_TO_EDGE); 22. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.G L_CLAMP_TO_EDGE); 23. GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, texture, 0); 24. 25. // setup texture 2 26. gl.glBindTexture(GL10.GL_TEXTURE_2D, texturesBuffer.get(2)); 27. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL1 0.GL_LINEAR); 28. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL1 0.GL_LINEAR_MIPMAP_NEAREST); 29. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.G L_CLAMP_TO_EDGE); 30. gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.G L_CLAMP_TO_EDGE); 31. Utils.generateMipmapsForBoundTexture(texture); 32. 33. // free bitmap 34. texture.recycle(); 定向光 文章分类:移动开发 这一节我们使用定向光,涉及漫射光的高级应用和镜面光源。 我们将展示镜面光的显示效果,使用红色的小球和照在小球上的光源。 程序代码: 第一步依然是定义属性值,这里我们要加上镜面光的属性值定义。 float lightAmbient[] = { 0.2f, 0.0f, 0.0f, 1.0f }; float lightDiffuse[] = { 0.5f, 0.0f, 0.0f, 1.0f }; float lightSpecular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; 同样,定义材质对镜面光的反射值 float matAmbient[] = { 1.0f, 1.0f, 1.0f, 1.0f }; float matDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; float matSpecular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; 因为是定向光,所以我们需要知道光的位置和方向,下面代码就是定义位置和方 向, float lightPosition[] = { 2.0f, 2.0f, 3.0f, 0.0f }; float lightDirection[] = { -2.0f, -2.0f, -3.0f }; 下面启用第一个光源 void init() { glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); 设置材质属性 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matAmbient); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matDiffuse); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matSpecular); 另一个可以用 glMaterialf 设置的属性是 GL_SHININESS,它的值在 0 到 128 之 间,它表明镜面光的焦距度,值越大镜面光焦距越多。 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20.0f); 下一步设置光属性 glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient); glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpecular); 设置光源的位置和方向,使用 glLightfv 函数,它的第二个参数可以指明设置 的是位置还是方向。 glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, lightDirection); 另一个有用的标记是 GL_SPOT_CUTOFF,它指定光锥体的大小,想象一个火把远 离你时所产生的火光锥体,1.2 将产生 2.4 度大的光锥体,如果设置为 180 度, 则发射的光会照到各个角落。 glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 1.2f); 我们要讨论的下一个标记是 GL_SPOT_EXPONENT,它控制圆锥体内光强分布的指 数因子,值在 0 到 128 之间,值越大,锥体轴线部分的光越强。 glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 20.0f); glLightf 函数还有三个标记可以设置,是用来控制衰减方式的,分别是: GL_CONSTANT_ATTENUATION(1), GL_LINEAR_ATTENUATION(0), GL_QUADRATIC_ATTENUATION。即常数衰减,线性衰减和二次衰减。括号中的值是 它的默认值。 衰减指的是光的强度逐渐减弱,就像你离火光越来越远一样。设置这些属性会导 致程序大幅减慢。 display 函数余下部分不变。 glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepthf(1.0f); glEnable(GL_CULL_FACE); glShadeModel(GL_SMOOTH); } 我们简单的使用 glutSolidSphere / ugSolidSpheref 来创建求面体,这个球面 体由水平 24 栈和垂直 24 片组成,这样可以更多的体现光照细节。 也许你奇怪我们为什么没有指定球面的法线,令人高兴的是 UG / GLUT|ES 库中 创建的形状物体,法线是自动生成的,均由库自动计算,这大大简化了我们的任 务。 void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAtf( 0.0f, 0.0f, 4.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); glRotatef(xrot, 1.0f, 0.0f, 0.0f); glRotatef(yrot, 0.0f, 1.0f, 0.0f); ugSolidSpheref(1.0f, 24, 24); glFlush(); glutSwapBuffers(); } 运行程序,会呈现一个红色的球,注意镜面光源在球的右上方,那么现在你可以 把定向光加入自己的程序了。 opengl es 灯光 文章分类:移动开发 这一章将在你的程序中加入灯光,使场景看起来和真实场景一样。 灯光 opengl 中灯光分为好几种,都可以加入到你的场景中。 Ambiend Light 环境光 环境光没有确切的来源方向,当环境光照射到物体时,光被反射到各个方向。 Diffuse Light 漫射光 漫射光不同于环境光,它来自某个方向,但和环境光一样,照射到物体时,会被 反射到各个方向。 Specular Light 镜面光 镜面光和漫射光一样是有方向的,但它反射方向是一定的,而不像漫射光一样反 射到各个方向。所以当镜面光照射到物体时,你会看到物体表面被照射的亮点。 Emissive Light 发射光 它来自于某一物体,该物体散发出大量的光,但不会被任何物体面反射。 为了更好的理解这几种光,我从网络上摘抄了一段定义: * 环境光——经过多次反射而来的光称为环境光,无法确定其最初的方向, 但当特定的光源关闭后,它们将消失. * 全局环境光——它们并非来自特定的光源,这些光经过了多次散射,已 经无法确定其光源位于何处. * 散射光——来自同一方向,照射到物体表面后,将沿各个方向均匀反射, 因此,无论从哪个方向观察,表面的亮度都相同. * 镜面反射光——来自特定方向,也被反射到特定方向.镜面反射度与之 相关. * 材质发射光——用于模拟发光物体.在 OpenGL 光照模型中,表面的发射 光增加了物体的亮度,它不受光源的影响,另外,发射光不会给整个场景中增加 光线. 材质 你不光可以设置光的属性,而且还可以指定不同的面对光照作出的反应,这就要 指定材质属性。 这就指定了一个面对光源反射多少。 法线 法线是一个向量垂直于(90 度)某一特定面,就称这个向量是某个面的法线。 法线可以用于光的计算。如果你想让画出的物体对光源产生影响,那么必须指定 物体每个面的法线。下面将会说明。 另一个需要注意的一点是,法线要单位化,我们不会深入数学计算,这不是我们 这章的目的。如果需要会在将来某章中讲解。简明的说,一个向量的长度等于各 个向量分量的平方和的平方根,再把每个向量的分量除以这个值。现在不需要过 多担心这个。 程序代码: 下面定义两个颜色数组,一个用于环境光,一个用于漫射光,它们是光源的颜色 值。 float lightAmbient[] = { 0.2f, 0.3f, 0.6f, 1.0f }; float lightDiffuse[] = { 0.2f, 0.3f, 0.6f, 1.0f }; 下面创建一个材质属性数组,分别用于环境光和漫射光。 用材质属性值乘以光源值得出面的反射颜色值,下面的值将会导致面反射的光失 去接收光的百分之四十。每个值表示特定颜色被反射的数量。 float matAmbient[] = { 0.6f, 0.6f, 0.6f, 1.0f }; float matDiffuse[] = { 0.6f, 0.6f, 0.6f, 1.0f }; void init() { 首先先启用光源,这样光才会在场景中起作用。 glEnable(GL_LIGHTING); opengl 最多允许 8 个光源,要使用某个光源,需要使用 glEnable 打开它,光源 的编号是 GL_LIGHTX,X 的值是 0---7。 指定材质属性,可以使用 glMaterialfv 和 glMaterialf ,glMaterialfv 接受向 量数组,而 glMaterialf 只接受一个向量。第一个参数指定那个面被更新,在 opengl es 中只可以使用 GL_FRONT_AND_BACK,其他参数不起作用。之所以存在 这个参数,是因为 opengl 可以设置多个参数。 第二个参数指定光源的类型,GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_EMISSION 和 GL_AMBIENT_AND_DIFFUSE. 最后一个参数指定一个数组或单个值,取决于你使用的哪个函数。 下一行设置面的材质属性: glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matAmbient); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matDiffuse); 灯光的设置和材质的设置相同,使用 glLightfv 或 glLightf 函数: glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient); glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse); init 函数没有发生改变: glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepthf(1.0f); glVertexPointer(3, GL_FLOAT, 0, box); glEnableClientState(GL_VERTEX_ARRAY); glEnable(GL_CULL_FACE); glShadeModel(GL_SMOOTH); } display 函数的开头部分没有发生改变: void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAtf( 0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); glRotatef(xrot, 1.0f, 0.0f, 0.0f); glRotatef(yrot, 0.0f, 1.0f, 0.0f); 前面我们讨论了法线,法线是垂直于面的,所以前平面的法线是(0, 0, 1),后 平面的法线是(0, 0, -1),两个法线的长度为 1,所以不用再单位化。 法线由 glNormal3f 函数指定,并在渲染时调用。这个函数由 3 个 float 类型的 数据组成单位化的向量。 // FRONT AND BACK glColor4f(1.0f, 0.0f, 0.0f, 1.0f); glNormal3f(0.0f, 0.0f, 1.0f); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glNormal3f(0.0f, 0.0f, -1.0f); glDrawArrays(GL_TRIANGLE_STRIP, 4, 4); 其他页面设置也同上, // LEFT AND RIGHT glColor4f(0.0f, 1.0f, 0.0f, 1.0f); glNormal3f(-1.0f, 0.0f, 0.0f); glDrawArrays(GL_TRIANGLE_STRIP, 8, 4); glNormal3f(1.0f, 0.0f, 0.0f); glDrawArrays(GL_TRIANGLE_STRIP, 12, 4); // TOP AND BOTTOM glColor4f(0.0f, 0.0f, 1.0f, 1.0f); glNormal3f(0.0f, 1.0f, 0.0f); glDrawArrays(GL_TRIANGLE_STRIP, 16, 4); glNormal3f(0.0f, -1.0f, 0.0f); glDrawArrays(GL_TRIANGLE_STRIP, 20, 4); glFlush(); glutSwapBuffers(); } 最后菜单增加一项彩色材质,这项选择打开或关闭色彩跟踪。色彩跟踪根据当前 面的色彩反色不同色的光。 case 2 : if (glIsEnabled(GL_COLOR_MATERIAL)) glDisable(GL_COLOR_MATERIAL); else glEnable(GL_COLOR_MATERIAL); break; 下面两张图是程序的运行结果,分别是普通灯光和色彩追踪的效果。 普通灯光 色彩跟踪 opengl es 色彩混合 文章分类:移动开发 色彩混合对于效果有很大作用,通过它,可以实现物体透明,例如玻璃、水、窗 户等等。 alpha 是混合的基础,前面说过,色彩是由 RGBA 表示的,A 就代表 alpha,我们 可以简单理解为透明度。A 值为 0 代表完全透明,1 代表不透明,指定 A 的值 0 到 1 之间可以调整色彩的透明度。 当使用混合时,始终要记住两个不同的颜色,一个是源色彩(用来参加运算),一 个是目标色彩(已经存在于缓冲区)。混合就是进行两个色彩的运算。 程序代码: 这章使用正交视图 glOrthof(0.0f, 3.0f, 0.0f, 3.0f, -1.0f, 1.0f); 然后重叠几个矩形放在屏幕上,顶点数组下面给出: GLfloat rectangle[] = { -1.0f, -0.25f, 1.0f, -0.25f, -1.0f, 0.25f, 1.0f, 0.25f }; 下面将显示色彩的不同混合方式,下面的变量用来控制混合方式。 int currBlend = 4; init 函数首先选择清除缓冲区的颜色,并且不使用深度值。 void init() { glClearColor(0.25f, 0.25f, 0.25f, 1.0f); 然后启用混合功能,传递 GL_BLEND 参数给 glEnable 函数。 glEnable(GL_BLEND); glBlendFunc 函数用于指定颜色如何混合,有两个参数,它们指定颜色运算方式, 有下面几种方式: GL_ZERO GL_ONE GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_DST_COLOR GL_ONE_MINUS_DST_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA GL_DST_ALPHA GL_ONE_MINUS_DST_ALPHA 第一个参数也可以指定为 GL_SRC_ALPHA_SATURATE。 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 下面的数组用于切换不同的混合操作。 GLenum blendSrc[] = { GL_ONE, GL_ONE, GL_ONE, GL_SRC_ALPHA, GL_SRC_ALPHA }; GLenum blendDst[] = { GL_ZERO, GL_ONE, GL_ONE_MINUS_DST_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA }; display 函数放置 4 个矩形在屏幕上 void display() { glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); glVertexPointer(2, GL_FLOAT, 0, rectangle); glEnableClientState(GL_VERTEX_ARRAY); glPushMatrix(); glTranslatef(1.5f, 2.0f, 0.0f); glColor4f(1.0f, 0.0f, 0.0f, 0.5f); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glPopMatrix(); glPushMatrix(); glTranslatef(0.7f, 1.5f, 0.0f); glRotatef(90.0f, 0.0f ,0.0f, 1.0f); glColor4f(0.0f, 1.0f, 0.0f, 0.5f); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glPopMatrix(); glPushMatrix(); glTranslatef(1.7f, 1.5f, 0.0f); glRotatef(90.0f, 0.0f ,0.0f, 1.0f); glColor4f(0.0f, 0.0f, 1.0f, 0.25f); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glPopMatrix(); glPushMatrix(); glTranslatef(1.5f, 1.0f, 0.0f); glColor4f(1.0f, 1.0f, 0.0f, 0.75f); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glPopMatrix(); glFlush(); glutSwapBuffers(); } menu 函数中选择不同的混合处理。 case 2 : ++currBlend %= 5; glBlendFunc(blendSrc[currBlend], blendDst[currBlend]); glutPostRedisplay(); break; 运行程序,你可以使用'b'键改变混合方式。 默认混合方式为( GL_ONE, GL_ZERO ),这种方式意味着目标色不起作用,仅仅 用源色覆盖目标色,效果如下: 第二种方式为( GL_ONE, GL_ONE ), 第三种方式为(GL_ONE, GL_ONE_MINUS_DST_ALPHA) 第四种方式为(GL_SRC_ALPHA, GL_ONE) (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) opengl es 灯光 | Opengl-ES 方法 Android 图片倒影 文章分类:移动开发 public static Bitmap createReflectedImage(Bitmap originalImage) { // The gap we want between the reflection and the original image final int reflectionGap = 4; int width = originalImage.getWidth(); int height = originalImage.getHeight(); // This will not scale but will flip on the Y axis Matrix matrix = new Matrix(); matrix.preScale(1, -1); // Create a Bitmap with the flip matrix applied to it. // We only want the bottom half of the image Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0, height / 2, width, height / 2, matrix, false); // Create a new bitmap with same width but taller to fit reflection Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (height + height / 2), Config.ARGB_8888); // Create a new Canvas with the bitmap that's big enough for // the image plus gap plus reflection Canvas canvas = new Canvas(bitmapWithReflection); // Draw in the original image canvas.drawBitmap(originalImage, 0, 0, null); // Draw in the gap Paint defaultPaint = new Paint(); canvas.drawRect(0, height, width, height + reflectionGap, defaultPaint); // Draw in the reflection canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null); // Create a shader that is a linear gradient that covers the reflection Paint paint = new Paint(); LinearGradient shader = new LinearGradient(0, originalImage.getHeight(), 0, bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP); // Set the paint to use this shader (linear gradient) paint.setShader(shader); // Set the Transfer mode to be porter duff and destination in paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN)); // Draw a rectangle using the paint with our linear gradient canvas.drawRect(0, height, width, bitmapWithReflection.getHeight() + reflectionGap, paint); return bitmapWithReflection; } 画面 文章分类:移动开发 Android 系统开机动画包括两部分: 开机显示的 ANDROID 文字; ANDROID 发光动画。 这篇文章说的开机动画是第一种,下面开始正文! 1. 制作当前屏幕像素的图片(模拟器默认为 320*480) 使用 PS 制作一张 320*480 的图片,保存时选“保存为 Web 所用格式”,然后在 弹开的窗口上,“预设”项选择“PNG-24”,保存为 android_logo.png 注:好像只支持 png-24,其他格式生成的 rle 文件显示不正常,有兴趣大家可 以再验证一下。 2. 将图片转换为 raw 格式 使用 linux 下的 ImageMagick 自带的 convert 命令,进行 raw 格式转换,命令为: convert -depth 8 android_logo.png rgb:android_logo.raw 注:ubuntu 10.04 默认已经安装 ImgageMagick 工具,如果当前系统没有安装, 可以执行下面的命令安装: sudo apt-get install imagemagick 3. 将 raw 格式转化为 rle 文件 需要用到 android 编译后的 rgb2565 工具,在 android/out/host/linux-x86/bin 目录下(android 为当前源码所在目录),转换命令如下: rgb2565 -rle < android_logo.raw > initlogo.rle 到目前为止,启动需要显示的图像已经做好了,就是 initlogo.rle,注意文件 名必须是这个,如果想改文件名,需要修改 android/system/core/init/init.h 中的宏: #define INIT_IMAGE_FILE "/initlogo.rle" ===================================================================== ======================= 下面需要将 initlogo.rle 加入的 android 文件系统中 4. 找到 ramdisk.img 文件 (android/out/target/product/generic/ramdisk.img),将文件名改为 ramdisk.img.gz,然后使用下面的命令解压: gunzip ramdisk.img.gz 解压后得到 ramdisk.img,可能有人要问,怎么文件名又改回去了?其实不然, 使用 file ramdisk.img 查看一下就知道了: 解压前:ramdisk.img: gzip compressed data, from Unix 解压后:ramdisk.img: ASCII cpio archive (SVR4 with no CRC) 跑题了,还是说正事儿。 5. 使用 cpio 提取文件: 新建一个 temp 目录: mkdir temp cd temp cpio -i -F ../ramdisk.img 6. 导出文件列表: cpio -i -t -F ../ramdisk.img > list 注:list 是一个文本文件,里面存储了 ramdisk.img 的文件结构,我们需要在 这个文件中加入 initlogo.rle 这一行,修改后的文件如下: data default.prop dev init init.goldfish.rc init.rc initlogo.rle proc sbin sbin/adbd sys system 7. 生成 ramdisk.img cpio -o -H newc -O ramdisk.img < list 注:根据 list 文件的描述,生成 ramdisk.img 文件 8. 用 ramdisk.img 覆盖 sdk 目录下的 ramdisk.img(android-sdk-windows/platforms/android-2.1/images/ramdisk. img),最好先备份一下。 9. 启动模拟器,就可以看到我们自己做的的开机界面了。 ///////////////////////// 开机图片设置 的下载地址为:http://docs.google.com/leaf?id=0 ... TIzOGQ5OWQ3&hl=en init 文件下载地址 http://docs.google.com/leaf?id=0 ... 2RiYjZjNjM2&hl=en split_bootimg.pl 下载地址: http://android-dls.com/files/linux/split_bootimg.zip T 卡文件下载地址:http://docs.google.com/leaf?id=0 ... GVjYzVhMjg4&hl=en 开机图片设置 软件原理: 根据 android 系统 开机 LOGO 和开机动画的存放路径:/initlogo.rle 和 /data/local/bootanimation.zip 在 init.rc 中 建立两个链接: /initlogo.rle ->/data/data/com.android.e139.gallery/initlogo.rle 和 /data/local/bootanimation.zip ->/data/data/com.android.e139.gallery/bootanimation.zip 来完成开机 LOGO 和开机动画的动态设定 安装要求: 1.本 apk 文件只能安装在 android 2.1 或 2.0 的操作系统 中 2.必须修改 android 根目录下面的两个文件:init.rc 和 init 功能才能实现 设置开机 LOGO 和开机动画的功能 修改 init.rc 和 init 的方法: 1.修改 init.rc 和 init 文件需要修改手机中的 boot.img 导出方法: cat /dev/mtd/mtd2 > /sdcard/root.img 然后 adb pull /sdcard/root.img ./ 这样就把 root.img 拷贝到本地目录下了。 boot.img 的组成结构是 +—————–+ | boot header | 1 page +—————–+ | kernel | n pages +—————–+ | ramdisk | m pages +—————–+ | second stage | o pages +—————–+ 那我们要做的就是把这几个部分分别分离出来 我们现在先进行镜像分离。用命令 ./split_bootimg.pl boot.img 成功执行后,可以得到两个文件,一个是 boot.img-kernel,另一个是 boot.img-ramdisk.gz。我们这里以修改 ramdisk 为例,所以将其解包 mkdir ramdisk cd ramdisk gzip -dc ../boot.img-ramdisk.gz | cpio -i cd .. 2.进入 ramdisk 修改 init.rc 在 init.rc 中增加: on logo-init mkdir /data 0775 system system # We chown/chmod /data again so because mount is run as root + defaults mount yaffs2 mtd@userdata /data nosuid nodev chown system system /data #for other user can read this dir chmod 0775 /data symlink /data/data/com.android.e139.gallery/initlogo.rle /initlogo.rle on early-boot # copy file symlink /data/data/com.android.e139.gallery/bootanimation.zip /data/local/bootanimation.zip chmod 0666 /data/local/bootanimation.zip 再将已经下载的 init 文件覆盖到目录下面的 init 文件 3.生成新 img 回到 ramdisk 的上一级目录后执行: mkbootfs ./ramdisk | gzip > ramdisk-new.gz mkbootimg --cmdline 'no_console_suspend=1 console=null' --kernel boot.img-kernel --ramdisk ramdisk-new.gz -o boot-new.img 就会重新生成 boot-new.img 3.刷入新 img 生成了新的 img 后,我们如何在系统上应用我们的新 boot.img 呢?首先,把 img 文件放到 sdcard 上去 adb push ./boot_new.img /sdcard 然后执行这两个操作 cat /dev/zero > /dev/mtd/mtd2 flash_image boot /sdcard/mynewimage.img 执行第一个操作时,可能会提示你 write: No space left on device 这个信息没关系,不用管它。两个命令都执行后,最后 adb shell reboot 即可。 如果重启顺利,那么恭喜你,你刷成功了. 安装步骤: 1.按上面的步骤修改手机中的 init.rc 和 init 文件 2.把下载的 T 卡文件放到 T 卡中 3.安装 开机图片设置.apk 文件 修改 boot.img 的方法参考: http://www.kunli.info/2009/09/14/how-to-modify-ramdisk-android/ 和 http://android-dls.com/wiki/index.php?title=HOWTO:_Unpack,_Edit,_and_ Re-Pack_Boot_Images 3D 桌面效果动画类 文章分类:移动开发 Java 代码 1. public class CubeAnimation extends Animation implements 2. Animation.AnimationListener { 3. public static final int FACE_LEFT = 0; 4. public static final int FACE_RIGHT = 1; 5. private int mInd; 6. private float mFromDegrees; 7. private float mToDegrees; 8. private float mCenterX; 9. private float mCenterY; 10. private int mHorizonType = 1; 11. private float mHorizonValue = 0.5F; 12. private Camera mCamera; 13. private View mView; 14. 15. public CubeAnimation(int ind) { 16. this.mInd = ind; 17. this.mFromDegrees = 0.0F; 18. this.mToDegrees = 90.0F; 19. } 20. 21. public CubeAnimation(Context context, AttributeSet attrs) { 22. super(context, attrs); 23. TypedArray a = context.obtainStyledAttributes(attrs, 24. R.styleable.CubeAnimation); 25. 26. this.mFromDegrees = 0.0F; 27. this.mToDegrees = 90.0F; 28. 29. Description d = Description.parseValue(a.peekValue(0)); 30. this.mHorizonType = d.type; 31. this.mHorizonValue = d.value; 32. 33. this.mInd = a.getInt(1, 0); 34. 35. boolean t = a.getBoolean(2, true); 36. if (!(t)) { 37. this.mInd = (1 - this.mInd); 38. this.mToDegrees = 0.0F; 39. this.mFromDegrees = 90.0F; 40. } 41. a.recycle(); 42. } 43. 44. public void onAnimationStart(Animation anim) { 45. this.mView.setVisibility(View.VISIBLE); 46. } 47. 48. public void onAnimationEnd(Animation anim) { 49. this.mView.setVisibility((this.mInd == 0) ? 0 : 8); 50. this.mInd = (1 - this.mInd); 51. } 52. 53. public void onAnimationRepeat(Animation anim) { 54. } 55. 56. public static void startCubeAnimation(Context context, int id, View view1, 57. View view2) { 58. XmlPullParser parser; 59. try { 60. parser = context.getResources().getAnimation(id); 61. AttributeSet attrs = Xml.asAttributeSet(parser); 62. 63. int type = parser.getEventType(); 64. int depth = parser.getDepth(); 65. while (true) { 66. while (true) { 67. if ((((type = parser.next()) == 3) && (parser.getDepth() <= depth)) 68. || (type == 1)) 69. break label172; 70. if (type == 2) 71. break; 72. } 73. 74. String name = parser.getName(); 75. 76. if (name.equals("cube")) { 77. CubeAnimation anim1 = new CubeAnimation(context, attrs); 78. anim1.mInd = 1; 79. anim1.mView = view1; 80. anim1.setAnimationListener(anim1); 81. CubeAnimation anim2 = new CubeAnimation(context, attrs); 82. anim2.mInd = 0; 83. anim2.mView = view2; 84. anim2.setAnimationListener(anim2); 85. view1.startAnimation(anim1); 86. label172: view2.startAnimation(anim2); 87. } 88. } 89. } catch (Resources.NotFoundException ex) { 90. Log.e("CubeAnimation", "NotFoundException"); 91. } catch (XmlPullParserException ex) { 92. Log.e("CubeAnimation", "XmlPullParserException"); 93. } catch (IOException ex) { 94. Log.e("CubeAnimation", "IOException"); 95. } 96. } 97. 98. public void initialize(int width, int height, int parentWidth, 99. int parentHeight) { 100. super.initialize(width, height, parentWidth, parentHeight); 101. this.mCenterX = resolveSize(1, 0.5F, width, parentWidth); 102. this.mCenterY = resolveSize(1, 0.5F, height, parentHeight); 103. if (this.mHorizonType == 0) { 104. this.mHorizonValue /= height; 105. } 106. 107. this.mCamera = new Camera(); 108. } 109. 110. protected void applyTransformation(float interpolatedTime, Transformation t) { 111. float fromDegrees = this.mFromDegrees; 112. float degrees = fromDegrees + (this.mToDegrees - fromDegrees) 113. * interpolatedTime; 114. 115. float centerX = this.mCenterX; 116. float centerY = this.mCenterY; 117. Camera camera = this.mCamera; 118. 119. Matrix matrix = t.getMatrix(); 120. 121. camera.save(); 122. 123. float b = 0.0F; 124. float e = -this.mHorizonValue; 125. 126. if (this.mInd == 0) { 127. degrees += 90.0F; 128. } 129. 130. camera.rotateY(degrees); 131. 132. camera.getMatrix(matrix); 133. camera.restore(); 134. 135. if (this.mInd == 0) { 136. matrix.preScale(-1.0F, 1.0F, centerX, 0.0F); 137. } 138. 139. float tranX = 320.0F * interpolatedTime; 140. 141. float tranY = -centerY * e + b; 142. matrix.preTranslate(0.0F, centerY * e); 143. matrix.postTranslate(tranX, tranY); 144. } 145. 146. protected static class Description { 147. public int type; 148. public float value; 149. 150. static Description parseValue(TypedValue value) { 151. Description d = new Description(); 152. if (value == null) { 153. d.type = 0; 154. d.value = 0.0F; 155. } else { 156. if (value.type == 6) { 157. d.type = (((value.data & 0xF) == 1) ? 2 : 1); 158. 159. d.value = TypedValue.complexToFloat(value.data); 160. return d; 161. } 162. if (value.type == 4) { 163. d.type = 0; 164. d.value = value.getFloat(); 165. return d; 166. } 167. if ((value.type >= 16) && (value.type <= 31)) { 168. d.type = 0; 169. d.value = value.data; 170. return d; 171. } 172. } 173. 174. d.type = 0; 175. d.value = 0.0F; 176. 177. return d; 178. } 179. } 180. } 31 菱形 3D 实例 文章分类:移动开发 下面是具体的实现方法: 首先需要建两个 array,第一 array 是用来告诉 opengl 这个图形有哪些顶点: 画一个三维的坐标轴,然后把你要画的点都算出来,然后放在这个 array 里。 Java 代码 1. float l=1.5f; 2. float[] vertex={ 3. 4. 0.0f,l,0.0f, 5. 6. l,0.0f,0.0f, 7. 8. 0.0f,0.0f,l, 9. 10. -l,0.0f,0.0f, 11. 12. 0.0f,0.0f,-l, 13. 14. 0.0f,-l,0.0f 15. 16. }; 第二个 array 是告诉 opengl 你要怎样组织这些点: 这里我要画三角形,所以每三个点是一组。 Java 代码 1. byte[] edge= 2. { 3. 0,1,2, 4. 1,2,5, 5. 6. 0,2,3, 7. 5,2,3, 8. 9. 0,3,4, 10. 5,3,4, 11. 12. 0,4,1, 13. 5,4,1 14. 15. }; 这里的数字,是第一个 array 的 index。 下面你要建立两个 Buffer 它们是用来存放这两个 array 的。 Java 代码 1. ByteBuffer bb = ByteBuffer.allocateDirect(vertex.length*4); 2. bb.order(ByteOrder.nativeOrder()); 3. fbv=bb.asFloatBuffer(); 4. fbv.put(vertex); 5. fbv.position(0); 6. 7. ffe=ByteBuffer.allocateDirect(edge.length); 8. ffe.put(edge); 9. ffe.position(0); 这样一个三维的菱形就画好了。 下面你要写一个方法能让它自己把自己画出来! Java 代码 1. public void draw(GL10 gl) 2. { 3. gl.glFrontFace(GL10.GL_CW); 4. gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fbv); 5. gl.glDrawElements(GL10.GL_TRIANGLES, 24, GL10.GL_UNSIGNED_BYTE, ffe); 6. 7. } 先说第一个 glFrontFace,物体都有一个正面一个反面,这里告诉 opengl 显示这个物体按顺 时针方向(CW=> clockwise) gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fbv);这个方法是把本程序所用的点都传递个 opengl。 opengl 需要知道什么哪?首先是 这个点是几维的(opengl 支持 2,3,4 维),这里是 3 所 以是三维的,第二个参数告诉 opengl,这个点是用什么样类型的变量来储存的,这里是 float 类型。第三个是步长(stride),这个我还没弄明白,不过我看的例子都为 0. 最后把你建立 好的三维坐标点都传给 opengl gl.glDrawElements。 这个方法是告诉 opengl 如果要画这个图形,应该怎么画。第一个参数, 告诉 opengl 用画三角形(这样 opengl 就以三个点为一组),然后告诉 opengl 你要用到多少 个点(注意这个点是在第二个 array 里的点数)。 第三个是告诉 opengl 这些点(其实是三维 坐标点的 reference)的类型。这里是 unsigned byte。最后把你排列点的 array 放进去! 第二个大的步骤是创建一个让这个三维坐标运行的环境(Renderer)。 这是一个 interface 类 首先,在 onDrawFrame 里,我们告诉本程序这个三维图形的行为: 在做任何事情之前,我们要清空所有以前内存里的东西,这个内存包括:Color 和 Depth gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT); 然后告诉 opengl 你要用那个 MatrixMode 这个就比较难解释了。 如果写程序 只要记住 GL_MODELVIEW 是管理图形的 缩放,移动,和转动就行了.(如果那 个朋友想理解的更深一点,可以联系我,我可以把我的笔记发过去或者参考 http://glasnost.itcarlow.ie/~powerk/GeneralGraphicsNotes/projection/projection_viewing.html )。 gl.glTranslatef(0, 0, -3.0f); 这个方法告诉 opengl 把图形沿 z 轴迁移 3 个 unit。这三个值分别是 x,y,z 轴。 gl.glRotatef(angle,0, 1, 0); 这个方法告诉我们以 y 为轴。 转 angle 个度数。注意这里的 1 和 0 是告诉沿着那个轴转, 别的值应该没有意义。 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 还记得上边说的 opengl 分 client side 和 service side 吗。 这个是告诉 opengl 如果 client side 调用 draw 什么的时候,这个 vertex array 是可用的。opengl 有很多这样的可选项,所以需要 告诉 opengl,因为我们已经设置了 vertex array(我们的第一个 array),所以告诉 opengl 它 是可用的(如果不告诉,opengl 会忽略)! trian.draw(gl); 这个方法是把图形画出来。 angle++; 为了达到动态的效果,我们让每一个 frame 的 angle,比上一个多一度。 当显示空间大小发生变化的时候,我们应该告诉 opengl 一下信息: Java 代码 1. public void onSurfaceChanged(GL10 gl, int width, int height) 2. { 3. gl.glViewport(0, 0, width, height); 4. gl.glMatrixMode(GL10.GL_PROJECTION); 5. gl.glLoadIdentity(); 6. float ratio = (float)width/height; 7. gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); 8. 9. } 首先是 opengl 可用的空间 : gl.glViewport(0, 0, width, height); 想象一下用这四个点画出来的四边形,就是 opengl 所能用的空间。 gl.glMatrixMode(GL10.GL_PROJECTION); 这个 matrix 是如何把三维坐标转换为二维坐标并把它放在显示器上。 gl.glLoadIdentity 是告诉 opengl 初始化这个 matrix。 gl.glFrustumf 要把三维的东西用二维显示出来,需要知道几个东西,第一是这个显示平面有多大,你可以 看多近和多远。这里的头四个参数,建立了一个四边形,告诉 opengl 把图形显示在这个范 围了。后两个参数告诉 opengl 这里显示平面里可以显示三维空间里最近和最远的位置。 当这个三维图形建立的是时候,我们可以告诉 opengl 一些基本参数。这里把能省略的都省 略了(其实什么都没有也可以运行!) Java 代码 1. public void onSurfaceCreated(GL10 gl, EGLConfig arg1) 2. { 3. gl.glEnable(GL10.GL_DEPTH_TEST); 4. gl.glClearColor(0,0, 0, 0); 5. } gl.glEnable(GL10.GL_DEPTH_TEST); 告诉 opengl 要检查 depth,为什么哪。在三维空间里一个 物体 A 在另一个物体 B 后面,那么这个 A 被 B 挡住里,所以你是看不见的。我们要告诉 opengl, 我们不想看见被挡住的东西。这个 GL_DEPTH_TEST 就是这个功能。 gl.glClearColor(0,0, 0, 0); 设置这个背景颜色为黑色,应为我们没有给我们的三维图形设置颜色(为了简单),它的初 始化颜色是白色。 以下是源代码: Java 代码 1. package Beta.ThreeD; 2. 3. import java.nio.ByteBuffer; 4. import java.nio.ByteOrder; 5. import java.nio.FloatBuffer; 6. 7. import javax.microedition.khronos.opengles.GL10; 8. 9. public class TriangleShape 10. { 11. 12. private final float l=1.5f; 13. 14. private FloatBuffer fbv; 15. 16. private ByteBuffer ffe; 17. 18. public TriangleShape() 19. 20. { 21. 22. float[] vertex={ 23. 24. 0.0f,l,0.0f, 25. 26. l,0.0f,0.0f, 27. 28. 0.0f,0.0f,l, 29. 30. -l,0.0f,0.0f, 31. 32. 0.0f,0.0f,-l, 33. 34. 0.0f,-l,0.0f 35. 36. }; 37. 38. 39. byte[] edge= 40. 41. { 42. 43. 0,1,2, 44. 45. 1,2,5, 46. 47. 48. 49. 0,2,3, 50. 51. 5,2,3, 52. 53. 54. 55. 0,3,4, 56. 57. 5,3,4, 58. 59. 60. 61. 0,4,1, 62. 63. 5,4,1 64. 65. }; 66. 67. ByteBuffer bb = ByteBuffer.allocateDirect(vertex.length*4); 68. 69. bb.order(ByteOrder.nativeOrder()); 70. 71. fbv=bb.asFloatBuffer(); 72. 73. fbv.put(vertex); 74. 75. fbv.position(0); 76. 77. 78. 79. 80. ffe=ByteBuffer.allocateDirect(edge.length); 81. 82. ffe.put(edge); 83. 84. ffe.position(0); 85. 86. } 87. 88. public void draw(GL10 gl) 89. 90. { 91. 92. gl.glFrontFace(GL10.GL_CW); 93. 94. gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fbv); 95. 96. gl.glDrawElements(GL10.GL_TRIANGLES, 24, GL10.GL_UNSIGNED_BYTE, ffe); 97. 98. } 99. } 100. 101. 102. package Beta.ThreeD; 103. 104. import javax.microedition.khronos.egl.EGLConfig; 105. import javax.microedition.khronos.opengles.GL10; 106. 107. import android.opengl.GLSurfaceView.Renderer; 108. 109. public class MySimpleRendered implements Renderer 110. { 111. 112. private int angle=50; 113. 114. private TriangleShape trian; 115. 116. public MySimpleRendered() 117. 118. { 119. 120. trian = new TriangleShape(); 121. 122. } 123. 124. @Override 125. 126. public void onDrawFrame(GL10 gl) 127. 128. { 129. 130. // TODO Auto-generated method stub 131. 132. gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT); 133. 134. gl.glMatrixMode(GL10.GL_MODELVIEW); 135. 136. gl.glLoadIdentity(); 137. 138. gl.glTranslatef(0, 0, -3.0f); 139. 140. gl.glRotatef(angle,0, 1, 0); 141. 142. gl.glRotatef(angle, 1, 0, 0); 143. 144. gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 145. 146. trian.draw(gl); 147. 148. angle++; 149. 150. } 151. 152. 153. @Override 154. 155. public void onSurfaceChanged(GL10 gl, int width, int height) 156. 157. { 158. 159. // TODO Auto-generated method stub 160. 161. gl.glViewport(0, 0, width, height); 162. 163. gl.glMatrixMode(GL10.GL_PROJECTION); 164. 165. gl.glLoadIdentity(); 166. 167. float ratio = (float)width/height; 168. 169. gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); 170. 171. 172. 173. } 174. 175. 176. @Override 177. 178. public void onSurfaceCreated(GL10 gl, EGLConfig arg1) 179. 180. { 181. 182. gl.glEnable(GL10.GL_DEPTH_TEST); 183. 184. gl.glClearColor(0,0, 0, 0); 185. 186. } 187. 188. } 189. package Beta.ThreeD; 190. 191. import android.app.Activity; 192. import android.os.Bundle; 193. import android.opengl.GLSurfaceView; 194. public class Triangle extends Activity { 195. /** Called when the activity is first created. */ 196. 197. private GLSurfaceView my_view; 198. @Override 199. public void onCreate(Bundle savedInstanceState) { 200. super.onCreate(savedInstanceState); 201. setContentView(R.layout.main); 202. my_view = new GLSurfaceView(this); 203. my_view.setRenderer(new MySimpleRendered()); 204. this.setContentView(my_view); 205. } 206. public void onResume() 207. { 208. 209. super.onResume(); 210. 211. my_view.onResume(); 212. } 213. public void onPause() 214. { 215. 216. super.onPause(); 217. 218. my_view.onPause(); 219. } 220. } 镜像倒影特效 Gallery 文章分类:移动开发 效果展示 本文档将介绍在 android 上如何实现一个倒影效果的 Gallery。 为了达到上图所示的效果, 首先,是需要有一个自定义的 gallery,实现了对 Gallery 的继承,通过重写 getChildStaticTransformation 方法来控制,每个子 view 有不同的缩放比例, 形成阶梯状的展示。这个 gallery 是在坤庭的代码基础上实现的,我这里就不再 重复介绍。 接下来,gallery 中的每个 view,都是一个自定义的 MirrorView,由它来实现 了画原图及画倒影。新的算法解决了性能问题,下面就重点说一下这部分内容: 镜像特效最近还蛮流行的,尤其在 HTC 的 Sense 介面上,常常都可以见到。大 家可以看到,加了个镜像特效后,那感觉就很立体,感觉上好像是这些图片摆立 在一个玻璃桌面上。 在 Android 上要帮图片加上镜像特效,会不会很麻烦?一点也不麻烦,只要几 行代码,就可以搞定。 因此,在开始看答案之前,我会建议你要先有 Photoshop 的使用经验。想想, 如果用 Photoshop 要帮图片加上镜像特效,要如何做?我想一般不外乎是先复 制个图片,并将其垂直翻转,接着再对这翻转的图片,加个由灰到黑的渐层 mask 即可。 好了,让我们来看一下答案。底下就是帮图片加上镜像特效的程式范例。 Java 代码 1. public class MirrorView extends View { 2. 3. Paint m_paint; 4. 5. int m_nShadowH; 6. 7. Drawable m_dw; 8. 9. Bitmap m_bitmap; 10. 11. Matrix mMatrix; 12. 13. int shadowHeight; 14. 15. public MirrorView(Context context, Bitmap bitmap) { 16. 17. super (context); 18. 19. m_bitmap = bitmap; 20. 21. _Init(); 22. 23. } 24. 25. private void _Init() { 26. 27. //m_dw = new BitmapDrawable(BitmapFactory.decodeResource(getResources(), R.draw able.icon)); 28. 29. m_dw = new BitmapDrawable(m_bitmap); 30. 31. m_dw.setBounds(0,0,m_dw.getIntrinsicWidth(),m_dw.getIntrinsicHeight()); 32. 33. m_nShadowH = m_dw.getIntrinsicHeight()/1; 34. 35. m_paint = new Paint(Paint.ANTI_ALIAS_FLAG ); 36. 37. LinearGradient lg = new LinearGradient(0, 0, 0, m_nShadowH, 0xB0FFFFFF, 0×00000000, Shader.TileMode.CLAMP ); 38. 39. m_paint.setShader(lg); 40. 41. m_paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY )); 42. 43. mMatrix = new Matrix(); 44. 45. } 46. 47. @Override 48. 49. public void onDraw(Canvas canvas) { 50. 51. super .onDraw(canvas); 52. 53. int nX = 0; 54. 55. int nY = 0; 56. 57. _DrawNormalImg(canvas, nX, nY); 58. 59. _DrawMirror(canvas, nX, nY); 60. 61. } 62. 63. private void _DrawNormalImg(Canvas canvas, int nX, int nY) { 64. 65. canvas.save(Canvas.MATRIX_SAVE_FLAG ); 66. 67. canvas.translate(nX, nY); 68. 69. m_dw.draw(canvas); 70. 71. canvas.restore(); 72. 73. } 74. 75. private void _DrawMirror(Canvas canvas, int nX, int nY) { 76. 77. int nW = m_dw.getIntrinsicWidth(); 78. 79. int nH = m_dw.getIntrinsicHeight(); 80. 81. shadowHeight=nH/2; 82. 83. float [] src={0, nH, nW, nH, nW,nH – m_nShadowH, 0, nH – m_nShadowH}; 84. 85. float [] dst={ 0, nH, nW, nH,nW, shadowHeight, 0, shadowHeight }; 86. 87. canvas.save(); 88. 89. mMatrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1); 90. 91. canvas.concat(mMatrix); 92. 93. //draw mirror image 94. 95. canvas.save(Canvas.MATRIX_SAVE_FLAG ); 96. 97. canvas.scale(1.0f, -1.0f); 98. 99. canvas.translate(nX, -(nY + nH * 2)); 100. 101. canvas.clipRect(0, nH, nW, nH – m_nShadowH); 102. 103. m_dw.draw(canvas); 104. 105. canvas.restore(); 106. 107. //draw mask 108. 109. canvas.save(); 110. 111. canvas.translate(nX, nY + nH); 112. 113. canvas.drawRect(0, 0, nW, m_nShadowH, m_paint); 114. 115. canvas.restore(); 116. 117. canvas.restore(); 118. 119. } 120. 121. } _DrawMirror() 方法是关键。用 Photoshop 要如何做出镜像特效?第一步是先 画出垂直翻转的图片。 Android 绘图座标体系预设的原点在左上角,X 轴往右是越来越大的正值,而 Y 轴往下,则是越来越大的正值。要画出垂直翻转的图片,其实也就是要垂直翻转 整个绘图座标体系。在 Android 中,要如何做?答案就是 canvas.scale(1.0f, -1.0f)。很简单吧,没想到给 scale() 函式一个负值,就可以翻转相对应的轴。 在 Photoshop 中,做镜像特效的第二步是要对这翻转的图片,加个由灰到黑的 渐层 mask。 在 Android 中,要画渐层色,那就一定得用 LinearGradient 这个类别。至于要 对背景图加上个 mask,就请参考一下 Paint 的 setXfermode() 函式。 _Init() 这个函式,就是负责生成一个由灰到黑渐层 mask 的 m_paint 物件。 这个控件我测试过,200 张图片加入 adapter,在大数据量情况下性能也没有问 题。 Gallery3D 各个界面可见范围计算方法 文章分类:移动开发 computeVisibleRange 算法分析: 第 1 步,计算出 left,right,bottom,top 第 2 步,计算出 numSlots,并除于 2 赋值给 index 第 3 步,由 index 得 position,判断 position 是否在第 1 步计算出的范围内,是的话,就把第 2 步计算得出的中间的 index 赋值给 firstVisibleSlotIndex,lastVisibleSlotIndex,否则,根据滑 动窗口算法改变 index 直到求组所需 index 第 4 步,在 while 循环中,用第 3 步得到的 firstVisibleSlotIndex 求出 position,进行和第 2 步相 反的判断,即 position 若不在可视范围内,则将相应的 index 给 firstVisibleSlotIndex,否则减 firstVisibleSlotIndex,直到找到最小的可视范围内的 index 作为 firstVisibleSlotIndex。 第 5 步,在 while 循环中,用第 3 步得到的 lastVisibleSlotIndex 求出 position,进行和第 2 步相 反的判断,即 position 若不在可视范围内,则将相应的 index 给 lastVisibleSlotIndex,否则增 lastVisibleSlotIndex,直到找到可视范围内的最大的 index 作为 lastVisibleSlotIndex。 第 6 步,进行 firstVisibleSlotIndex,lastVisibleSlotIndex 的越界判断。 outBufferedVisibleRange 对应的是可见的。outBufferedVisibleRange 对应的是 0~文件夹的最大数。 computeVisibleItems 算法分析: 第 1 步 由 slot 计算出 position,set,当前 set 不为空且 slot 在有效范围,创建 bestItems,计算 sortedIntersection 第 2 步 计算这个 slotindex 中的图片数目,取这个文件中的前 12 张图片加到 bestItems. 第 3 步 取 bestItems 里的图片对应的 displayList 中的 displayItem,并赋值给 displayItems 数 组,同时保存 position,及 j,j 是 bestItems 数组中一项,范围是 0~12。 第四步 对于每一个文件夹,要在 displayItems 里有对应的 12 项,当文件夹内图片不足 12 时,余下的用 null 填充。 当绘制缩略图界面时,有些不同 在第 1 步中,slotindex 不再表示文件夹,这时表示具体某一张图片了,所以由 slot 得到的 set 里 始 终 只 有 1 项 , 且 会 调 ArrayUtils.computeSortedIntersection(visibleItems, items, MAX_ITEMS_PER_SLOT, bestItems, sTempHash);给 bestItems 赋值,这样第 2 步就在 bestItems 加项动作不执行。 Gallery3D 中画图时调用 glTranslate 函数参数赋值过程 文章分类:移动开发 GridDrawManager::drawDisplayItem(RenderView view, GL11 gl, DisplayItem displayItem, Texture texture, int pass,Texture previousTexture, float mixRatio) 函数有下面几句: Java 代码 1. Vector3f animatedPosition = displayItem.mAnimatedPosition; 2. float translateXf = animatedPosition.x * camera.mOneByScale; 3. float translateYf = animatedPosition.y * camera.mOneByScale; 4. float translateZf = -animatedPosition.z; 调用过程: ->computeVisibleItems(),displayItems[baseIndex + j] = displayItem;Vector3f position = pool.create(); GridCameraManager.getSlotPositionForSlotIndex(i, camera, layout, deltaAnchorPosition, position);//give position value displayList.setPositionAndStackIndex(displayItem, position, j, true);//raletive position to item ->GridLayer, mDrawManager = new GridDrawManager(context, mCamera, mDrawables, sDisplayList, sDisplayItems, sDisplaySlots); ->GridDrawManager(), mDisplayItems = displayItems; ->drawFocusItems ,DisplayItem[] displayItems = mDisplayItems; ->animatedPosition = displayItem.mAnimatedPosition; ->drawDisplayItem, amAnimatedPosition ->DisplayItem::commit() amAnimatedPosition.set(mTargetPosition); -> DisplayItem::set(Vector3f position, int stackIndex, boolean performTransition) mTargetPosition.z = Java 代码 1. public void getPositionForSlotIndex(int slotIndex, int itemWidth, int itemHeight, Vector3f outPosition) { 2. outPosition.x = (slotIndex / mNumRows) * (itemWidth + mSpacingX); 3. outPosition.y = (slotIndex % mNumRows) * (itemHeight + mSpacingY); 4. int maxY = (mNumRows - 1) * (itemHeight + mSpacingY); 5. outPosition.y -= (maxY >> 1); 6. outPosition.z = 0; 7. Log.d("outPosition","slotIndex="+slotIndex+",mNumRows="+mNumRows+",outPosit ion=("+outPosition.x+","+outPosition.y+","+outPosition.z+")"); 8. } 在 gallery3d 中矩阵是从上到下、从左到右排列的,在主界面时最多有 3 行,mNumRows=3, 在缩略图界面最多 4 行 mNumRows=4,在查看界面只有一行 mNumRows=1 上面函数是计算所绘制项位置的,slotIndex / mNumRows 得到的是当前处于多少列,slotIndex % mNumRows 得到的是处于多少行。 int maxY = (mNumRows - 1) * (itemHeight + mSpacingY); outPosition.y -= (maxY >> 1);是为了在 y 方向对称,想成屏幕中间是分界线,以上的项 y 为负,线以下的 y 为正。 deltaAnchorPosition 的赋值过程: Java 代码 1. int currentlyVisibleSlotIndex = getAnchorSlotIndex(ANCHOR_CENTER);->anchorItem = dis playItem.mItemRef;-> newSlotIndex = i;->if (currentAnchorSlotIndex != Shared.INVALID & & newAnchorSlotIndex != Shared.INVALID) { 2. layout.getPositionForSlotIndex(newAnchorSlotIndex, itemWidth, itemHeight, de ltaAnchorPosition); 3. oldLayout.getPositionForSlotIndex(currentAnchorSlotIndex, itemWidth, itemHei ght, currentSlotPosition); 4. currentSlotPosition.subtract(sDeltaAnchorPosition); 5. deltaAnchorPosition.subtract(currentSlotPosition); 6. deltaAnchorPosition.y = 0; 7. deltaAnchorPosition.z = 0; 8. } MediaFeed::run() onFeedChanged(, onLayout(newSlotIndex, currentlyVisibleSlotIndex, null); onLayout, sDeltaAnchorPositionUncommited.set(deltaAnchorPosition); computeVisibleRange(),sDeltaAnchorPosition.set(sDeltaAnchorPositionUncommited); deltaAnchorPosition.set(sDeltaAnchorPosition); deltaAnchorPosition Gallery3D 笔记 文章分类:移动开发 布局及特效 gallery3d 的精华 一、布局 gallery3d 的界面生成和普通的应用程序不一样。普通程序一般一个界面就是一 个 activity,布局用 xml 或代码都可以实现,界面切换是 activity 的切换方式; 而 gallery3d 没有用 android 的 UI 系统,而是用 opengl 画出来的,即界面是在 同一个 activity 的,如主界面,缩略图界面,单张图片查看界面,标记界面等 都属于同一个 activity。那么这界面布局不同的界面是如何组合到一起的呢? 分析代码,可以把它看成一个状态机: 1、标记模式 public static final int MODE_SELECT = 1;(HudLayer) 包含了主界面标记模式,缩略界面矩阵游览时标记模式、缩略图界面分类游览时 标记模式 3 个界面 2、普通模式 public static final int MODE_NORMAL = 0;(HudLayer) 包含了 Java 代码 1. public static final int STATE_MEDIA_SETS = 0;主界面 2. public static final int STATE_GRID_VIEW = 1;缩略图矩阵浏览 3. public static final int STATE_FULL_SCREEN = 2;查看界面 4. public static final int STATE_TIMELINE = 3;缩略图界面分类浏览 有了以上状态分类后,在渲染的时候就能根据些界面的组成来定哪些控件譔隐藏, 哪些要显示了。 下面是基本控件: Java 代码 1. com.cooliris.media.GridLayer 2. com.cooliris.media.BackgroundLayer 3. com.cooliris.media.HudLayer 4. com.cooliris.media.ImageButton 5. com.cooliris.media.TimeBar 6. com.cooliris.media.MenuBar 7. com.cooliris.media.PopupMenu 8. com.cooliris.media.PathBarLayer 在渲染时,每一帧所有界面上的元素都画了,由于根据上面的状态只把特定窗口 的特定元素显示出来,其它窗口中的隐藏,所以不会乱。 Layer 是上面控件的基类,上面控件的类也就有了下面两个方法来隐藏不譔显示 的界面元素。 Java 代码 1. public boolean isHidden() { 2. return mHidden; 3. } 4. 5. public void setHidden(boolean hidden) { 6. if (mHidden != hidden) { 7. mHidden = hidden; 8. onHiddenChanged(); 9. } 10. } 下面是根据上面分类来画不同元素所用的标识: Java 代码 1. public static final int PASS_THUMBNAIL_CONTENT = 0; 2. public static final int PASS_FOCUS_CONTENT = 1; 3. public static final int PASS_FRAME = 2; 4. public static final int PASS_PLACEHOLDER = 3; 5. public static final int PASS_FRAME_PLACEHOLDER = 4; 6. public static final int PASS_TEXT_LABEL = 5; 7. public static final int PASS_SELECTION_LABEL = 6; 8. public static final int PASS_VIDEO_LABEL = 7; 9. public static final int PASS_LOCATION_LABEL = 8; 10. public static final int PASS_MEDIASET_SOURCE_LABEL = 9; Java 代码 1. drawDisplayItem(view, gl, displayItem, texture, PASS_THUMBNAIL_CONTENT, placeholde r,displayItem.mAnimatedPlaceholderFade); 画缩略图的,注掉此句,前两屏只显示框, 第三屏 OK 2. drawDisplayItem(view, gl, displayItem, texture, PASS_FOCUS_CONTENT, null, 0.0f);画单 张图片的,注掉,第三屏黑屏 3. drawDisplayItem(view, gl, itemDrawn, textureToUse, PASS_FRAME, previousTexture, ratio );画边框的,注掉,前两屏明显没有边框,巨齿明显 4. drawDisplayItem(view, gl, displayItem, textureString, PASS_TEXT_LABEL, null, 0);画文本 标签的 5. drawDisplayItem(view, gl, displayItem, textureToUse, PASS_SELECTION_LABEL, null, 0);画 选中标记的 6. drawDisplayItem(view, gl, displayItem, videoTexture, PASS_VIDEO_LABEL, null, 0);画视频 标记的 7. drawDisplayItem(view, gl, displayItem, locationTexture, PASS_LOCATION_LABEL, null, 0); 画位置标记的 8. drawDisplayItem(view, gl, displayItem, locationTexture, PASS_MEDIASET_SOURCE_LABEL ,transparentTexture, 0.85f);画源来源图标的(相机或一般文件夹) 二、特效 举如何显示一张图片为例,在图片完全显示出来经过这样一个过程,附近的图片 渐小渐出,当前图片渐大渐入,当前图片逐渐变大直到全屏。实现这个特效,要 进行很多帧的渲染。就是说并不是只调一次 onDrawFrame 函数就可以了,要调用 多次。可以把这个特效的实现想成一个状态变化的过程,在每一个状态,纹理的 显示大小和位置都不同,这也符合动画的基本原理。放大、缩小我们只要改变顶 点数据就可以做到,gallery3d 也是这样做的,下面是主要代码: 我们知道调用 onDrawFrame 来渲染,最后调到下面的 drawFocusItems 函数, Java 代码 1. GridQuad quad = GridDrawables.sFullscreenGrid[vboIndex]; 2. float u = texture.getNormalizedWidth(); 3. float v = texture.getNormalizedHeight(); 4. float imageWidth = texture.getWidth(); 5. float imageHeight = texture.getHeight(); 6. boolean portrait = ((theta / 90) % 2 == 1); 7. if (portrait) { 8. viewAspect = 1.0f / viewAspect; 9. } 10. quad.resizeQuad(viewAspect, u, v, imageWidth, imageHeight);//改变用来贴图片的长方 形的大小 11. quad.bindArrays(gl);//绑定新数据,为渲染做准备。 而位置的改变有两种方式,一种是直接以顶点数据中改变,另一种是计算出在 3 维 3 个方向的偏移量,再调用 gltranslate 来做,从代码可以看出采用的是第二 种方式来做的,比第一种方式更方便一些。代码: Java 代码 1. gl.glTranslatef(-translateXf, -translateYf, -translateZf); 而这里的 3 个偏移量的计算是和 camera 相关的,相关文件为 GridCamera.java, GridCameraManager.java,过程很复杂,理清楚后再细化吧。 cache 管理 下面是 cache 文件 Java 代码 1. /sdcard/Android/data/com.cooliris.media/cache/local-album-cache 2. d---rwxr-x system sdcard_rw 2010-05-21 09:56 local-album-cache 3. d---rwxr-x system sdcard_rw 2010-05-21 09:56 local-meta-cache 4. ----rwxr-x system sdcard_rw 299877 2010-05-28 07:36 local-album-cachechunk_0 5. d---rwxr-x system sdcard_rw 2010-05-21 09:56 geocoder-cache 6. ----rwxr-x system sdcard_rw 284 2010-05-28 07:36 local-album-cacheindex 7. d---rwxr-x system sdcard_rw 2010-05-21 09:56 local-image-thumbs 8. d---rwxr-x system sdcard_rw 2010-05-21 09:56 local-video-thumbs 9. d---rwxr-x system sdcard_rw 2010-05-21 09:56 picasa-thumbs 10. ----rwxr-x system sdcard_rw 80 2010-05-28 07:36 local-meta-cachechunk_0 11. ----rwxr-x system sdcard_rw 164 2010-05-28 07:36 local-meta-cacheindex 12. d---rwxr-x system sdcard_rw 2010-05-21 09:56 hires-image-cache 13. ----rwxr-x system sdcard_rw 627629 2010-05-28 07:37 local-image-thumbschunk_0 14. ----rwxr-x system sdcard_rw 3914 2010-05-21 09:56 local-image-thumbsindex 15. ----rwxr-x system sdcard_rw 53343 2010-05-28 07:34 hires-image-cache-4982941342 287215583_1024.cache 16. ----rwxr-x system sdcard_rw 237692 2010-05-28 07:33 hires-image-cache36845684843 69117627_1024.cache 17. ----rwxr-x system sdcard_rw 133182 2010-05-28 07:34 hires-image-cache60754254408 1226432_1024.cache 18. ----rwxr-x system sdcard_rw 83223 2010-05-28 07:34 hires-image-cache42754796232 10216146_1024.cache 19. ----rwxr-x system sdcard_rw 292837 2010-05-28 07:34 hires-image-cache-6463165569 36433937_1024.cache 20. ----rwxr-x system sdcard_rw 191377 2010-05-28 07:35 hires-image-cache26313646045 09958174_1024.cache 21. ----rwxr-x system sdcard_rw 366905 2010-05-28 07:35 hires-image-cache-3280562009 766080884_1024.cache 22. ----rwxr-x system sdcard_rw 323671 2010-05-28 07:35 hires-image-cache57524718275 33329222_1024.cache 创建 cache 的关键代码 Java 代码 1. LocalDataSource 2. public static final DiskCache sThumbnailCache = new DiskCache("local-image-thumbs");-- --------------------local-image-thumbs local-image-thumbschunk_0 local-image-thumbsind ex 3. public static final DiskCache sThumbnailCacheVideo = new DiskCache("local-video-thum bs");--------------------local-video-thumbs 4. public static final DiskCache sAlbumCache = new DiskCache("local-album-cache");--------- -------------local-album-cache local-album-cacheindex 5. public static final DiskCache sMetaAlbumCache = new DiskCache("local-meta-cache");---- --------------local-meta-cache local-meta-cacheindex 6. getChunkFile --------------local-meta-cachechunk_0 local-album-cachechunk_0 7. 8. ReverseGeocoder:: private static final DiskCache sGeoCache = new DiskCache("geocoder -cache"); -------------------------geocoder-cache 9. PicasaDataSource:: public static final DiskCache sThumbnailCache = new DiskCache("pica sa-thumbs");-----------------------------picasa-thumbs 10. UriTexture::writeToCache --------------------------hires-image-cache-xxx_1024.cache 布局补充: 在画一个界面是,是分类化的,比如第一个界面是显示所有有图片的文件夹,在代 码里叫专辑.有这些元素要创建: 文本标签 显示专辑名和专辑内图片或视频数 路径条 显示路径名 按纽 拍照按纽,放大/缩小 菜单栏 全选,取消全选,分享,删除,更多等 图片边框 用于显示图片的矩形 在渲染时一次把一类元素画完,再画另一类.如主界面顺序为: 路径条->按纽->文本标签->图片边框->图片. 具体代码见 drawBlendedComponents 函数 1.CacheService.java 中 写 缓 存 : sAlbumCache.put(ALBUM_CACHE_LOCALE_INDEX, sDummyData, 0); 第一个是 key ,这里是正常数据,当然还有别的 key , key 分别是 -1,-2,-3,-4,-5 。 2.DiskCache.java 中,执行上面的写的过程,这里先得明白他的 cache 怎么装的: 它是由很多称之为“片”的文件组成的,形成一个 List 形式: private final LongSparseArray mChunkFiles = new LongSparseArray(); 即 mChuckFiles 就是整个 cache ,里面包括很多 chunk( 即片 ) ,每一个 chunk 大小为 1MB. 当 要 写 入某 一 个 chunk 里面的时候,先要找到他在 mChuckFiles 里面 的 索 引值 即 chunkIndex, 由 mChunkFiles.get(chunkIndex); 来获取这个文件, chunkIndex 怎么来的呢? private LongSparseArray mIndexMap; Record record = mIndexMap.get(key); 这里的 key 就是上面用 put 方法传过来的 ALBUM_CACHE_LOCALE_INDEX 的值(就是 -5 ) int chunkIndex = record.chunk; 这么一步步来的。 当然了,第一次都是空的,也就是 get 不到东西 mChunkFiles.get(chunkIndex); 和 Record record = mIndexMap.get(key); 都 get 不到,那么第一次就先把东西放进去, mIndexMap.put(key, new Record (chunkIndex, record.offset, data.length, record.sizeOnDisk, timestamp)); (记录 key 值)以及 final String chunkFilePath = mCacheDirectoryPath + CHUNK_FILE_PREFIX + chunk; chunkFile = new RandomAccessFile(chunkFilePath, "rw");mChunkFiles.put(chunk, chunkFile); (三句代码来新建 一个 chunkfile 并放到 cache 列表里面) 注意: Record 是内部类,只是一个数据集合类而已,相当于文件描述信息。每个 cache (即 chunk )对应一个。 private final LongSparseArray mChunkFiles = new LongSparseArray(); 中 mChunkFiles 最大装 13 个,每个 chunk 是 1M, 所以全部 Cache 是 13M. Gallery3d 代码分析之渲染流程 文章分类:移动开发 RenderView gallery3d 的渲染从 RenderView 开始。RenderView 从 GLSurfaceView 继承而来,采用了通 知型绘制模式,即通过调用 requestRender 通知 RenderView 重绘屏幕。 RenderView 将所有需要绘制的对象都保存一个 Lists 中,Lists 包含了 5 个 ArrayList,其定义 如下所示: Java 代码 1. public final ArrayList updateList = new ArrayList(); 2. public final ArrayList opaqueList = new ArrayList(); 3. public final ArrayList blendedList = new ArrayList(); 4. public final ArrayList hitTestList = new ArrayList(); 5. public final ArrayList systemList = new ArrayList(); RenderView 的 onDrawFrame 接口完成每一帧的绘制操作,绘制时遍历 lists 里每个 list 的 每一个成员并调用其 renderXXX 函数。主要代码如下所示: Java 代码 1. ... 2. final Lists lists = sLists; 3. 4. final ArrayList updateList = lists.updateList; 5. boolean isDirty = false; 6. for (int i = 0, size = updateList.size(); i != size; ++i) { 7. boolean retVal = updateList.get(i).update(this, mFrameInterval); 8. isDirty |= retVal; 9. } 10. if (isDirty) { 11. requestRender(); 12. } 13. 14. // Clear the depth buffer. 15. gl.glClear(GL11.GL_DEPTH_BUFFER_BIT); 16. gl.glEnable(GL11.GL_SCISSOR_TEST); 17. gl.glScissor(0, 0, getWidth(), getHeight()); 18. 19. // Run the opaque pass. 20. gl.glDisable(GL11.GL_BLEND); 21. final ArrayList opaqueList = lists.opaqueList; 22. for (int i = opaqueList.size() - 1; i >= 0; --i) { 23. final Layer layer = opaqueList.get(i); 24. if (!layer.mHidden) { 25. layer.renderOpaque(this, gl); 26. } 27. } 28. 29. // Run the blended pass. 30. gl.glEnable(GL11.GL_BLEND); 31. final ArrayList blendedList = lists.blendedList; 32. for (int i = 0, size = blendedList.size(); i != size; ++i) { 33. final Layer layer = blendedList.get(i); 34. if (!layer.mHidden) { 35. layer.renderBlended(this, gl); 36. } 37. } 38. gl.glDisable(GL11.GL_BLEND); lists 的各个 list 里包含的各个 layer 如下所示: Java 代码 1. lists 2. |------------------|-----------------|-----------------|---------------| 3. updateList opaqueList blendedList systemList hitTestList 4. | | | | | 5. GridLayer GridLayer GridLayer GridLayer GridLayer 6. BackgroudLayer BackgroudLayer BackgroudLayer 7. HudLayer HudLayer HudLayer HudLayer 8. TimeBar TimeBar TimeBar 9. PathBar PathBar PathBar 10. XXXButton XXXButton XXXButton 11. XXXMenu XXXMenu XXXMenu Layer 类提供了 update(...), renderOpaque (...), renderBlended (...) 接口,从上面 RenderView 的 onDrawFrame 绘制代码可以看到,这些接口被调用。 Java 代码 1. public abstract class Layer { 2. ... ... 3. 4. public abstract void generate(RenderView view, RenderView.Lists lists); 5. 6. public boolean update(RenderView view, float frameInterval) { 7. return false; 8. } 9. 10. public void renderOpaque(RenderView view, GL11 gl) { 11. } 12. 13. public void renderBlended(RenderView view, GL11 gl) { 14. } 15. ... ... 16. 17. } GridLayer GridLayer 中有个 GridDrawManager,专门负责绘制。 下面是 GridDrawManager 的构造函数,从其参数里可以看出些门道。 Java 代码 1. mDrawManager = new GridDrawManager(context, mCamera, mDrawables, sDisplayList, sDisplayItems, sDisplaySlots); Gallery 3D 代码分析之 GLSurfaceView 文章分类:移动开发 简介 SDK 中的 android.opengl.GLSurfaceView 类提供如下功能:  在 OpenGL ES 和 View 系统之间建立联系;  使得 OpenGL ES 可以工作在 Activity 生命周期中;  可选择合适的 frame buffer 像素格式;  创建并管理一个单独的渲染线程,可以实现平滑的动画;  提供 debugging 工具和 API。 一个简单的 GLSurfaceView 应用 Java 代码 1. package com.example.android.apis.graphics; 2. 3. import javax.microedition.khronos.egl.EGLConfig; 4. import javax.microedition.khronos.opengles.GL10; 5. 6. import android.app.Activity; 7. import android.opengl.GLSurfaceView; 8. import android.os.Bundle; 9. 10. public class ClearActivity extends Activity { 11. @Override 12. protected void onCreate(Bundle savedInstanceState) { 13. super.onCreate(savedInstanceState); 14. mGLView = new GLSurfaceView(this); 15. mGLView.setRenderer(new ClearRenderer()); 16. setContentView(mGLView); 17. } 18. 19. @Override 20. protected void onPause() { 21. super.onPause(); 22. mGLView.onPause(); 23. } 24. 25. @Override 26. protected void onResume() { 27. super.onResume(); 28. mGLView.onResume(); 29. } 30. 31. private GLSurfaceView mGLView; 32. } 33. 34. class ClearRenderer implements GLSurfaceView.Renderer { 35. public void onSurfaceCreated(GL10 gl, EGLConfig config) { 36. // Do nothing special. 37. } 38. 39. public void onSurfaceChanged(GL10 gl, int w, int h) { 40. gl.glViewport(0, 0, w, h); 41. } 42. 43. public void onDrawFrame(GL10 gl) { 44. gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 45. } 46. } 这个程序功能很简单,每帧绘制时将屏幕设置成黑色。但它是一个完整的工作在 Activity 生 命周期中的 OpenGL 程序。当 activity 暂停时,它暂停渲染;当 activity 继续时,它继续 渲染。可以将这个程序用作非交互式的 demo 程序。可以在 ClearRenderer.onDrawFrame() 接口中增加 OpenGL 调用做很多的绘制。 GLSurfaceView.Render 接口有三个方法: * onSurfaceCreated():该方法在渲染开始前调用,OpenGL ES 的绘制上下文被重建时也会被 调用。当 activity 暂停时绘制上下文会丢失,当 activity 继续时,绘制上下文会被重建。另 外,创建长期存在的 OpenGL 资源(如 texture)往往也在这里进行。 * onSurfaceChanged():当 surface 的尺寸发生改变时该方法被调用。往往在这里设置 viewport。若你的 camera 是固定的,也可以在这里设置 camera。 * onDrawFrame():每帧都通过该方法进行绘制。绘制时通常先调用 glClear 函数来清空 framebuffer,然后在调用 OpenGL ES 的起它的接口进行绘制。 输入如何处理 若是开发一个交互型的应用(如游戏),通常需要子类化 GLSurfaceView,由此可以获取输入 事件。下面有个例子: Java 代码 1. package com.google.android.ClearTest; 2. 3. import javax.microedition.khronos.egl.EGLConfig; 4. import javax.microedition.khronos.opengles.GL10; 5. 6. import android.app.Activity; 7. import android.content.Context; 8. import android.opengl.GLSurfaceView; 9. import android.os.Bundle; 10. import android.view.MotionEvent; 11. 12. public class ClearActivity extends Activity { 13. @Override 14. protected void onCreate(Bundle savedInstanceState) { 15. super.onCreate(savedInstanceState); 16. mGLView = new ClearGLSurfaceView(this); 17. setContentView(mGLView); 18. } 19. 20. @Override 21. protected void onPause() { 22. super.onPause(); 23. mGLView.onPause(); 24. } 25. 26. @Override 27. protected void onResume() { 28. super.onResume(); 29. mGLView.onResume(); 30. } 31. 32. private GLSurfaceView mGLView; 33. } 34. 35. class ClearGLSurfaceView extends GLSurfaceView { 36. public ClearGLSurfaceView(Context context) { 37. super(context); 38. mRenderer = new ClearRenderer(); 39. setRenderer(mRenderer); 40. } 41. 42. public boolean onTouchEvent(final MotionEvent event) { 43. queueEvent(new Runnable(){ 44. public void run() { 45. mRenderer.setColor(event.getX() / getWidth(), 46. event.getY() / getHeight(), 1.0f); 47. }}); 48. return true; 49. } 50. 51. ClearRenderer mRenderer; 52. } 53. 54. class ClearRenderer implements GLSurfaceView.Renderer { 55. public void onSurfaceCreated(GL10 gl, EGLConfig config) { 56. // Do nothing special. 57. } 58. 59. public void onSurfaceChanged(GL10 gl, int w, int h) { 60. gl.glViewport(0, 0, w, h); 61. } 62. 63. public void onDrawFrame(GL10 gl) { 64. gl.glClearColor(mRed, mGreen, mBlue, 1.0f); 65. gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 66. } 67. 68. public void setColor(float r, float g, float b) { 69. mRed = r; 70. mGreen = g; 71. mBlue = b; 72. } 73. 74. private float mRed; 75. private float mGreen; 76. private float mBlue; 77. } 其他的 GLSurfaceView 例子 在 Android SDK 的 API Demo 例子程序中还有很多例子:  GLSurfaceView  Kube  Translucent GLSurfaceView:透明背景  Textured Triangle:纹理贴图  Sprite Text:在 texture 上写文本并显示在 3D 场景中  Touch Rotate:旋转 3D 对象 选择一个 Surface GLSurfaceView 提供了接口可选择 surface 的类型。默认情况下, GLSurfaceView 会使用一 个 16 位 RGB frame buffer,带 16 位深度。你也可以根据自己的需要进行选择,比如在 Translucent GLSurfaceView 例子里,需要一个 Alpha 通道来实现透明。GLSurfaceView 提供 了 setEGLSurfaceChooser()方法来选择 surface。 选择一个 RGB (565)的 16 位 framebuffer,接口如下: Java 代码 1. setEGLConfigChooser(boolean needDepth) 若要定制 red, green, blue, alpha 和 depth,则用如下接口: Java 代码 1. setEGLConfigChooser(int redSize, int greenSize,int blueSize, int alphaSize,int depthSize, in t stencilSize) 使用自己实现的 EGLConfigChooser,用如下的接口: Java 代码 1. setEGLConfigChooser(EGLConfigChooser configChooser) 持续型渲染模式 & 通知型渲染模式 大多数 3D 应用,如游戏、模拟等都是持续型渲染的动画,还有些 3D 应用是反应式的 (reactive),它们往往先被动等待,当用户有了动作再做出反应。对于这种应用,持续渲染屏 幕是浪费时间。若开发反应式的应用,可以调用下面的方法 Java 代码 1. GLSurfaceView.setRenderMode(RENDERMODE_WHEN_DIRTY); 停止持续渲染。当调用 Java 代码 1. GLSurfaceView.requestRender() 时,程序再渲染屏幕。 调试 GLSurfaceView.setDebugFlags() 方法可以激活 log 或者错误检测,它们可以帮助调试 OpenGL ES 调用。具体使用时,在 GLSurfaceView 的构造函数中,调用 setRender() 之前 调用 GLSurfaceView.setDebugFlags()就可以了。下面是个例子: Java 代码 1. public ClearGLSurfaceView(Context context) { 2. super(context); 3. // Turn on error-checking and logging 4. setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS); 5. mRenderer = new ClearRenderer(); 6. setRenderer(mRenderer); 7. }
还剩234页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 15 金币 [ 分享pdf获得金币 ] 8 人已下载

下载pdf

pdf贡献者

linole

贡献于2011-12-01

下载需要 15 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf