好久没有写博客了,上一篇博文距现在都有七个多月了,实在是惭愧。但是这段时间仍然是在忙于项目或是自我充电。这几天实现了一个基于GridView的翻牌动画效果,这里就将其整理出来同各位分享。
一、整体介绍
GridView设置15个Item(5*3),刚好满屏显示(没有ScrollBar),没有点击某个Item前可以使用摇一摇功能对GridView中的图片进行切换,点击某个Item时对应的图片放大,然后实现“翻牌”效果,并将该Item中显示的图片切换为对应的文字。随后所有其他的Item也自动实现翻牌效果。
(1)目录结构
(2)效果图
二、详细介绍
按上面的目录结构从上致下
1、GridAdapter 继承至 BaseAdapter
重点代码:
(1)自定义的一个Item touch事件监听接口
1 public interface OnItemTouchedListener { 2 public boolean onItemTouch (View v, MotionEvent event, int position); 3 }
(2)设置OnItemTouchedListener
1 public void setOnItemTouchedListener(OnItemTouchedListener onItemTouchedListener) { 2 this.listener = onItemTouchedListener; 3 }
(3)getView()函数中动态设置 Item的高、宽加载网络图片为每个Item设置OnTouchListener
1 @Override 2 public View getView(final int position, View convertView, ViewGroup parent) { 3 LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 4 convertView = inflater.inflate(R.layout.grid_item, parent, false); 5 6 LayoutParams layoutParams = convertView.getLayoutParams(); 7 layoutParams.width = viewWidth; 8 layoutParams.height = viewHeight; 9 convertView.setLayoutParams(layoutParams); 10 ImageView imageView = (ImageView) convertView.findViewById(R.id.grid_image); 11 12 DisplayImageOptions options = new DisplayImageOptions.Builder()// 13 .cacheInMemory(true)// 14 .cacheOnDisc(true)// 15 .bitmapConfig(Config.RGB_565)// 16 .build(); 17 ImageLoader.getInstance().displayImage(urlArray.get(position), 18 imageView, options); 19 convertView.setOnTouchListener(new OnTouchListener() { 20 21 @Override 22 public boolean onTouch(View v, MotionEvent event) { 23 24 return listener.onItemTouch(v, event, position); 25 } 26 }); 27 28 return convertView; 29 }
2、RotateAnimation
参考于github上jianghejie的3DNumberRotate项目中的NumberRotate3DAnimation类,基于Camera实现数字3D翻转动画。
3、自定义的Application类
项目中使用了universal-image-loader加载网络图片,在这里对ImageLoader进行初始化:
1 private void initImageLoader() { 2 3 DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder() // 4 .showImageForEmptyUri(R.mipmap.empty_img) // 5 .showImageOnFail(R.mipmap.empty_img) // 6 .cacheInMemory(true) // 7 .cacheOnDisc(true) // 8 .build();// 9 10 File cacheDir = StorageUtils.getCacheDirectory(getApplicationContext()); 11 ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder( 12 getApplicationContext())// 13 .memoryCache(new LruMemoryCache(5 * 1024 * 1024))// 14 .memoryCacheSize(10 * 1024 * 1024)// 15 .defaultDisplayImageOptions(defaultOptions)// 16 .discCache(new UnlimitedDiscCache(cacheDir))// 17 .discCacheFileNameGenerator(new HashCodeFileNameGenerator())// 18 .build(); 19 ImageLoader.getInstance().init(config); 20 }
4、util包中的几个工具类
(1)Constants:放一些常量,这里我存放的是GridView中网络图片的路径;
(2)DisplayUtil:这是关于显示的一个工具类,包括获取屏幕高宽、dp转px等功能;
(3)ItemCenterMeasure:这个类是设计用来根据GridView高宽计算Item尺寸的,其实可以省去,或者直接归并到DisplayUtil中;
5、MainActivity中功能较多写的比较杂乱
主要代码:
(1)Adapter设置自定义的OnItemTouchedListener
1 mAdapter.setOnItemTouchedListener(new GridAdapter.OnItemTouchedListener() { 2 3 @Override 4 public boolean onItemTouch(View v, MotionEvent event, int position) { 5 mView = v; 6 currentPos = position; 7 if(event.getAction() == MotionEvent.ACTION_DOWN){ 8 if (isClicked) { 9 Toast toast = Toast.makeText(context, getString(R.string.warning), 10 Toast.LENGTH_SHORT); 11 toast.setGravity(Gravity.CENTER, 0, 0); 12 toast.show(); 13 return false; 14 } else{ 15 //play sound 16 soundPool.play(music, 1, 1, 0, 0, 1); 17 //trigger zoom animation on items 18 ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 1.1f, 1.0f, 1.1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); 19 scaleAnimation.setDuration(500); 20 AnimationSet animationSet = new AnimationSet(true); 21 animationSet.addAnimation(scaleAnimation); 22 animationSet.setFillAfter(true); 23 animationSet.setAnimationListener(new Animation.AnimationListener() { 24 25 @Override 26 public void onAnimationStart(Animation animation) { 27 28 } 29 30 @Override 31 public void onAnimationRepeat(Animation animation) { 32 33 } 34 35 @Override 36 public void onAnimationEnd(Animation animation) { 37 enableRefreshFirst = true; 38 RotateAnimation rotateAnim = null; 39 40 float cX = mView.getWidth() / 2.0f; 41 float cY = mView.getHeight() / 2.0f; 42 rotateAnim = new RotateAnimation(cX, cY); 43 44 if (rotateAnim != null) { 45 rotateAnim.setInterpolatedTimeListener(MainActivity.this, mView); 46 rotateAnim.setFillAfter(true); 47 rotateAnim.setAnimationListener(new Animation.AnimationListener() { 48 49 @Override 50 public void onAnimationStart(Animation animation) { 51 52 } 53 54 @Override 55 public void onAnimationRepeat(Animation animation) { 56 57 } 58 59 @Override 60 public void onAnimationEnd(Animation animation) { 61 handler.postDelayed(new Runnable() { 62 63 @Override 64 public void run() { 65 otherItemRotate(); 66 } 67 }, 500); 68 } 69 }); 70 mView.startAnimation(rotateAnim); 71 72 } 73 74 isClicked = true; 75 } 76 }); 77 v.startAnimation(animationSet); 78 } 79 } 80 81 return false; 82 } 83 });
(2)动态创建一个TextView,并算出GridView的高、宽
其中计算GridView的高度这一句(DisplayUtil.SCREEN_HEIGHT_PIXELS - DisplayUtil.dp2px(16) * 2 - tvBmHeight - 80)在我设备(分辨率:1920*1080)上要减去80px才能使所有的Item整好全部显示出来,不知道为什么,如果不减去80px,GridViw 中的最后一行Item将会显示不完全也就是说要通过滑动ScrollBar才能看全。这一点还望大神能给予指点。
1 private void createCRTextView() { 2 LinearLayout ll = (LinearLayout) findViewById(R.id.logo_ly); 3 tvBm = new TextView(context); 4 tvBm.setText(getResources().getString(R.string.logo)); 5 tvBm.setTextAppearance(context, R.style.logoTextView); 6 LinearLayout.LayoutParams crParams = new LinearLayout.LayoutParams(GridLayout.LayoutParams.WRAP_CONTENT, GridLayout.LayoutParams.WRAP_CONTENT); 7 crParams.topMargin = 5; 8 crParams.bottomMargin = 10; 9 crParams.gravity = Gravity.CENTER; 10 tvBm.setLayoutParams(crParams); 11 12 tvBm.setOnClickListener(new View.OnClickListener() { 13 14 @Override 15 public void onClick(View v) { 16 ScaleAnimation scaleAnim = new ScaleAnimation(1.0f, 1.2f, 1.0f, 1.2f, 17 Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); 18 scaleAnim.setDuration(500); 19 scaleAnim.setFillAfter(false); 20 tvBm.startAnimation(scaleAnim); 21 } 22 }); 23 24 ll.addView(tvBm); 25 int tvBmHeight = crParams.height + 5 + 10; 26 27 28 gridWidthPix = DisplayUtil.SCREEN_WIDTH_PIXELS - DisplayUtil.dp2px(16) * 2; 29 //I am not sure why the right of next equality should minus 80px to display all items in the gridview without scrollbar in my devices (1 920*1080), 30 //this may make a bad adaption for various devices with different resolution ratio 31 gridHeightPix = DisplayUtil.SCREEN_HEIGHT_PIXELS - DisplayUtil.dp2px(16) * 2 - tvBmHeight - 80; 32 33 34 }
(3)摇一摇触发的时候更新GridView中的图片路径
@Override public void onSensorChanged(SensorEvent event) { int sensorType = event.sensor.getType(); float[] values = event.values; if (sensorType == Sensor.TYPE_ACCELEROMETER) { //values[0] X axis acceleration;values[1] Y axis acceleration;values[2] Z axis acceleration if (Math.abs(values[0]) > 17 || Math.abs(values[1]) > 17 || Math.abs(values[2]) > 17) { if (!isClicked) { vibrator.vibrate(500); mAdapter.setUrls(Constants.getUrls(2)); mGridView.invalidate(); } } } }
6、还有一个自定义的GridView,实现禁止滑动
重写dispatchTouchEvent方法
@Override public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_MOVE) { return true;//禁止gridview滑动 } return super.dispatchTouchEvent(ev); }
7、布局文件这里就不给予说明了,很简单明了的,需要参考的可以直接下源码看。
源码下载链接:
(1)CSDN:需要1个下载积分,积分有点缺您要是愿意打赏请点这里下载;
(2)GitHub:实在吝啬或是没有积分也没关系,请到这里下载,当然也希望你Start一下,或是Fork;
好了到此算是写完了,如果对您有用,劳烦您点个赞或是分享一下;如果您对代码有一些建议,期待您在评论处给予指正。
最近状态有点不佳,送给自己以及各位一句话共勉:
业精于勤 荒于嬉;行成于思 毁于随