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

手机下载了一些APP,发现现在仿win8的主界面越来越多,在大家见惯了类GridView或者类Tab后,给人一种耳目一新的感觉。今天在eoe上偶然发现已经有人实现了这个功能的源码(地址:http://www.eoeandroid.com/forum.php?mod=viewthread&tid=327557),马上下载跑了一下,效果很炫,但是有些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

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

时间: 2024-07-29 16:05:44

Android仿Win8的metro的UI界面(上)的相关文章

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

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

Android仿Win8界面开发_Android

本文将要模仿Win8界面的一个设计,一个一个的方块.方法很简单.这里自己把图片改改就可以成为自己想要的界面了. 1.首先来看看自定义的MyImageView: package com.example.win8test; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Camera; import android.graphics.Canvas; impo

Android仿Win8界面开发

本文将要模仿Win8界面的一个设计,一个一个的方块.方法很简单.这里自己把图片改改就可以成为自己想要的界面了. 1.首先来看看自定义的MyImageView: package com.example.win8test; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Camera; import android.graphics.Canvas; impo

在Android中实现Service动态更新UI界面(Service与主程序Activity之间的数据交互或控制)

案例:通过service向远程服务器发送请求,根据服务器返回的结果动态更新主程序UI界面,主程序可实时关闭或重启服务. 方案一:使用广播+Service 注册BroadcastReceiver 1.在主程序activity中注册一个BroadcastReceiver,用于接收Service发布的广播. @Override protected void onStart() {//重写onStart方法 dataReceiver = new DataReceiver(); IntentFilter

如何去掉Android 6.0 UI界面上的搜索框

网上参考了许多博文,更改了不少都没有结果,搜索框就是去不了,后来在以下的这个java文件中找到这个按钮监听事件 packages/apps/Launcher3/src/com/android/launcher3/Launcher.java 找到这个方法: public View getOrCreateQsbBar() { ..... ....  //将这段代码改成这样,屏蔽掉上方的搜索栏    if (widgetId != -1 && false) {            //if (

Android学习笔记(9):使用XML文件和Java代码控制UI界面

Android推荐使用XML文件设置UI界面,然后用Java代码控制逻辑部分,这体现了MVC思想.   MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑.   我们可以在app\src\main\res\layout目录下定义一个XML文件(R.java

使用AsyncTask异步更新UI界面及原理分析

概述: AsyncTask是在Android SDK 1.5之后推出的一个方便编写后台线程与UI线程交互的辅助类.AsyncTask的内部实现是一个线程池,所有提交的异步任务都会在这个线程池中的工作线程内执行,当工作线程需要跟UI线程交互时,工作线程会通过向在UI线程创建的Handler传递消息的方式,调用相关的回调函数,从而实现UI界面的更新.AsyncTask抽象出后台线程运行的五个状态,分别是:1.准备运行,2.正在后台运行,3.进度更新,4.完成后台任务,5.取消任务,对于这五个阶段,A

android编程怎么在锁屏界面上显示文字

问题描述 android编程怎么在锁屏界面上显示文字 android编程中怎么在锁屏界面上显示文字,请大家帮我一下.

Android 仿Windows Metro 界面UI

布局采用LinearLayout来实现(比较喜欢这个布局,在UI之前要有全局考虑的思想,操作起来比较简单),每一个菜单都是一个Linear块,内部是一个ImageView和一个TextView:一共做了两个界面点击互相切换,下面是效果截图:            由于每个Linear块的属性配置都差不多很相似,所以提取出来做成了统一的style,在XML文件中引用则更方便一些   下面是UI设计的布局文件代码片段: <?xml version="1.0" encoding=&qu