在 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的更多相关文章

  1. Android 仿Win8的metro的UI界面(上)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/23441455 昨晚没事手机下载了一些APP,发现现在仿win8的主界面越来越多, ...

  2. Android仿WIN8系统磁贴点击下沉倾斜效果

    ※效果 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGluZ2xvbmd4aW4yNA==/font/5a6L5L2T/fontsize/400/fil ...

  3. Android仿Win8界面的button点击

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

  4. android仿win8 metro磁贴布局

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

  5. VC/Wince 实现仿Win8 Metro风格界面2——页面滑动切换(附效果图)

    前几天开始写仿Win8 Metro界面文章,部分网友觉得不错,感谢各位的意见.本来今天一直在折腾Android VLC播放器,没时间写.不过明天休息,所以今天就抽时间先写一下. 言归正传,我们都知道W ...

  6. VC/Wince 实现仿Win8 Metro风格界面1——设计概述和自绘Button(附效果图)

    去年用VC做了一个仿Win8 Metro风格的界面,感觉挺有意思,最近打算把实现过程和一些技术原理记录下来. 主要是风格上类似Win8,其实功能上很多借鉴了Android的操作方式.界面只支持两种大小 ...

  7. 仿win8磁贴界面以及功能

    做移动产品界面占很大的一部分,同时也是决定一款产品好的的重要因素,最近看见有人放win8的界面效果,搜了两款,一款是只是仿界面没有特效,另一款是自定义组件能够实现反转效果,今天分析一下这两类界面. 仿 ...

  8. Android 仿微信小视频录制

    Android 仿微信小视频录制 WechatShortVideo和WechatShortVideo文章

  9. WPF自定义控件之仿Win8滚动条--ScrollViewer

    1.说明 自己学习WPF不是很久,现将自己做的一些小项目中用到的自定义控件整理出来,方便以后使用,不尽人意之处,还请多多批评与指导,现在就来实现自定义ScrollViewer仿Win8滚动条 2.效果 ...

随机推荐

  1. Elasticsearch 5.x安装

    node1 elasticsearch node2 elasticsearch node3 elasticsearch 前期准备 JDK1.8 修改/etc/security/limits.conf ...

  2. linux系统环境下的静态库和动态库的制作

    linux系统下的应用编程需要系统提供的库文件,包括静态库或动态库.不管是静态库还是动态库,都是编译好的二进制文件.在我们编译程序时要链接的目标文件,静态库是链接的时候直接编译到程序里,和程序成为一体 ...

  3. 《黑客攻防技术宝典Web实战篇@第2版》读书笔记1:了解Web应用程序

    读书笔记第一部分对应原书的第一章,主要介绍了Web应用程序的发展,功能,安全状况. Web应用程序的发展历程 早期的万维网仅由Web站点构成,只是包含静态文档的信息库,随后人们发明了Web浏览器用来检 ...

  4. 【Hadoop故障处理】高可用(HA)环境DataNode问题

    [故障背景] NameNode和DataNode进程正常运行,但是网页找不到DataNode,DataNode为空.各个节点机器之间可以ping同主机名. [日志排查] 众多日志中找到如下关键点错误信 ...

  5. Hadoop-Hive学习笔记(1)

    1. Hive什么 a.Hive是基于Hadoop的一个数据仓库工具(注意不是数据仓库),将结构化的数据文件映射成一张数据库表. b.Hive是SQL的解析引擎,可以把sql语句转换成MapReduc ...

  6. java端连接zookeeper出现unknowHostException错误

    连接zookeeper出现异常:unknowHostException 出现这种错误一开始以为是zookeeper的配置文件出了问题,所以一直在找配置文件的问题,但是zookeeper在虚拟机里面是可 ...

  7. 『Python基础-13』函数 Function

    这篇笔记记录的知识点: 函数的基本概念 自定义函数 函数的几种参数 编程的三种方式: 1.OOP 面向对象编程,万物皆对象,以class为主,抽象化 2.POP 面向过程编程,万事皆过程,def定义过 ...

  8. python网络编程之进程

    一.什么是进程 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本执行实 ...

  9. Java学习笔记十八:Java面向对象的三大特性之封装

    Java面向对象的三大特性之封装 一:面向对象的三大特性: 封装 继承 多态   二:封装的概念: 将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访 ...

  10. MCUXpresso release build 时提示GFLIB等函数未引用的问题

    MCUXpresso release build 时提示 GFLIB 等函数未引用的问题 最近在使用 MCUXpresso 编译工程时选择 Debug(Debug build) 能顺利编译,但是选择 ...