在 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. Hibernate 事务不回滚

    问题:               这几天在做开发时,发现事务不回滚了,Service是用AOP加的事务,数据库是MySql, 表全部是InnoDB:   方法回滚是采用spring的手动回滚:   ...

  2. Android 微信页面刷新问题

    今天测试妹纸提了个bug,Android手机用微信打开测试页面,刷新功能无效.因为开发时懒,只验证了Ios手机无异常,没有注意打安卓这个问题. 我是直接用的window.location.reload ...

  3. Java : java基础(6) 反射与枚举

    类需要经过 加载, 连接, 初始化三个步骤来进行初始化. 加载是把class文件读入内存创建一个class对象, 连接分为三步,第一步是验证是否是正确的结构, 第二步是准备, 为类的静态成员分配内存, ...

  4. CentOS7 宝塔搭配git 实时更新项目源码

    上一篇文章 介绍了如何在CentOS7上 搭建GIT环境 详见链接:https://www.cnblogs.com/mverting/p/10206532.html 本章主要介绍git如何和wdcp搭 ...

  5. 帝国cms全文搜索 增加自定义字段搜索

    帝国cms全站搜索功能只能调出固定的几个字段,如果想搜索其他字段的值,这时我们应该怎么办呢?开拓族网站有这个需求,所以研究了一下帝国的全站搜索,后来发现在/e/sch/index.php中可以直接对数 ...

  6. ZYNQ的Linux Linaro系统镜像制作SD卡启动

    ZYNQ的Linux Linaro系统镜像制作SD卡启动 0. 概述 ZYNQ生成uboot的时候和正常的ARM设备不太一样,ZYNQ属于二次辅助启动uboot然后由uboot启动内核,大概意思就是 ...

  7. 20190118-自定义实现replace方法

    1.自定义实现replace方法 Python replace() 方法把字符串中的 old(旧字符串) 替换成 neange(新字符串),如果指定第三个参数max,则替换不超过 max 次.考虑ol ...

  8. tcp/ip五层协议

    TCP/IP协议不是TCP和IP这两个协议的合称,而是指因特网整个TCP/IP协议族.互联网协议(Internet Protocol Suite)是一个网络通信模型,以及一整个网络传输协议家族,为互联 ...

  9. JZ2440开发板:修改ARM芯片时钟(学习笔记)

    想要修改ARM芯片的时钟,需要去查询芯片手册和原理图,获取相关的信息(见下方图片) 首先来看时钟的结构图 根据结构图可以看出,时钟源有两种选择:1. XTIpll和XTOpll所连接的晶振 2. EX ...

  10. 20145209 2016-2017-2 《Java程序设计》第9周学习总结

    20145209 2016-2017-2 <Java程序设计>第9周学习总结 教材学习内容总结 JDBC简介 撰写应用程序是利用通信协议对数据库进行指令交换,以进行数据的增删查找 JDBC ...