天天看點

WindowManager.LayoutParamshttps://www.cnblogs.com/Fang3s/p/4189603.htmlAndroid添加系統級頂層視窗 和 WindowManager添加view的動畫問題WindowManager.LayoutParams

https://www.cnblogs.com/Fang3s/p/4189603.html

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" target="_blank" rel="external nofollow" >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)

WindowManager.LayoutParamshttps://www.cnblogs.com/Fang3s/p/4189603.htmlAndroid添加系統級頂層視窗 和 WindowManager添加view的動畫問題WindowManager.LayoutParams
<!-- 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();  == [email protected]#########
        //
        // //and
        //
        // getWindow().getDecorView().findViewById(android.R.id.content)
        
        // //giving child of its == [email protected]#######
        // //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;

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

;

}

};

};

public

GuideLayout(Context context) {

this

(context,

null

);

// TODO Auto-generated constructor stub

}

public

GuideLayout(Context context, AttributeSet attrs) {

this

(context, attrs,

);

// TODO Auto-generated constructor stub

}

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);

}

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[

] = ObjectAnimator.ofFloat(mTextView,

"alpha"

,

new

float

[] {

.0F,

1

.0F });

showAnimator[

1

] = ObjectAnimator.ofFloat(mImageView,

"alpha"

,

new

float

[] {

.0F,

1

.0F });

mShowAnimatorSet.playTogether(showAnimator);

mShowAnimatorSet.setDuration(1500l);

mHideAnimatorSet =

new

AnimatorSet();

Animator[] hideAnimator =

new

Animator[

2

];

hideAnimator[

] = ObjectAnimator.ofFloat(mTextView,

"alpha"

,

new

float

[] {

1

.0F,

.0F });

hideAnimator[

1

] = ObjectAnimator.ofFloat(mImageView,

"alpha"

,

new

float

[] {

1

.0F,

.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);

}

}

繼續閱讀