Android添加系統級頂層窗口 和 WindowManager添加view的動畫問題


 

當Dialog有編輯框時如果選擇會彈菜單窗口就不要用

Context applicationContext = mainActivity.getApplicationContext();
AlertDialog.Builder dlgBuilder = new AlertDialog.Builder(applicationContext);
AlertDialog dialog = dlgBuilder.create();
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

 

public class Dialog implements DialogInterface, Window.Callback, KeyEvent.Callback, OnCreateContextMenuListener

 

constructor

  /**
     * Create a Dialog window that uses the default dialog frame style.
     * 
     * @param context The Context the Dialog is to run it.  In particular, it
     *                uses the window manager and theme in this context to
     *                present its UI.
     */
    public Dialog(Context context) {
        this(context, 0, true);
    }

    /**
     * Create a Dialog window that uses a custom dialog style.
     * 
     * @param context The Context in which the Dialog should run. In particular, it
     *                uses the window manager and theme from this context to
     *                present its UI.
     * @param theme A style resource describing the theme to use for the 
     * window. See <a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes">Style 
     * and Theme Resources</a> for more information about defining and using 
     * styles.  This theme is applied on top of the current theme in 
     * <var>context</var>.  If 0, the default dialog theme will be used.
     */
    public Dialog(Context context, int theme) {
        this(context, theme, true);
    }

    Dialog(Context context, int theme, boolean createContextThemeWrapper) {
        if (createContextThemeWrapper) {
            if (theme == 0) {
                TypedValue outValue = new TypedValue();
                context.getTheme().resolveAttribute(com.android.internal.R.attr.dialogTheme,
                        outValue, true);
                theme = outValue.resourceId;
            }
            mContext = new ContextThemeWrapper(context, theme);
        } else {
            mContext = context;
        }

        mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
        Window w = PolicyManager.makeNewWindow(mContext);
        mWindow = w;
        w.setCallback(this);
        w.setWindowManager(mWindowManager, null, null);
        w.setGravity(Gravity.CENTER);
        mListenersHandler = new ListenersHandler(this);
    }

show


/** * Start the dialog and display it on screen. The window is placed in the * application layer and opaque. Note that you should not override this * method to do initialization when the dialog is shown, instead implement * that in {@link #onStart}. */ public void show() { if (mShowing) { if (mDecor != null) { if (mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) { mWindow.invalidatePanelMenu(Window.FEATURE_ACTION_BAR); } mDecor.setVisibility(View.VISIBLE); } return; } mCanceled = false; if (!mCreated) { dispatchOnCreate(null); } onStart(); mDecor = mWindow.getDecorView(); if (mActionBar == null && mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) { final ApplicationInfo info = mContext.getApplicationInfo(); mWindow.setDefaultIcon(info.icon); mWindow.setDefaultLogo(info.logo); mActionBar = new ActionBarImpl(this); } WindowManager.LayoutParams l = mWindow.getAttributes(); if ((l.softInputMode & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) == 0) { WindowManager.LayoutParams nl = new WindowManager.LayoutParams(); nl.copyFrom(l); nl.softInputMode |= WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION; l = nl; } try { mWindowManager.addView(mDecor, l); mShowing = true; sendShowMessage(); } finally { } }

 

 

AndroidRuntime FATAL EXCEPTION

12-28 13:21:19.631: E/AndroidRuntime(8611): FATAL EXCEPTION: main
12-28 13:21:19.631: E/AndroidRuntime(8611): android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
12-28 13:21:19.631: E/AndroidRuntime(8611): at android.view.ViewRootImpl.setView(ViewRootImpl.java:571)
12-28 13:21:19.631: E/AndroidRuntime(8611): at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:246)
12-28 13:21:19.631: E/AndroidRuntime(8611): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
12-28 13:21:19.631: E/AndroidRuntime(8611): at android.widget.PopupWindow.invokePopup(PopupWindow.java:993)
12-28 13:21:19.631: E/AndroidRuntime(8611): at android.widget.PopupWindow.showAtLocation(PopupWindow.java:847)
12-28 13:21:19.631: E/AndroidRuntime(8611): at com.android.internal.policy.impl.PhoneWindow$DecorView$1.run(PhoneWindow.java:2285)
12-28 13:21:19.631: E/AndroidRuntime(8611): at android.os.Handler.handleCallback(Handler.java:725)
12-28 13:21:19.631: E/AndroidRuntime(8611): at android.os.Handler.dispatchMessage(Handler.java:92)
12-28 13:21:19.631: E/AndroidRuntime(8611): at android.os.Looper.loop(Looper.java:137)
12-28 13:21:19.631: E/AndroidRuntime(8611): at android.app.ActivityThread.main(ActivityThread.java:5041)
12-28 13:21:19.631: E/AndroidRuntime(8611): at java.lang.reflect.Method.invokeNative(Native Method)
12-28 13:21:19.631: E/AndroidRuntime(8611): at java.lang.reflect.Method.invoke(Method.java:511)
12-28 13:21:19.631: E/AndroidRuntime(8611): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
12-28 13:21:19.631: E/AndroidRuntime(8611): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
12-28 13:21:19.631: E/AndroidRuntime(8611): at dalvik.system.NativeStart.main(Native Method)



 

 

    <!-- Variant of {@link #Theme_Translucent} that has no title bar and
         no status bar -->
    <style name="Theme.Translucent.NoTitleBar.Fullscreen">
        <item name="android:windowFullscreen">true</item>
    </style>
    
    <!-- Default theme for activities that don't actually display a UI; that
         is, they finish themselves before being resumed.  -->
    <style name="Theme.NoDisplay">
        <item name="android:windowBackground">@null</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowAnimationStyle">@null</item>
        <item name="android:windowDisablePreview">true</item>
        <item name="android:windowNoDisplay">true</item>
    </style>

    <!-- Default theme for dialog windows and activities (on API level 10 and lower),
         which is used by the
         {@link android.app.Dialog} class.  This changes the window to be
         floating (not fill the entire screen), and puts a frame around its
         contents.  You can set this theme on an activity if you would like to
         make an activity that looks like a Dialog. -->
    <style name="Theme.Dialog">
        <item name="android:windowFrame">@null</item>
        <item name="android:windowTitleStyle">@android:style/DialogWindowTitle</item>
        <item name="android:windowBackground">@android:drawable/panel_background</item>
        <item name="android:windowIsFloating">true</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
        <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
        <item name="android:windowCloseOnTouchOutside">@bool/config_closeDialogWhenTouchOutside</item>
        <item name="android:windowActionModeOverlay">true</item>

        <item name="android:colorBackgroundCacheHint">@null</item>
        
        <item name="textAppearance">@android:style/TextAppearance</item>
        <item name="textAppearanceInverse">@android:style/TextAppearance.Inverse</item>

        <item name="textColorPrimary">@android:color/primary_text_dark</item>
        <item name="textColorSecondary">@android:color/secondary_text_dark</item>
        <item name="textColorTertiary">@android:color/tertiary_text_dark</item>
        <item name="textColorPrimaryInverse">@android:color/primary_text_light</item>
        <item name="textColorSecondaryInverse">@android:color/secondary_text_light</item>
        <item name="textColorTertiaryInverse">@android:color/tertiary_text_light</item>
        <item name="textColorPrimaryDisableOnly">@android:color/primary_text_dark_disable_only</item>
        <item name="textColorPrimaryInverseDisableOnly">@android:color/primary_text_light_disable_only</item>
        <item name="textColorPrimaryNoDisable">@android:color/primary_text_dark_nodisable</item>
        <item name="textColorSecondaryNoDisable">@android:color/secondary_text_dark_nodisable</item>
        <item name="textColorPrimaryInverseNoDisable">@android:color/primary_text_light_nodisable</item>
        <item name="textColorSecondaryInverseNoDisable">@android:color/secondary_text_light_nodisable</item>
        <item name="textColorHint">@android:color/hint_foreground_dark</item>
        <item name="textColorHintInverse">@android:color/hint_foreground_light</item>
        <item name="textColorSearchUrl">@android:color/search_url_text</item>

        <item name="textAppearanceLarge">@android:style/TextAppearance.Large</item>
        <item name="textAppearanceMedium">@android:style/TextAppearance.Medium</item>
        <item name="textAppearanceSmall">@android:style/TextAppearance.Small</item>
        <item name="textAppearanceLargeInverse">@android:style/TextAppearance.Large.Inverse</item>
        <item name="textAppearanceMediumInverse">@android:style/TextAppearance.Medium.Inverse</item>
        <item name="textAppearanceSmallInverse">@android:style/TextAppearance.Small.Inverse</item>

        <item name="listPreferredItemPaddingLeft">10dip</item>
        <item name="listPreferredItemPaddingRight">10dip</item>
        <item name="listPreferredItemPaddingStart">10dip</item>
        <item name="listPreferredItemPaddingEnd">10dip</item>

        <item name="preferencePanelStyle">@style/PreferencePanel.Dialog</item>
    </style>

    <!-- Variant of {@link Theme_Dialog} that does not include a frame (or background).
         The view hierarchy of the dialog is responsible for drawing all of
         its pixels. -->
    <style name="Theme.Dialog.NoFrame">
        <item name="windowBackground">@android:color/transparent</item>
        <item name="android:windowFrame">@null</item>
        <item name="windowContentOverlay">@null</item>
        <item name="android:windowAnimationStyle">@null</item>
        <item name="android:backgroundDimEnabled">false</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowCloseOnTouchOutside">false</item>
    </style>

    <!-- Default theme for alert dialog windows (on API level 10 and lower), which is used by the
         {@link android.app.AlertDialog} class.  This is basically a dialog
         but sets the background to empty so it can do two-tone backgrounds. -->
    <style name="Theme.Dialog.Alert">
        <item name="windowBackground">@android:color/transparent</item>
        <item name="windowTitleStyle">@android:style/DialogWindowTitle</item>
        <item name="windowContentOverlay">@null</item>
        <item name="itemTextAppearance">@android:style/TextAppearance.Large.Inverse</item>
        <item name="textAppearanceListItem">@android:style/TextAppearance.Large.Inverse</item>
        <item name="textAppearanceListItemSmall">@android:style/TextAppearance.Large.Inverse</item>
    </style>

 

        <activity
            android:name=".AlertActivity"
            android:excludeFromRecents="true"
            android:finishOnTaskLaunch="true"
            android:launchMode="singleInstance"
            android:theme="@*android:style/Theme.Dialog.Alert" >
        </activity>

 

 

package com.android.autologin;

import android.app.Activity;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.os.Bundle;

/**
 *     This is the dialog Activity used as an AlertDialog for the user to interact.
 * Requires android:launchMode="singleInstance" in your AndroidManifest to work
 * properly.
 * <p/>
 *     當Dialog有編輯框時如果選擇會彈菜單窗口就不要用 AlertDialog(Application)
 * 再添加WindowManager.LayoutParams. TYPE_SYSTEM_ALERT,
 * <pre>
 *         Context applicationContext = mainActivity.getApplicationContext();
 *        AlertDialog.Builder dlgBuilder = new AlertDialog.Builder(applicationContext);
 *        EditText et = new EditText(mainActivity);
 *        dlgBuilder.setTitle(mainActivity.getTitle());
 *        dlgBuilder.setPositiveButton(android.R.string.ok, null);
 *        dlgBuilder.setNegativeButton(android.R.string.cancel, null);
 *        dlgBuilder.setIcon(android.R.drawable.ic_dialog_alert);
 *        dlgBuilder.setView(et);
 *        AlertDialog dialog = dlgBuilder.create();
 *        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
 *        dialog.show();
 * </pre>
 * 防止報錯
 * attrs.token = null,
 * BadTokenException("Unable to add window -- token " + attrs.token + " is not for an application")
 * 
 * @usage
 * 
 * <i>.java</i>
 *        
 * <code><pre>
 *         Intent dialogIntent = new Intent(mContext, AlertActivity.class);
 *         dialogIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 *         mContext.startActivity(dialogIntent);
 * </pre></code> 
 * 
 * <i>AndroidManifest.xml</i>
 * 
 * <pre>
 *         < activity
 *             android:name=".AlertActivity"
 *             android:excludeFromRecents="true"
 *             android:finishOnTaskLaunch="true"
 *             android:launchMode="singleInstance"
 *             android:theme="@android:style/Theme.Dialog" >
 *         < /activity>
 * </pre>
 * 
 * @author Sansan
 **/
public class AlertActivity extends Activity implements DialogInterface.OnClickListener, OnDismissListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // setContentView(R.layout.alertactivity);
        
        
        // Get root view from current activity
        // @see http://stackoverflow.com/questions/4486034/get-root-view-from-current-activity
        
        // //rootview
        //// check layouts in hierarchyviewer.
        
        // findViewById(android.R.id.content) is giving me the root view
        // findViewById(android.R.id.content).getRootView()
        //getWindow().getDecorView().findViewById(android.R.id.content)
        
        // //-------------------------------------------------------------------------------------------
        // //This is what I use to get the root view as found in the XML file assigned with setContentView
        // //This answer gave the view without the status bar - which is what I wanted. I was looking for 
        // //the pixel width + height of the visible part of the activity. This one works, thanks!
        //
        //This excludes ActionBar!
        //final ViewGroup viewGroup = (ViewGroup) ((ViewGroup) this.findViewById(android.R.id.content)).getChildAt(0);
        // //-------------------------------------------------------------------------------------------
        
        
        // //-------------------------------------------------------------------------------------------
        // //I tested this in android 4.0.3, only:
        //
        // getWindow().getDecorView().getRootView();
        //
        // //give the same view what we get from
        //
        // anyview.getRootView();  == com.android.internal.policy.impl.PhoneWindow$DecorView@#########
        //
        // //and
        //
        // getWindow().getDecorView().findViewById(android.R.id.content)
        
        // //giving child of its == android.widget.FrameLayout@#######
        // //Please confirm.
        // //-------------------------------------------------------------------------------------------
        
        //setVisible(true);
        //requestWindowFeature(Window.FEATURE_NO_TITLE);//去掉標題欄
        
        // //Error, if select any text to pop up a system menu view, such as
        // paste in
        // // the Dialog.
        // //@see android/view/ViewRootImpl.java
        // //case WindowManagerGlobal.ADD_NOT_APP_TOKEN: throw new
        // //WindowManager.BadTokenException("Unable to add window -- token " +
        // //attrs.token + " is not for an application");
        // Context applicationContext = this.getApplicationContext();
        // AlertDialog.Builder dlgBuilder = new
        // AlertDialog.Builder(applicationContext);

        //AlertDialog.Builder dlgBuilder = new AlertDialog.Builder(this);
        //EditText et = new EditText(this);

        //dlgBuilder.setTitle(this.getTitle());
        //dlgBuilder.setPositiveButton(android.R.string.ok, AlertActivity.this);
        //dlgBuilder.setNegativeButton(android.R.string.cancel, AlertActivity.this);
        //dlgBuilder.setIcon(android.R.drawable.ic_dialog_alert);
        //dlgBuilder.setView(et);
        //AlertDialog dialog = dlgBuilder.create();
        //dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        //dialog.setCanceledOnTouchOutside(false);
        //dialog.setOnDismissListener(this);
        //dialog.show();
        
        
        // //DialogFragment
        // FragmentTransaction ft = getFragmentManager().beginTransaction();
        // DialogFragment newFragment = MyDialogFragment.newInstance();
        // ft.add(android.R.id.content, newFragment);
        // ft.commit();
    }

    //// @TargetApi(Build.VERSION_CODES.HONEYCOMB) 
//    public static class MyDialogFragment extends DialogFragment {
//        static MyDialogFragment newInstance() {
//            return new MyDialogFragment();
//        }
//
//        @Override
//        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//            //View v = inflater.inflate(R.layout.alertdialog, container, false);
//            getActivity().getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
//            return new EditText(getActivity());
//        }
//    }
    
    /**
     * meanwhile, finish the AlertActivity.
     */
    @Override
    public void onDismiss(DialogInterface dialog) {
        //finish();
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {

    }
}

 

 

Context applicationContext = mainActivity.getApplicationContext();
        WindowManager applicationWindowManager = (WindowManager) applicationContext.getSystemService(Context.WINDOW_SERVICE);
        AlertDialog.Builder dlgBuilder = new AlertDialog.Builder(mainActivity);
        EditText et = new EditText(mainActivity);

        // Dialog界面
        dlgBuilder.setTitle(mainActivity.getTitle());
        dlgBuilder.setPositiveButton(android.R.string.ok, null);
        dlgBuilder.setNegativeButton(android.R.string.cancel, null);
        dlgBuilder.setIcon(android.R.drawable.ic_dialog_alert);
        dlgBuilder.setView(et);
        AlertDialog dialog = dlgBuilder.create();
        // dialog.getWindow().getAttributes().token = mainActivity.getWindow().getAttributes().token;
        //
        try { Field mWindowManagerField = Dialog.class.getDeclaredField("mWindowManager"); mWindowManagerField.setAccessible(true); mWindowManagerField.set(dialog, applicationWindowManager); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block
 Alog.w(TAG, e.toString()); } catch (IllegalAccessException e) { // TODO Auto-generated catch block
 Alog.w(TAG, e.toString()); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block
 Alog.w(TAG, e.toString()); }

        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        // dialog.getWindow().addFlags(android.R.attr.windowIsFloating);
        dialog.show();

 

 

public abstract class Window

    /**
     * Return whether this window is being displayed with a floating style
     * (based on the {@link android.R.attr#windowIsFloating} attribute in
     * the style/theme).
     *
     * @return Returns true if the window is configured to be displayed floating
     * on top of whatever is behind it.
     */
    public abstract boolean isFloating();

    /**
     * Set the width and height layout parameters of the window.  The default
     * for both of these is MATCH_PARENT; you can change them to WRAP_CONTENT
     * or an absolute value to make a window that is not full-screen.
     *
     * @param width The desired layout width of the window.
     * @param height The desired layout height of the window.
     *
     * @see ViewGroup.LayoutParams#height
     * @see ViewGroup.LayoutParams#width
     */
    public void setLayout(int width, int height) {
        final WindowManager.LayoutParams attrs = getAttributes();
        attrs.width = width;
        attrs.height = height;
        if (mCallback != null) {
            mCallback.onWindowAttributesChanged(attrs);
        }
    }

    /**
     * Set the gravity of the window, as per the Gravity constants.  This
     * controls how the window manager is positioned in the overall window; it
     * is only useful when using WRAP_CONTENT for the layout width or height.
     *
     * @param gravity The desired gravity constant.
     *
     * @see Gravity
     * @see #setLayout
     */
    public void setGravity(int gravity)
    {
        final WindowManager.LayoutParams attrs = getAttributes();
        attrs.gravity = gravity;
        if (mCallback != null) {
            mCallback.onWindowAttributesChanged(attrs);
        }
    }

    /**
     * Set the type of the window, as per the WindowManager.LayoutParams
     * types.
     *
     * @param type The new window type (see WindowManager.LayoutParams).
     */
    public void setType(int type) {
        final WindowManager.LayoutParams attrs = getAttributes();
        attrs.type = type;
        if (mCallback != null) {
            mCallback.onWindowAttributesChanged(attrs);
        }
    }

    /**
     * Set the format of window, as per the PixelFormat types.  This overrides
     * the default format that is selected by the Window based on its
     * window decorations.
     *
     * @param format The new window format (see PixelFormat).  Use
     *               PixelFormat.UNKNOWN to allow the Window to select
     *               the format.
     *
     * @see PixelFormat
     */
    public void setFormat(int format) {
        final WindowManager.LayoutParams attrs = getAttributes();
        if (format != PixelFormat.UNKNOWN) {
            attrs.format = format;
            mHaveWindowFormat = true;
        } else {
            attrs.format = mDefaultWindowFormat;
            mHaveWindowFormat = false;
        }
        if (mCallback != null) {
            mCallback.onWindowAttributesChanged(attrs);
        }
    }

    /**
     * Specify custom animations to use for the window, as per
     * {@link WindowManager.LayoutParams#windowAnimations
     * WindowManager.LayoutParams.windowAnimations}.  Providing anything besides
     * 0 here will override the animations the window would
     * normally retrieve from its theme.
     */
    public void setWindowAnimations(int resId) {
        final WindowManager.LayoutParams attrs = getAttributes();
        attrs.windowAnimations = resId;
        if (mCallback != null) {
            mCallback.onWindowAttributesChanged(attrs);
        }
    }

    /**
     * Specify an explicit soft input mode to use for the window, as per
     * {@link WindowManager.LayoutParams#softInputMode
     * WindowManager.LayoutParams.softInputMode}.  Providing anything besides
     * "unspecified" here will override the input mode the window would
     * normally retrieve from its theme.
     */
    public void setSoftInputMode(int mode) {
        final WindowManager.LayoutParams attrs = getAttributes();
        if (mode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            attrs.softInputMode = mode;
            mHasSoftInputMode = true;
        } else {
            mHasSoftInputMode = false;
        }
        if (mCallback != null) {
            mCallback.onWindowAttributesChanged(attrs);
        }
    }
    
    /**
     * Convenience function to set the flag bits as specified in flags, as
     * per {@link #setFlags}.
     * @param flags The flag bits to be set.
     * @see #setFlags
     * @see #clearFlags
     */
    public void addFlags(int flags) {
        setFlags(flags, flags);
    }

    /** @hide */
    public void addPrivateFlags(int flags) {
        setPrivateFlags(flags, flags);
    }
    
    /**
     * Convenience function to clear the flag bits as specified in flags, as
     * per {@link #setFlags}.
     * @param flags The flag bits to be cleared.
     * @see #setFlags
     * @see #addFlags
     */
    public void clearFlags(int flags) {
        setFlags(0, flags);
    }

    /**
     * Set the flags of the window, as per the
     * {@link WindowManager.LayoutParams WindowManager.LayoutParams}
     * flags.
     * 
     * <p>Note that some flags must be set before the window decoration is
     * created (by the first call to
     * {@link #setContentView(View, android.view.ViewGroup.LayoutParams)} or
     * {@link #getDecorView()}:
     * {@link WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN} and
     * {@link WindowManager.LayoutParams#FLAG_LAYOUT_INSET_DECOR}.  These
     * will be set for you based on the {@link android.R.attr#windowIsFloating}
     * attribute.
     *
     * @param flags The new window flags (see WindowManager.LayoutParams).
     * @param mask Which of the window flag bits to modify.
     * @see #addFlags
     * @see #clearFlags
     */
    public void setFlags(int flags, int mask) {
        final WindowManager.LayoutParams attrs = getAttributes();
        attrs.flags = (attrs.flags&~mask) | (flags&mask);
        if ((mask&WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0) {
            attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY;
        }
        mForcedWindowFlags |= mask;
        if (mCallback != null) {
            mCallback.onWindowAttributesChanged(attrs);
        }
    }

    private void setPrivateFlags(int flags, int mask) {
        final WindowManager.LayoutParams attrs = getAttributes();
        attrs.privateFlags = (attrs.privateFlags & ~mask) | (flags & mask);
        if (mCallback != null) {
            mCallback.onWindowAttributesChanged(attrs);
        }
    }

    /**
     * Set the amount of dim behind the window when using
     * {@link WindowManager.LayoutParams#FLAG_DIM_BEHIND}.  This overrides
     * the default dim amount of that is selected by the Window based on
     * its theme.
     *
     * @param amount The new dim amount, from 0 for no dim to 1 for full dim.
     */
    public void setDimAmount(float amount) {
        final WindowManager.LayoutParams attrs = getAttributes();
        attrs.dimAmount = amount;
        mHaveDimAmount = true;
        if (mCallback != null) {
            mCallback.onWindowAttributesChanged(attrs);
        }
    }

    /**
     * Specify custom window attributes.  <strong>PLEASE NOTE:</strong> the
     * layout params you give here should generally be from values previously
     * retrieved with {@link #getAttributes()}; you probably do not want to
     * blindly create and apply your own, since this will blow away any values
     * set by the framework that you are not interested in.
     *
     * @param a The new window attributes, which will completely override any
     *          current values.
     */
    public void setAttributes(WindowManager.LayoutParams a) {
        mWindowAttributes.copyFrom(a);
        if (mCallback != null) {
            mCallback.onWindowAttributesChanged(mWindowAttributes);
        }
    }

    /**
     * Retrieve the current window attributes associated with this panel.
     *
     * @return WindowManager.LayoutParams Either the existing window
     *         attributes object, or a freshly created one if there is none.
     */
    public final WindowManager.LayoutParams getAttributes() {
        return mWindowAttributes;
    }

 

public static class

WindowManager.LayoutParams

extends  ViewGroup.LayoutParams
implements  Parcelable
java.lang.Object
   ? android.view.ViewGroup.LayoutParams
     ? android.view.WindowManager.LayoutParams
 WindowManager.LayoutParams 是 WindowManager 接口的嵌套類;它繼承於 ViewGroup.LayoutParams; 它用於向WindowManager描述Window的管理策略。
主要成員常量
Window flag系列
該系列主要用於對Window的flag進行設置。設置Window的flag,可以直接對Window的getAttributes()得到其 WindowManager.LayoutParams對象,然后直接對它flag變量操作。也可以Window的addFlags(int flags)方法,setFlags(int flags, int mask)方法,clearFlags(int flags)方法進行操作。
比如設置全屏:
 Window window = getWindow(); 
 WindowManager.LayoutParams winParams = win.getAttributes();
 winParams.flags=winParams.flags|WindowManager.LayoutParams.FLAG_FULLSCREEN;
 或
 window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
 或
 window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); 
 取消全屏
 Window window = getWindow(); 
 winParams.flags=winParams.flags&~WindowManager.LayoutParams.FLAG_FULLSCREEN;
 或
 window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
 或
window.setFlags(0, WindowManager.LayoutParams.FLAG_FULLSCREEN);
所有Window flag如下:

Window.addFlags(int flag)

final Window win = getWindow();
         win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);//覆蓋在屏幕鎖之上。
          PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
         if (!pm.isScreenOn()) {//屏幕時候保持高亮
             win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                     | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                     | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
                     | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
         }

 

 

一些Flag的介紹 
窗口之后的內容變暗。 
public static final int FLAG_DIM_BEHIND       = 0x00000002; 

窗口之后的內容變模糊。 
public static final int FLAG_BLUR_BEHIND       = 0x00000004; 

不許獲得焦點。 
不能獲得按鍵輸入焦點,所以不能向它發送按鍵或按鈕事件。那些時間將發送給它后面的可以獲得焦點的窗口。此選項還會設置FLAG_NOT_TOUCH_MODAL選項。設置此選項,意味着窗口不能與軟輸入法進行交互,所以它的Z序獨立於任何活動的輸入法(換句話說,它可以全屏顯示,如果需要的話,可覆蓋輸入法窗口)。要修改這一行為,可參考FLAG_ALT_FOCUSALBE_IM選項。 
public static final int FLAG_NOT_FOCUSABLE     = 0x00000008; 

不接受觸摸屏事件。 
public static final int FLAG_NOT_TOUCHABLE     = 0x00000010; 

當窗口可以獲得焦點(沒有設置FLAG_NOT_FOCUSALBE選項)時,仍然將窗口范圍之外的點設備事件(鼠標、觸摸屏)發送給后面的窗口處理。否則它將獨占所有的點設備事件,而不管它們是不是發生在窗口范圍之內。 
public static final int FLAG_NOT_TOUCH_MODAL   = 0x00000020; 

如果設置了這個標志,當設備休眠時,點擊觸摸屏,設備將收到這個第一觸摸事件。 
通常第一觸摸事件被系統所消耗,用戶不會看到他們點擊屏幕有什么反應。 
public static final int FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040; 

當此窗口為用戶可見時,保持設備常開,並保持亮度不變。 
public static final int FLAG_KEEP_SCREEN_ON    = 0x00000080; 

窗口占滿整個屏幕,忽略周圍的裝飾邊框(例如狀態欄)。此窗口需考慮到裝飾邊框的內容。 
public static final int FLAG_LAYOUT_IN_SCREEN   =0x00000100; 

允許窗口擴展到屏幕之外。 
public static final int FLAG_LAYOUT_NO_LIMITS   =0x00000200; 

窗口顯示時,隱藏所有的屏幕裝飾(例如狀態條)。使窗口占用整個顯示區域。 
public static final int FLAG_FULLSCREEN     = 0x00000400; 

此選項將覆蓋FLAG_FULLSCREEN選項,並強制屏幕裝飾(如狀態條)彈出。 
public static final int FLAG_FORCE_NOT_FULLSCREEN   =0x00000800; 

抖動。指的是對半透明的顯示方法。又稱“點透”。圖形處理較差的設備往往用“點透”替代Alpha混合。 
public static final int FLAG_DITHER           = 0x00001000; 

不允許屏幕截圖。 
public static final int FLAG_SECURE           = 0x00002000; 

一種特殊模式,布局參數用於指示顯示比例。 
public static final int FLAG_SCALED           = 0x00004000; 

當屏幕有可能貼着臉時,這一選項可防止面頰對屏幕造成誤操作。 
public static final int FLAG_IGNORE_CHEEK_PRESSES   = 0x00008000; 

當請求布局時,你的窗口可能出現在狀態欄的上面或下面,從而造成遮擋。當設置這一選項后,窗口管理器將確保窗口內容不會被裝飾條(狀態欄)蓋住。 
public static final int FLAG_LAYOUT_INSET_DECOR = 0x00010000; 

反轉FLAG_NOT_FOCUSABLE選項。 
如果同時設置了FLAG_NOT_FOCUSABLE選項和本選項,窗口將能夠與輸入法交互,允許輸入法窗口覆蓋; 
如果FLAG_NOT_FOCUSABLE沒有設置而設置了本選項,窗口不能與輸入法交互,可以覆蓋輸入法窗口。 
public static final int FLAG_ALT_FOCUSABLE_IM = 0x00020000; 

如果你設置了FLAG_NOT_TOUCH_MODAL,那么當觸屏事件發生在窗口之外事,可以通過設置此標志接收到一個MotionEvent.ACTION_OUTSIDE事件。注意,你不會收到完整的down/move/up事件,只有第一次down事件時可以收到ACTION_OUTSIDE。 
public static final int FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000; 

當屏幕鎖定時,窗口可以被看到。這使得應用程序窗口優先於鎖屏界面。可配合FLAG_KEEP_SCREEN_ON選項點亮屏幕並直接顯示在鎖屏界面之前。可使用FLAG_DISMISS_KEYGUARD選項直接解除非加鎖的鎖屏狀態。此選項只用於最頂層的全屏幕窗口。 
public static final int FLAG_SHOW_WHEN_LOCKED = 0x00080000; 

請求系統牆紙顯示在你的窗口后面。窗口必須是半透明的。 
public static final int FLAG_SHOW_WALLPAPER = 0x00100000; 

窗口一旦顯示出來,系統將點亮屏幕,正如用戶喚醒設備那樣。 
public static final int FLAG_TURN_SCREEN_ON = 0x00200000; 

解除鎖屏。只有鎖屏界面不是加密的才能解鎖。如果鎖屏界面是加密的,那么用戶解鎖之后才能看到此窗口,除非設置了FLAG_SHOW_WHEN_LOCKED選項。 
public static final int FLAG_DISMISS_KEYGUARD = 0x00400000; 

鎖屏界面淡出時,繼續運行它的動畫。 
public static final int FLAG_KEEP_SURFACE_WHILE_ANIMATING =0x10000000; 

以原始尺寸顯示窗口。用於在兼容模式下運行程序。 
public static final int FLAG_COMPATIBLE_WINDOW = 0x20000000; 

用於系統對話框。設置此選項的窗口將無條件獲得焦點。 
public static final int FLAG_SYSTEM_ERROR = 0x40000000; 

 

type 的取值:
      應用程序窗口。
      public static final int FIRST_APPLICATION_WINDOW = 1;   
 
      所有程序窗口的“基地”窗口,其他應用程序窗口都顯示在它上面。    
      public static final int TYPE_BASE_APPLICATION   =1;
        
      普通應用功能程序窗口。token必須設置為Activity的token,以指出該窗口屬誰。
      public static final int TYPE_APPLICATION       = 2;
 
       用於應用程序啟動時所顯示的窗口。應用本身不要使用這種類型。
      它用於讓系統顯示些信息,直到應用程序可以開啟自己的窗口。  
      public static final int TYPE_APPLICATION_STARTING = 3;
      
      應用程序窗口結束。
      public static final int LAST_APPLICATION_WINDOW = 99;
 
      子窗口。子窗口的Z序和坐標空間都依賴於他們的宿主窗口。
      public static final int FIRST_SUB_WINDOW       = 1000;
 
      面板窗口,顯示於宿主窗口上層。
      public static final int TYPE_APPLICATION_PANEL  = FIRST_SUB_WINDOW;
 
      媒體窗口,例如視頻。顯示於宿主窗口下層。
      public static final int TYPE_APPLICATION_MEDIA  = FIRST_SUB_WINDOW+1;
 
      應用程序窗口的子面板。顯示於所有面板窗口的上層。(GUI的一般規律,越“子”越靠上)
      public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW +2;
 
      對話框。類似於面板窗口,繪制類似於頂層窗口,而不是宿主的子窗口。
      public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW +3;
 
      媒體信息。顯示在媒體層和程序窗口之間,需要實現透明(半透明)效果。(例如顯示字幕)
      public static final int TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW +4;
 
      子窗口結束。( End of types of sub-windows )
      public static final int LAST_SUB_WINDOW        = 1999;
 
      系統窗口。非應用程序創建。
      public static final int FIRST_SYSTEM_WINDOW    = 2000;
 
      狀態欄。只能有一個狀態欄;它位於屏幕頂端,其他窗口都位於它下方。
      public static final int TYPE_STATUS_BAR        =  FIRST_SYSTEM_WINDOW;
 
      搜索欄。只能有一個搜索欄;它位於屏幕上方。
      public static final int TYPE_SEARCH_BAR        = FIRST_SYSTEM_WINDOW+1;
 
      電話窗口。它用於電話交互(特別是呼入)。它置於所有應用程序之上,狀態欄之下。
      public static final int TYPE_PHONE            = FIRST_SYSTEM_WINDOW+2;
 
      系統提示。它總是出現在應用程序窗口之上。
      public static final int TYPE_SYSTEM_ALERT      =  FIRST_SYSTEM_WINDOW +3;
 
      鎖屏窗口。
      public static final int TYPE_KEYGUARD          = FIRST_SYSTEM_WINDOW +4;
 
      信息窗口。用於顯示toast。
      public static final int TYPE_TOAST            = FIRST_SYSTEM_WINDOW +5;
 
      系統頂層窗口。顯示在其他一切內容之上。此窗口不能獲得輸入焦點,否則影響鎖屏。
      public static final int TYPE_SYSTEM_OVERLAY    =  FIRST_SYSTEM_WINDOW +6;
 
      電話優先,當鎖屏時顯示。此窗口不能獲得輸入焦點,否則影響鎖屏。
      public static final int TYPE_PRIORITY_PHONE    =  FIRST_SYSTEM_WINDOW +7;
 
      系統對話框。(例如音量調節框)。
      public static final int TYPE_SYSTEM_DIALOG     =  FIRST_SYSTEM_WINDOW +8;
 
      鎖屏時顯示的對話框。
      public static final int TYPE_KEYGUARD_DIALOG   =  FIRST_SYSTEM_WINDOW +9;
 
      系統內部錯誤提示,顯示於所有內容之上。
      public static final int TYPE_SYSTEM_ERROR      =  FIRST_SYSTEM_WINDOW +10;
 
      內部輸入法窗口,顯示於普通UI之上。應用程序可重新布局以免被此窗口覆蓋。
      public static final int TYPE_INPUT_METHOD      =  FIRST_SYSTEM_WINDOW +11;
 
      內部輸入法對話框,顯示於當前輸入法窗口之上。
      public static final int TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW +12;
 
      牆紙窗口。
      public static final int TYPE_WALLPAPER         = FIRST_SYSTEM_WINDOW +13;
 
      狀態欄的滑動面板。
      public static final int TYPE_STATUS_BAR_PANEL   = FIRST_SYSTEM_WINDOW +14;
 
      系統窗口結束。
      public static final int LAST_SYSTEM_WINDOW     = 2999;

 

 

關於Window的類型,主要有三種:
1 Application Windows:取值在 FIRST_APPLICATION_WINDOW 和 LAST_APPLICATION_WINDOW 之間。
是通常的、頂層的應用程序窗口。必須將token設置成activity的token。
2 Sub Windows:取值在 FIRST_SUB_WINDOW 和 LAST_SUB_WINDOW 之間。
與頂層窗口相關聯,token必須設置為它所附着的宿主窗口的token。
3 System Windows:取值在 FIRST_SYSTEM_WINDOW 和 LAST_SYSTEM_WINDOW 之間。
用於特定的系統功能。它不能用於應用程序,使用時需要特殊權限,在manifest.xml中添加如下聲明:

 
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

這三種類型的圖層順序是一次增高,即Application Windows在對底層,System Windows在最上層。看到這里我們再來看一下上面的代碼,其中這樣一句:

 
mWindowLayoutParams.type = android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;

 Dialog是屬於Sub Windows類型的,Toast是System Windows類型

 

Android WindowManager及其動畫問題

來源:wangjinyu501的專欄

一、概述 開發中發現在WindowManager上像在Activity中使用動畫效果無效,比如下面的代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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,可以這樣使用

?
1
2
3
4
5
6
7
8
9
10
11
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,可以如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/**
*
*/
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上的動畫效果了。其實,造成這種現象的原因在於對AndroidAPI以及其體系的理解不夠深刻。忽略了動畫執行所需要的基本條件,影射的問題就是考慮問題不夠全面。所以,不論開發哪種功能,使用哪個API,前期的規划、調研很重要。知己知彼,僅此而已。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM