Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android特效開發(可伸縮View帶互相擠壓效果)進階篇

Android特效開發(可伸縮View帶互相擠壓效果)進階篇

編輯:關於Android編程

在上一篇文章末尾我提出了三點不足 ,遂本篇主要是為了解決上篇的不足之處。 對於上一篇的不足之處 有三點 :      1. 特效動畫死板,變化速度死板;      2. 特效動畫不能設置動畫時間,如遇到高分辨率的機型,動畫時間會變長。      3. view只能水平伸縮,不能豎直伸縮。   對於第一點不足之處變化速度死板,我立馬想到了Android中Interpolator類,對於做過Android中動畫的同學 來說,這個類應該並不陌生,該類可以改變動畫的變化速率,它的直接子類中有       BounceInterpolator  彈球效果        AccelerateInterpolator 加速      LinearInterpolator 勻速 更多子類可請查閱Android開發文檔 它有個getInterpolation (float input) 方法,你可以傳入動畫消逝時間值(input范圍 [0,1] ),0代表開始,1代表 結束,獲取變化速率。等會兒代碼中有用到這個類。 有關插值器可參考: android動畫(一)Interpolator 對於第一二三點不足,我寫了輔助類StretchAnimation可以解決。歡迎批評指正。 StretchAnimation只負責view水平拉伸或者垂直拉伸。你可以設置動畫的時間,你可以設置它的插值器,改變動 畫的效果。下面該類的實現過程。 [java]   public class StretchAnimation {          private final static String TAG = "SizeChange";       private Interpolator mInterpolator; // 好多書上翻譯為插值器       private View mView;    // 你要伸縮的view       private int mCurrSize; //當前大小       private int mRawSize;       private int mMinSize; // 最小大小 固定值       private int mMaxSize; // 最大大小 固定值       private boolean isFinished = true;// 動畫結束標識       private TYPE mType = TYPE.vertical;       private final static int FRAMTIME = 20;// 一幀的時間 毫秒       public static enum TYPE {           horizontal, // 改變view水平方向的大小           vertical    // 改變view豎直方向的大小       }          private int mDuration;  // 動畫運行的時間       private long mStartTime;// 動畫開始時間       private float mDurationReciprocal;        private int mDSize; // 需要改變view大小的增量          public StretchAnimation(int maxSize, int minSize, TYPE type, int duration) {           if (minSize >= maxSize) {               throw new RuntimeException("View的最大改變值不能小於最小改變值");           }           mMinSize = minSize;           mMaxSize = maxSize;           mType = type;           mDuration = duration;       }          public void setInterpolator(Interpolator interpolator) {           mInterpolator = interpolator;       }          public TYPE getmType() {           return mType;       }          public boolean isFinished() {           return isFinished;       }          public void setDuration(int duration) {           mDuration = duration;       }          private void changeViewSize() {              if (mView != null && mView.getVisibility() != View.GONE) {               LayoutParams params = mView.getLayoutParams();               if (mType == TYPE.vertical) {                   params.height = mCurrSize;               } else if (mType == TYPE.horizontal) {                   params.width = mCurrSize;               }               Log.i(TAG, "CurrSize = " + mCurrSize + " Max=" + mMaxSize + " min="                       + mMinSize);               mView.setLayoutParams(params);           }       }          private Handler mHandler = new Handler() {              @Override           public void handleMessage(Message msg) {                  if (msg.what == 1) {                   if (!computeViewSize()) {                          mHandler.sendEmptyMessageDelayed(1, FRAMTIME);                   } else {                       if (animationlistener != null) {                           animationlistener.animationEnd(mView);                       }                   }               }               super.handleMessage(msg);           }          };          /**       * @return 返回true 表示動畫完成       */       private boolean computeViewSize() {              if (isFinished) {               return isFinished;           }           int timePassed = (int) (AnimationUtils.currentAnimationTimeMillis() - mStartTime);              if (timePassed <= mDuration) {               float x = timePassed * mDurationReciprocal;               if (mInterpolator != null) {                   x = mInterpolator.getInterpolation(x);               }               mCurrSize = mRawSize + Math.round(x * mDSize);           } else {                  isFinished = true;               mCurrSize = mRawSize + mDSize;              }           changeViewSize();           return isFinished;       }          public void startAnimation(View view) {              if (view != null) {               mView = view;           } else {               Log.e(TAG, "view 不能為空");               return;           }           LayoutParams params = mView.getLayoutParams();              if (isFinished) {               mDurationReciprocal = 1.0f / (float) mDuration;               if (mType == TYPE.vertical) {                   mRawSize = mCurrSize = mView.getHeight();               } else if (mType == TYPE.horizontal) {                   mRawSize = mCurrSize = mView.getWidth();               }               Log.i(TAG, "mRawSize=" + mRawSize);               if (mCurrSize > mMaxSize || mCurrSize < mMinSize) {                   throw new RuntimeException(                           "View 的大小不達標 currentViewSize > mMaxSize || currentViewSize < mMinSize");               }               isFinished = false;               mStartTime = AnimationUtils.currentAnimationTimeMillis(); // 動畫開始時間               if (mCurrSize < mMaxSize) {                   mDSize = mMaxSize - mCurrSize;               } else {                   mDSize = mMinSize - mMaxSize;               }               Log.i(TAG, "mDSize=" + mDSize);               mHandler.sendEmptyMessage(1);           }       }          private AnimationListener animationlistener;          interface AnimationListener {           public void animationEnd(View v);       }          public void setOnAnimationListener(AnimationListener listener) {           animationlistener = listener;       }     初始化該類後再調用startAnimation 就可以播放動畫。 原理補充:每次開始播放動畫時你要知道需要改變的值是多少,我上面是用mDSize表示,然後根據時間的消逝值除以你設置的動畫要播放的時間值得到結果X,你再通過Interpolation.getInterpolation(x)就可以得到變化速率,變化速率乘以mDSize,就可以得到此時時的View大小改變量了。改變量曉得了,你就可以算出view的此時的大小了。 下面是我在activity中使用StretchAnimation的過程 [java]   public class StretchActivity extends Activity implements                       View.OnClickListener,                      StretchAnimation.AnimationListener {          private final static String TAG = "StretchActivity";              // 屏幕寬度       private int screentWidth = 0;              private int screentHeight = 0;              // View可伸展最長的寬度       private int maxSize;              // View可伸展最小寬度       private int minSize;              // 當前點擊的View       private View currentView;              // 顯示最長的那個View       private View preView;              // 主布局ViewGroup       private LinearLayout mainContain;              private StretchAnimation stretchanimation;              private TextView tvLog;          @Override       protected void onCreate(Bundle savedInstanceState)        {              super.onCreate(savedInstanceState);                      setContentView(R.layout.activity_main);              mainContain = (LinearLayout) this.findViewById(R.id.main_contain);                      initCommonData();                      initViewData(2);                  }          /**       * @param index 初始化時哪一個是最大的 從零開始       */       private void initViewData(int index) {              tvLog = (TextView)this.findViewById(R.id.tv_log);           View child;           int sizeValue = 0;           LayoutParams params = null;           int childCount = mainContain.getChildCount();           if(index <0 || index >= childCount)           {               throw new RuntimeException("index 超出范圍");           }                      for (int i = 0; i < childCount; i++) {                              child = mainContain.getChildAt(i);               child.setOnClickListener(this);               params = child.getLayoutParams();                              if (i == index) {                   preView = child;                   sizeValue = maxSize;               } else {                   sizeValue = minSize;               }               if(stretchanimation.getmType() == com.manymore13.Stretch.StretchAnimation.TYPE.horizontal){                   params.width = sizeValue;               }else if(stretchanimation.getmType() == com.manymore13.Stretch.StretchAnimation.TYPE.vertical){                   params.height = sizeValue;               }                  child.setLayoutParams(params);           }                  }              private void initCommonData()       {           DisplayMetrics metric = new DisplayMetrics();           getWindowManager().getDefaultDisplay().getMetrics(metric);           screentWidth = metric.widthPixels; // 屏幕寬度(像素)           screentHeight= metric.heightPixels;           //           measureSize(screentHeight);           stretchanimation = new StretchAnimation(maxSize, minSize, StretchAnimation.TYPE.vertical, 500);           stretchanimation.setInterpolator(new BounceInterpolator());           stretchanimation.setDuration(800);           stretchanimation.setOnAnimationListener(this);       }             /**       * 測量View 的 max min 長度  這裡你可以根據你的要求設置max       * @param screenSize       * @param index 從零開始       */       private void measureSize(int layoutSize) {           int halfWidth = layoutSize / 2;           maxSize = halfWidth - 50;           minSize = (layoutSize - maxSize) / (mainContain.getChildCount() - 1);                      Log.i(TAG, "maxWidth="+maxSize+" minWidth = "+minSize);                  }          @Override       public void onClick(View v) {                      int id = v.getId();           View tempView = null;           switch (id) {                      case R.id.btnOne:               tempView = mainContain.getChildAt(0);               break;           case R.id.btnTwo:               tempView = mainContain.getChildAt(1);               break;           case R.id.btnThree:               tempView = mainContain.getChildAt(2);               break;           case R.id.btnFour:               tempView = mainContain.getChildAt(3);               break;           }           if(tempView == preView){               Log.d(TAG, "");               String addInfo = ((Button) currentView).getText().toString()+"動畫不能執行";               printAddViewDebugInfo(addInfo);               return;           }else{               currentView = tempView;           }           Log.i(TAG, ((Button) currentView).getText().toString() + " click");           clickEvent(currentView);           onOffClickable(false);           String addInfo = ((Button) currentView).getText().toString()+"start animation";           printAddViewDebugInfo(addInfo);           stretchanimation.startAnimation(currentView);             }              private void clickEvent(View view) {           View child;           int childCount = mainContain.getChildCount();           LinearLayout.LayoutParams params;           for (int i = 0; i < childCount; i++) {               child = mainContain.getChildAt(i);               if (preView == child) {                   params = (android.widget.LinearLayout.LayoutParams) child                           .getLayoutParams();                                      if(preView != view){                       params.weight = 1.0f;                   }                   child.setLayoutParams(params);                                  } else {                   params = (android.widget.LinearLayout.LayoutParams) child                           .getLayoutParams();                   params.weight = 0.0f;                   if(stretchanimation.getmType() == StretchAnimation.TYPE.horizontal){                       params.width = minSize;                   }else if(stretchanimation.getmType() == StretchAnimation.TYPE.vertical){                       params.height = minSize;                   }                                      child.setLayoutParams(params);               }           }           preView = view;                  }              // 調試信息       private void printDebugMsg() {           View child;           int childCount = mainContain.getChildCount();           StringBuilder sb = new StringBuilder();           sb.append("preView = "+((Button)preView).getText().toString()+" ");           sb.append("click = "+((Button)currentView).getText().toString()+" ");           for (int i = 0; i < childCount; i++) {               child = mainContain.getChildAt(i);               LinearLayout.LayoutParams params = (android.widget.LinearLayout.LayoutParams) child                       .getLayoutParams();               sb.append(params.weight+" ");           }           Log.d(TAG, sb.toString());       }              // LinearLayout下所有childView 可點擊開關       // 當動畫在播放時應該設置為不可點擊,結束時設置為可點擊       private void onOffClickable(boolean isClickable)       {           View child;           int childCount = mainContain.getChildCount();           for (int i = 0; i < childCount; i++) {               child = mainContain.getChildAt(i);               child.setClickable(isClickable);           }       }          @Override       public void animationEnd(View v) {                      Log.i(TAG, ("-----"+((Button)v).getText().toString())+" annation end");           String addStr = ((Button)v).getText().toString()+" annation end";           printAddViewDebugInfo(addStr);           onOffClickable(true);       }              private void printAddViewDebugInfo(String addinfo)       {           String temp = tvLog.getText().toString();           tvLog.setText(temp+"\n"+addinfo);       }   在上面代碼中可以看到stretchanimation 的初始化與調用 初始化stretchanimation  // 我這裡設置的View是垂直伸縮動畫,maxSIze是伸縮的最大值,minSize是伸縮的最小值,500是500毫秒的動畫時間 // 注意:你這裡設置StretchAnimation.TYPE.vertical垂直伸縮動畫,你XML中相應View布局也應該是垂直, [java]   stretchanimation = new StretchAnimation(maxSize, minSize, StretchAnimation.TYPE.vertical, 500);   // 設置它的插值器 彈球效果   stretchanimation.setInterpolator(new BounceInterpolator());   // 動畫播放的總時間   stretchanimation.setDuration(800);   // 動畫播放完後的回調   stretchanimation.setOnAnimationListener(this);   // 播放動畫 參數是你要播放的View   stretchanimation.startAnimation(currentView)    
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved