Android仿Win8的metro的UI界面(上)
手机下载了一些app,发现现在仿win8的主界面越来越多,在大家见惯了类gridview或者类tab后,给人一种耳目一新的感觉。今天在eoe上偶然发现已经有人实现了这个功能的源码(地址:),马上下载跑了一下,效果很炫,但是有些bug,比如点击速度特别快时图像会被放大,以及点击时会触发两次点击事件。
本例子基于eoe中这位大神的实现,做了一些简化,和bug的修复。
效果:
首先普及一个小知识点:
我们在项目中有时候需要一个缓慢的梯度数据,例如:控件的宽度以一定的比例增加,然后以相同的比例还原到原来的长度。
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); 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.0
1.0846523
1.1764706
1.2760615
1.384083
1.5012488
1.384083
1.2760615
1.1764706
1.0846523
1.0
很完美吧,基本是个对称的梯度数据,梯度的幅度由代码中的s觉得,越接近1幅度越小,反之则反之。
好了下面开始代码:
1、布局文件
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/bkg_img_default" android:gravity="center" android:orientation="vertical" > <linearlayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" > <linearlayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" > <linearlayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" > <com.ljp.ani01.myimageview android:id="@+id/c_joke" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="2dp" android:scaletype="matrix" android:src="@drawable/left_top" /> <com.ljp.ani01.myimageview android:id="@+id/c_idea" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="2dp" android:scaletype="matrix" android:src="@drawable/left_bottom" /> </linearlayout> <com.ljp.ani01.myimageview android:id="@+id/c_constellation" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="2dp" android:scaletype="matrix" android:src="@drawable/right" /> </linearlayout> <com.ljp.ani01.myimageview android:id="@+id/c_recommend" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="2dp" android:scaletype="matrix" android:src="@drawable/bottom" /> </linearlayout> </linearlayout>
布局文件,完成了上面效果图的静态效果,如果你不需要添加点击动画,或者只需要很简单的点击效果,那么就已经完成这样的菜单的编写,再添加个backgroud自定义下点击效果就好了。当然,我们这里有个比较柔和的点击动画,有自定义的imageview完成。
2、myimageview.java
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
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下,还是很有必要的。
源码下载:http://xiazai.jb51.net/201608/yuanma/androidrolateanim(jb51.net).rar
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
下一篇: Shiro集成Spring之注解示例详解