編輯:關於Android編程
昨晚沒事手機下載了一些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
好了下面開始代碼:
1、布局文件
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(); } }); } }
如果你覺得這篇文章對你有用,可以頂一個~~
用過多米音樂的都市知道, 這個UI可以上下滑動,作用嘛---無聊中可以劃劃解解悶,這被錘子公司老羅稱謂為“情懷”,其實叫“情味”更
Android其中最重要的特性之一,就是一個應用可以基於“action”來切換到另一個應用。比如,你的應用想要查找地方,在地圖上顯示。但是不一定要
概述Android Design Support Library 是Google在2015年的IO大會上,帶來的全新適應Material Design設計規范的支持庫。在
這篇山寨一個新版QQ的列表滑動刪除,上篇有說到QQ的滑動刪除,推測原理就是ListView本身每個item存在一個Button,只不過普通的狀態下隱藏掉了,檢測到向左的滑