Android WindowManager及其動畫問題

來源:互聯網
上載者:User

標籤:android   style   blog   color   os   使用   io   for   ar   

本:1.0 日期:2014.8.16 2014.8.23 2014.8.26著作權:© 2014 kince 轉載註明出處  一、概述    開發中發現在WindowManager上像在Activity中使用動畫效果無效,比如下面的代碼:
        ImageView iv = new ImageView(this);        iv.setImageResource(R.drawable.ic_launcher);        TranslateAnimation animation = new TranslateAnimation(                Animation.ABSOLUTE, 20, Animation.ABSOLUTE, 300,                Animation.ABSOLUTE, 100, Animation.ABSOLUTE, 400);        animation.setDuration(1000);        animation.setFillAfter(false);        iv.setAnimation(animation);        WindowManager mWindowManager = (WindowManager) this                .getSystemService(Context.WINDOW_SERVICE);        WindowManager.LayoutParams mLayoutParams = new WindowManager.LayoutParams();        mLayoutParams.x = 20;        mLayoutParams.y = 100;        mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;        mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;        mLayoutParams.gravity = Gravity.TOP;        mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;        mWindowManager.addView(iv, mLayoutParams);        animation.start();
二、分析  為什麼會不執行動畫呢,原因在於:the view which is going to be animated must not be directly added to the top window, because top window of android is not a real ViewGroup. so the view must be added to a ViewGroup like FrameLayout first and then this ViewGroup be added to the top window.意思是說動畫執行的條件是不能直接添加到最頂層的Window,而是需要一個容器。比如,在xml中定義的控制項就可以使用動畫。  後來發現一種解決方案是WindowManager.LayoutParams有一個動畫屬性:windowAnimations,可以這樣使用
   lp = new WindowManager.LayoutParams(LayoutParams.WRAP_CONTENT,                    LayoutParams.WRAP_CONTENT,                    WindowManager.LayoutParams.TYPE_PHONE,                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE                              | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE                              | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,                     PixelFormat.RGBA_8888);          lp.gravity = Gravity.LEFT |Gravity.TOP;          lp.windowAnimations = R.style.anim_view;//動畫          wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);          wm.addView(view, lp);
  但是,這是對整個View的一個動畫,而不是View中某個控制項的動畫。而且,使用的時候需要在View狀態改變的時候才會出現動畫效果。比如消失/出現的時候才會有動畫效果。因此這個方案也是行不通的。  既然WindowManager不是一個ViewGroup,那麼就構造一個容器來裝載WindowManager,可以如下:
/****/package com.kince.apus.widget;import com.kince.apus.R;import android.animation.Animator;import android.animation.Animator.AnimatorListener;import android.animation.AnimatorSet;import android.animation.ObjectAnimator;import android.content.Context;import android.graphics.PixelFormat;import android.os.Handler;import android.util.AttributeSet;import android.view.LayoutInflater;import android.view.View;import android.view.WindowManager;import android.widget.FrameLayout;import android.widget.ImageView;import android.widget.TextView;/*** @author kince* @category Windowmanager在Layout中的應用***/public class GuideLayout extends FrameLayout {     private WindowManager wManager;     private WindowManager.LayoutParams wmParams;     private View addView;     private TextView mTextView;     private ImageView mImageView;     private boolean isAddView;     private AnimatorSet mShowAnimatorSet, mHideAnimatorSet;     private Handler mHandler = new Handler() {          public void handleMessage(android.os.Message msg) {               super.handleMessage(msg);               switch (msg.what) {               case 1:                    showAnimator();                    break;               default:                    break;               }          };     };     /**     * @param context     */     public GuideLayout(Context context) {          this(context, null);          // TODO Auto-generated constructor stub     }     /**     * @param context     * @param attrs     */     public GuideLayout(Context context, AttributeSet attrs) {          this(context, attrs, 0);          // TODO Auto-generated constructor stub     }     /**     * @param context     * @param attrs     * @param defStyle     */     public GuideLayout(Context context, AttributeSet attrs, int defStyle) {          super(context, attrs, defStyle);          addView = LayoutInflater.from(context).inflate(R.layout.guide_layout,                    this);          mTextView = (TextView) addView.findViewById(R.id.tv);          mImageView = (ImageView) addView.findViewById(R.id.iv);          mTextView.setVisibility(View.GONE);          mImageView.setVisibility(View.GONE);          setAnimator();          getWindowManager(context);     }     /**     * @category 執行個體化WindowManager 初次類比位置時候使用     * @param context     */     private void getWindowManager(final Context context) {          wManager = (WindowManager) context.getApplicationContext()                    .getSystemService(Context.WINDOW_SERVICE);          wmParams = new WindowManager.LayoutParams();          wmParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;          wmParams.format = PixelFormat.TRANSPARENT;          wmParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL                    | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE                    | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;          wmParams.gravity = 17;          wmParams.width = WindowManager.LayoutParams.MATCH_PARENT;          wmParams.height = WindowManager.LayoutParams.MATCH_PARENT;     }     private void setAnimator() {          mShowAnimatorSet = new AnimatorSet();          Animator[] showAnimator = new Animator[2];          showAnimator[0] = ObjectAnimator.ofFloat(mTextView, "alpha",                    new float[] { 0.0F, 1.0F });          showAnimator[1] = ObjectAnimator.ofFloat(mImageView, "alpha",                    new float[] { 0.0F, 1.0F });          mShowAnimatorSet.playTogether(showAnimator);          mShowAnimatorSet.setDuration(1500l);          mHideAnimatorSet = new AnimatorSet();          Animator[] hideAnimator = new Animator[2];          hideAnimator[0] = ObjectAnimator.ofFloat(mTextView, "alpha",                    new float[] { 1.0F, 0.0F });          hideAnimator[1] = ObjectAnimator.ofFloat(mImageView, "alpha",                    new float[] { 1.0F, 0.0F });          mHideAnimatorSet.playTogether(hideAnimator);          mHideAnimatorSet.setDuration(1500l);     }     public void showAnimator() {          mTextView.setVisibility(View.VISIBLE);          mImageView.setVisibility(View.VISIBLE);          mShowAnimatorSet.start();          isAddView=true;     }     public void hideAnimator() {          mHideAnimatorSet.start();          mHideAnimatorSet.addListener(new AnimatorListener() {               @Override               public void onAnimationStart(Animator animation) {                    // TODO Auto-generated method stub               }               @Override               public void onAnimationRepeat(Animator animation) {                    // TODO Auto-generated method stub               }               @Override               public void onAnimationEnd(Animator animation) {                    // TODO Auto-generated method stub                    mTextView.setVisibility(View.INVISIBLE);                    mImageView.setVisibility(View.INVISIBLE);               }               @Override               public void onAnimationCancel(Animator animation) {                    // TODO Auto-generated method stub               }          });     }     public void sendMessage() {          if (isAddView) {               wManager.removeView(this);               mHandler.removeMessages(1);               isAddView=false;          }          mHandler.sendEmptyMessage(1);          wManager.addView(this, wmParams);     }}
  這樣一來,就可以實現在WindowManager上的動畫效果了。其實,造成這種現象的原因在於對Android API以及其體系的理解不夠深刻。忽略了動畫執行所需要的基本條件,影射的問題就是考慮問題不夠全面。所以,不論開發哪種功能,使用哪個API,前期的規劃、調研很重要。知己知彼,僅此而已。



Android WindowManager及其動畫問題

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.