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

jopen 8年前發布 | 9K 次閱讀 Java開發

轉載請標明出處: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 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://blog.csdn.net//lmj623565791/article/details/23441455

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!