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

来自:http://www.2cto.com/kf/201404/292480.html

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

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

效果:

\

首先普及一个小知识点:

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

 

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

输出结果:

 

 

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

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

 

 

好了下面开始代码:

1、布局文件

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!--?xml version= 1.0 encoding=utf- 8 ?-->
<linearlayout xmlns:android= "http://schemas.android.com/apk/res/android" android:orientation= "vertical" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:gravity= "center" android:background= "@drawable/bkg_img_default" >
 
     <linearlayout android:orientation= "vertical" android:layout_width= "wrap_content" android:layout_height= "wrap_content" >
 
         <linearlayout android:orientation= "horizontal" android:layout_width= "wrap_content" android:layout_height= "wrap_content" >
 
             <linearlayout android:orientation= "vertical" android:layout_width= "wrap_content" android:layout_height= "wrap_content" >
 
                 <com.ljp.ani01.myimageview android:id= "@+id/c_joke" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:src= "@drawable/left_top" android:scaletype= "matrix" android:layout_margin= "2dp" >
 
                 <com.ljp.ani01.myimageview android:id= "@+id/c_idea" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:src= "@drawable/left_bottom" android:scaletype= "matrix" android:layout_margin= "2dp" >
             </com.ljp.ani01.myimageview></com.ljp.ani01.myimageview></linearlayout>
 
             <com.ljp.ani01.myimageview android:id= "@+id/c_constellation" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:src= "@drawable/right" android:scaletype= "matrix" android:layout_margin= "2dp" >
         </com.ljp.ani01.myimageview></linearlayout>
 
         <com.ljp.ani01.myimageview android:id= "@+id/c_recommend" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:src= "@drawable/bottom" android:scaletype= "matrix" android:layout_margin= "2dp" >
     </com.ljp.ani01.myimageview></linearlayout>
 
</linearlayout>

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

 

2、MyImageView.java

 

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

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值