转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/23441455

昨晚没事手机下载了一些APP,发现现在仿win8的主界面越来越多,在大家见惯了类GridView或者类Tab后,给人一种耳目一新的感觉。今天在eoe上偶然发现已经有人实现了这个功能的源码(地址:http://www.eoeandroid.com/forum.php?mod=viewthread&tid=327557),马上下载跑了一下,效果很炫,但是有些bug,比如点击速度特别快时图像会被放大,以及点击时会触发两次点击事件。

本例子基于eoe中这位大神的实现,做了一些简化,和bug的修复。

效果:

首先普及一个小知识点:

我们在项目中有时候需要一个缓慢的梯度数据,例如:控件的宽度以一定的比例增加,然后以相同的比例还原到原来的长度。

  1. package com.zhy._01;
  2. public class Test2
  3. {
  4. public static void main(String[] args)
  5. {
  6. float val = 1;
  7. float s = 0.85f;
  8. int i = 0;
  9. s = (float) Math.sqrt(1 / s);
  1. System.out.println(val);
  2. while (i < 5)
  3. {
  4. val = val *s ;
  5. System.out.println(val);
  6. i++;
  7. }
  8. s = 0.85f;
  9. i = 0;
  10. s = (float) Math.sqrt(s);
  11. while (i < 5)
  12. {
  13. val = val *s ;
  14. System.out.println(val);
  15. i++;
  16. }
  17. }

输出结果:

  1. 1.0
  2. 1.0846523
  3. 1.1764706
  4. 1.2760615
  5. 1.384083
  6. 1.5012488
  7. 1.384083
  8. 1.2760615
  9. 1.1764706
  10. 1.0846523
  11. 1.0

很完美吧,基本是个对称的梯度数据,梯度的幅度由代码中的s觉得,越接近1幅度越小,反之则反之。

好了下面开始代码:

1、布局文件

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="fill_parent"
  4. android:layout_height="fill_parent"
  5. android:background="@drawable/bkg_img_default"
  6. android:gravity="center"
  7. android:orientation="vertical" >
  8. <LinearLayout
  9. android:layout_width="wrap_content"
  10. android:layout_height="wrap_content"
  11. android:orientation="vertical" >
  12. <LinearLayout
  13. android:layout_width="wrap_content"
  14. android:layout_height="wrap_content"
  15. android:orientation="horizontal" >
  16. <LinearLayout
  17. android:layout_width="wrap_content"
  18. android:layout_height="wrap_content"
  19. android:orientation="vertical" >
  20. <com.ljp.ani01.MyImageView
  21. android:id="@+id/c_joke"
  22. android:layout_width="wrap_content"
  23. android:layout_height="wrap_content"
  24. android:layout_margin="2dp"
  25. android:scaleType="matrix"
  26. android:src="@drawable/left_top" />
  27. <com.ljp.ani01.MyImageView
  28. android:id="@+id/c_idea"
  29. android:layout_width="wrap_content"
  30. android:layout_height="wrap_content"
  31. android:layout_margin="2dp"
  32. android:scaleType="matrix"
  33. android:src="@drawable/left_bottom" />
  34. </LinearLayout>
  35. <com.ljp.ani01.MyImageView
  36. android:id="@+id/c_constellation"
  37. android:layout_width="wrap_content"
  38. android:layout_height="wrap_content"
  39. android:layout_margin="2dp"
  40. android:scaleType="matrix"
  41. android:src="@drawable/right" />
  42. </LinearLayout>
  43. <com.ljp.ani01.MyImageView
  44. android:id="@+id/c_recommend"
  45. android:layout_width="wrap_content"
  46. android:layout_height="wrap_content"
  47. android:layout_margin="2dp"
  48. android:scaleType="matrix"
  49. android:src="@drawable/bottom" />
  50. </LinearLayout>
  51. </LinearLayout>

布局文件,完成了上面效果图的静态效果,如果你不需要添加点击动画,或者只需要很简单的点击效果,那么就已经完成这样的菜单的编写,再添加个backgroud自定义下点击效果就好了。当然,我们这里有个比较柔和的点击动画,有自定义的ImageView完成。

2、MyImageView.java

  1. package com.ljp.ani01;
  2. import android.content.Context;
  3. import android.graphics.Matrix;
  4. import android.graphics.drawable.BitmapDrawable;
  5. import android.graphics.drawable.Drawable;
  6. import android.os.Handler;
  7. import android.util.AttributeSet;
  8. import android.util.Log;
  9. import android.view.MotionEvent;
  10. import android.widget.ImageView;
  11. public class MyImageView extends ImageView
  12. {
  13. private static final String TAG = "MyImageView";
  14. private static final int SCALE_REDUCE_INIT = 0;
  15. private static final int SCALING = 1;
  16. private static final int SCALE_ADD_INIT = 6;
  17. /**
  18. * 控件的宽
  19. */
  20. private int mWidth;
  21. /**
  22. * 控件的高
  23. */
  24. private int mHeight;
  25. /**
  26. * 控件的宽1/2
  27. */
  28. private int mCenterWidth;
  29. /**
  30. * 控件的高 1/2
  31. */
  32. private int mCenterHeight;
  33. /**
  34. * 设置一个缩放的常量
  35. */
  36. private float mMinScale = 0.85f;
  37. /**
  38. * 缩放是否结束
  39. */
  40. private boolean isFinish = true;
  41. public MyImageView(Context context)
  42. {
  43. this(context, null);
  44. }
  45. public MyImageView(Context context, AttributeSet attrs)
  46. {
  47. this(context, attrs, 0);
  48. }
  49. public MyImageView(Context context, AttributeSet attrs, int defStyle)
  50. {
  51. super(context, attrs, defStyle);
  52. }
  53. /**
  54. * 必要的初始化
  55. */
  56. @Override
  57. protected void onLayout(boolean changed, int left, int top, int right, int bottom)
  58. {
  59. super.onLayout(changed, left, top, right, bottom);
  60. if (changed)
  61. {
  62. mWidth = getWidth() - getPaddingLeft() - getPaddingRight();
  63. mHeight = getHeight() - getPaddingTop() - getPaddingBottom();
  64. mCenterWidth = mWidth / 2;
  65. mCenterHeight = mHeight / 2;
  66. Drawable drawable = getDrawable();
  67. BitmapDrawable bd = (BitmapDrawable) drawable;
  68. bd.setAntiAlias(true);
  69. }
  70. }
  71. @Override
  72. public boolean onTouchEvent(MotionEvent event)
  73. {
  74. switch (event.getAction())
  75. {
  76. case MotionEvent.ACTION_DOWN:
  77. float X = event.getX();
  78. float Y = event.getY();
  79. mScaleHandler.sendEmptyMessage(SCALE_REDUCE_INIT);
  80. break;
  81. case MotionEvent.ACTION_UP:
  82. mScaleHandler.sendEmptyMessage(SCALE_ADD_INIT);
  83. break;
  84. }
  85. return true;
  86. }
  87. /**
  88. * 控制缩放的Handler
  89. */
  90. private Handler mScaleHandler = new Handler()
  91. {
  92. private Matrix matrix = new Matrix();
  93. private int count = 0;
  94. private float s;
  95. /**
  96. * 是否已经调用了点击事件
  97. */
  98. private boolean isClicked;
  99. public void handleMessage(android.os.Message msg)
  100. {
  101. matrix.set(getImageMatrix());
  102. switch (msg.what)
  103. {
  104. case SCALE_REDUCE_INIT:
  105. if (!isFinish)
  106. {
  107. mScaleHandler.sendEmptyMessage(SCALE_REDUCE_INIT);
  108. } else
  109. {
  110. isFinish = false;
  111. count = 0;
  112. s = (float) Math.sqrt(Math.sqrt(mMinScale));
  113. beginScale(matrix, s);
  114. mScaleHandler.sendEmptyMessage(SCALING);
  115. }
  116. break;
  117. case SCALING:
  118. beginScale(matrix, s);
  119. if (count < 4)
  120. {
  121. mScaleHandler.sendEmptyMessage(SCALING);
  122. } else
  123. {
  124. isFinish = true;
  125. if (MyImageView.this.mOnViewClickListener != null && !isClicked)
  126. {
  127. isClicked = true;
  128. MyImageView.this.mOnViewClickListener.onViewClick(MyImageView.this);
  129. } else
  130. {
  131. isClicked = false;
  132. }
  133. }
  134. count++;
  135. break;
  136. case 6:
  137. if (!isFinish)
  138. {
  139. mScaleHandler.sendEmptyMessage(SCALE_ADD_INIT);
  140. } else
  141. {
  142. isFinish = false;
  143. count = 0;
  144. s = (float) Math.sqrt(Math.sqrt(1.0f / mMinScale));
  145. beginScale(matrix, s);
  146. mScaleHandler.sendEmptyMessage(SCALING);
  147. }
  148. break;
  149. }
  150. }
  151. };
  152. protected void sleep(int i)
  153. {
  154. try
  155. {
  156. Thread.sleep(i);
  157. } catch (InterruptedException e)
  158. {
  159. e.printStackTrace();
  160. }
  161. }
  162. /**
  163. * 缩放
  164. *
  165. * @param matrix
  166. * @param scale
  167. */
  168. private synchronized void beginScale(Matrix matrix, float scale)
  169. {
  170. matrix.postScale(scale, scale, mCenterWidth, mCenterHeight);
  171. setImageMatrix(matrix);
  172. }
  173. /**
  174. * 回调接口
  175. */
  176. private OnViewClickListener mOnViewClickListener;
  177. public void setOnClickIntent(OnViewClickListener onViewClickListener)
  178. {
  179. this.mOnViewClickListener = onViewClickListener;
  180. }
  181. public interface OnViewClickListener
  182. {
  183. void onViewClick(MyImageView view);
  184. }
  185. }

代码不算复杂,主要就是对onTouchEvent的Action_Down和Action_Up的监听,然后通过Handler结合matrix完成缩放的效果。这里简单说一个mScaleHandler里面代码的逻辑,当检测到ACTION_DOWN事件,会判断当前缩放是否完成,如果完成了则添加缩小的效果,如果没有,则一直检测。ACTION_UP也是同样的过程。缩放的梯度就用到了文章开始介绍的小知识点。

有人会觉得使用Handler比较麻烦,这里一直使用Handler.sendMsg的原因是,利用了这个消息队列,队列先进先出,保证动画效果的流畅。因为ACTION_DOWN_与ACTION_UP一瞬点完成的,其实动画还在进行。如果你在onTouchEvent中用while集合sleep完成动画,会出现卡死,监听不到Up事件等问题。

3、主Activity

  1. package com.ljp.ani01;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.view.View;
  5. import android.view.View.OnClickListener;
  6. import android.widget.Toast;
  7. public class TestRolateAnimActivity extends Activity
  8. {
  9. MyImageView joke;
  10. @Override
  11. public void onCreate(Bundle savedInstanceState)
  12. {
  13. super.onCreate(savedInstanceState);
  14. setContentView(R.layout.main);
  15. joke = (MyImageView) findViewById(R.id.c_joke);
  16. joke.setOnClickIntent(new MyImageView.OnViewClickListener()
  17. {
  18. @Override
  19. public void onViewClick(MyImageView view)
  20. {
  21. Toast.makeText(TestRolateAnimActivity.this, "Joke", 1000).show();
  22. }
  23. });
  24. }
  25. }

利用提供的回调接口注册了点击事件。这里说明一下,现在为ImageView设置OnClickLIstener是没有作用的,因为自定义的ImageView的onTouchEvent直接返回了true,不会往下执行click事件,如果你希望通过OnClickLIstener进行注册,你可以把ontouchevent里面返回值改成super.ontouchevent(event),并且需要将ImageView的clickable设置为true。这些都是Ontouch事件的传播机制,不了解的google下,还是很有必要的。

如果你觉得这篇文章对你有用,可以顶一个~~

源码下载点击此处

Android 仿Win8的metro的UI界面(上)的更多相关文章

  1. Android 仿PhotoShop调色板应用(三) 主体界面绘制

    版权声明:本文为博主原创文章,未经博主允许不得转载. Android 仿PhotoShop调色板应用(三) 主体界面绘制    关于PhotoShop调色板应用的实现我总结了两个最核心的部分:   1 ...

  2. Unity在UI界面上显示3D模型/物体,控制模型旋转

    Unity3D物体在UI界面的显示 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- ...

  3. 在Android中实现service动态更新UI界面

    之前曾介绍过Android的UI设计与后台线程交互,据Android API的介绍,service一般是在后台运行的,没有界面的.那么如何实现service动态更新UI界面呢?案例:通过service ...

  4. Android Handler传递参数动态更新UI界面demo

    package com.example.demo_test; import android.app.Activity; import android.os.Bundle; import android ...

  5. android中实现service动态更新UI界面

    案例:通过service向远程服务器发送请求,根据服务器返回的结果动态更新主程序UI界面,主程序可实时关闭或重启服务. 注册BroadcastReceiver 在主程序activity中注册一个Bro ...

  6. Flash Stage3D 在2D UI 界面上显示3D模型问题完美解决

    一直以来很多Stage3D开发者都在为3D模型在2DUI上显示的问题头疼.Stage3D一直是在 Stage2D下面.为了做到3D模型在2DUI上显示通常大家有几种实现方式,下面来说说这几种实现方式吧 ...

  7. android仿win8 metro磁贴布局

    代码下载     //更新代码,   这里是更新后的代码 //////////////////////// 1,含一个图片无限滚动的控件,自己实现的 2.可新增删除每个磁贴 3.来个图片吧 ////* ...

  8. Android基础总结(3)——UI界面布局

    Android的UI设计有好几种界面程序编写方式.大体上可分为两大类:一类是利用可视化工具来进行,允许你进行拖拽控件来进行布局:还有一类是编写xml文档来进行布局.这两种方法可以相互转换. 1.常见的 ...

  9. Android仿Win8界面的button点击

    今天没事的时候,感觉Win8的扁平化的button还是挺好看的,就研究了下怎样在安卓界面实现Win8的扁平化button点击效果. 发现了一个自己定义的View能够实现扁平化button效果,话不多说 ...

随机推荐

  1. [转]Delphi : keydown与keypress的区别,组合键

    Shift 是一个集合变量. type TShiftState = set of (ssShift, ssAlt, ssCtrl, ssLeft, ssRight, ssMiddle, ssDoubl ...

  2. indexedDB bootstrap angularjs 前端 MVC Demo

    前端之MVC应用 1.indexedDB(Model): 数据层,前端浏览器 HTML5 API 面向对象数据库,一般现在用的数据库都是关系型数据库. 那么indexeddb有什么特点呢: 首先,从字 ...

  3. cache—主存—辅存三级调度模拟

    近日,在体系结构的课程中,老师留了一个上机作业,为cache—主存—辅存三级调度模拟,要求如下: 实现三级存储体系的模拟调度程序 描述:CPU在cache访问数据块,若命中给出对应的cache实地址, ...

  4. 最短路径算法——Dijkstra,Bellman-Ford,Floyd-Warshall,Johnson

    根据DSqiu的blog整理出来 :http://dsqiu.iteye.com/blog/1689163 PS:模板是自己写的,如有错误欢迎指出~ 本文内容框架: §1 Dijkstra算法 §2 ...

  5. 02_ Windows与Linux双重引导

    1. Grub2引导window. ---------------------步骤1--------------------------------- vim /etc/grub.d/40_custo ...

  6. 清除div浮动的三种方式

    html: <body> <div class="main"> <div class="first"></div> ...

  7. Mesh绘制雷达图(UGUI)

    参考资料:http://www.cnblogs.com/jeason1997/p/5130413.html ** 描述:雷达图 刷新 radarDate.SetVerticesDirty(); usi ...

  8. 机器学习公开课~~~~mooc

    https://class.coursera.org/ntumlone-001/class/index

  9. qt 运行提示:error: cannot find -lGL

    安装:libgl1-mesa-dev问题解决 y@y:~$ sudo apt-get install libgl1-mesa-dev

  10. 脚本两则--用于快速部署HADOOP,SPARK这些(特别是VM虚拟机模板部署出来的)。。

    感觉可能只是适合我自己的部署习惯吧,且只针对CENTOS6及以下版本,以后有时间,可能还是要改进.. 1,从VM的模块产生的虚拟机,如何快速搞定网络配置? #!/bin/bash #usage:./i ...