Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android WindowManager及其動畫問題

Android WindowManager及其動畫問題

編輯:關於Android編程

本: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,前期的規劃、調研很重要。知己知彼,僅此而已。



  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved