zoukankan      html  css  js  c++  java
  • 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,前期的规划、调研很重要。知己知彼,仅此而已。

  • 相关阅读:
    springboot controller传参,对象映射
    将已有的lng lat 字段转换成point类型字段
    导入csv 到mysql数据库
    spring 数据库字段映射
    spring restTemplate使用方法
    mongo 大数据量更新注意事项
    mongo大数据量更新服务端超时解决: Cursor not found, cursor id: 82792803897
    JS 判断是否为null
    JS 日期格式化
    杨氏矩阵:查找x是否在矩阵中,第K大数
  • 原文地址:https://www.cnblogs.com/Fang3s/p/4189603.html
Copyright © 2011-2022 走看看