在路上

 找回密码
 立即注册
在路上 站点首页 学习 查看内容

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

2017-2-7 13:38| 发布者: zhangjf| 查看: 487| 评论: 0

摘要: 转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/23441455 昨晚没事手机下载了一些APP,发现现在仿win8的主界面越来越多,在大家见惯了类GridView或者类Tab后,给人一种耳目一新的感觉。今天 ...

转载请标明出处: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. }
  18. }
复制代码

输出结果:

  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下,还是很有必要的。


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


源码下载点击此处






来自: http://blog.csdn.net//lmj623565791/article/details/23441455

最新评论

小黑屋|在路上 ( 蜀ICP备15035742号-1 

;

GMT+8, 2025-7-8 19:55

Copyright 2015-2025 djqfx

返回顶部