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

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

转载请标明出处: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的修复。

效果:

首先普及一个小知识点:

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

package com.zhy._01;public class Test2public 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.01.08465231.17647061.27606151.3840831.50124881.3840831.27606151.17647061.08465231.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 ImageViewprivate static final String TAG = "MyImageView"private static final int SCALE_REDUCE_INIT = 0private static final int SCALING = 1private 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 = truepublic 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下,还是很有必要的。


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


源码下载点击此处





           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

这里写图片描述

猜你喜欢

转载自blog.csdn.net/sdfwcc/article/details/84195598