欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2024-03-31 19:20:34
手机下载了一些app,发现现在仿win8的主界面越来越多,在大家见惯了类gridview或者类tab后,给人一种耳目一新的感觉。今天在eoe上偶然发现已经有人实现了这个功能...

手机下载了一些app,发现现在仿win8的主界面越来越多,在大家见惯了类gridview或者类tab后,给人一种耳目一新的感觉。今天在eoe上偶然发现已经有人实现了这个功能的源码(地址:),马上下载跑了一下,效果很炫,但是有些bug,比如点击速度特别快时图像会被放大,以及点击时会触发两次点击事件。

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

效果:

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

首先普及一个小知识点

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

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。