Android窗口化app位移

来源:互联网 发布:淘宝网背带裤女装 编辑:程序博客网 时间:2024/05/16 16:58

强制移动window窗口可以通过在PhoneWindowManager中强制指定window的显示区域即可, 但我需要的是一个有过渡动画的位移.

查找相关代码发现窗口动画有一个位移的函数:

|--frameworks/base/server/java/com/android/server/wm/WindowManagerService.java

 // "Something has changed!  Let's make it correct now."    private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) {...if (w.mHasSurface && w.shouldAnimateMove()) {                        // Frame has moved, containing content frame                        // has also moved, and we're not currently animating...                        // let's do something.                        Animation a = AnimationUtils.loadAnimation(mContext,                                com.android.internal.R.anim.window_move_from_decor);                        winAnimator.setAnimation(a);                        winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left;                        winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top;                        try {                            w.mClient.moved(w.mFrame.left, w.mFrame.top);                        } catch (RemoteException e) {                        }                    }...}

|--frameworks/base/core/java/android/view/ViewRootImpl.java

static class W extends IWindow.Stub {        ...        @Override        public void moved(int newX, int newY) {            final ViewRootImpl viewAncestor = mViewAncestor.get();            if (viewAncestor != null) {                viewAncestor.dispatchMoved(newX, newY);            }        }...}    public void dispatchMoved(int newX, int newY) {        if (DEBUG_LAYOUT) Log.v(TAG, "Window moved " + this + ": newX=" + newX + " newY=" + newY);        if (mTranslator != null) {            PointF point = new PointF(newX, newY);            mTranslator.translatePointInScreenToAppWindow(point);            newX = (int) (point.x + 0.5);            newY = (int) (point.y + 0.5);        }        Message msg = mHandler.obtainMessage(MSG_WINDOW_MOVED, newX, newY);        mHandler.sendMessage(msg);    }    ...case MSG_WINDOW_MOVED:                if (mAdded) {                    final int w = mWinFrame.width();                    final int h = mWinFrame.height();                    final int l = msg.arg1;                    final int t = msg.arg2;                    mWinFrame.left = l;                    mWinFrame.right = l + w;                    mWinFrame.top = t;                    mWinFrame.bottom = t + h;                    if (mView != null) {                        forceLayout(mView);                    }                    requestLayout();                }                break;...private void performTraversals() {}->WindowManagerService.relayoutWindow().->WindowManagerService.performLayoutAndPlaceSurfacesLocked().

|--frameworks/base/service/java/com/android/server/wm/WindowState.java

/**     * Return whether this window is wanting to have a translation     * animation applied to it for an in-progress move.  (Only makes     * sense to call from performLayoutAndPlaceSurfacesLockedInner().)     */    boolean shouldAnimateMove() {//有可能不满足的一个条件        return mContentChanged && !mExiting && !mWinAnimator.mLastHidden && mService.okToDisplay()                && (mFrame.top != mLastFrame.top                        || mFrame.left != mLastFrame.left)                && (mAttrs.privateFlags&PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0                && (mAttachedWindow == null || !mAttachedWindow.shouldAnimateMove());    }    @Override    public void computeFrameLw(Rect pf, Rect df, Rect of, Rect cf, Rect vf, Rect dcf) {        ...        if (!mParentFrame.equals(pf)) {            //Slog.i(TAG, "Window " + this + " content frame from " + mParentFrame            //        + " to " + pf);            mParentFrame.set(pf);            mContentChanged = true;        }   ...}

//也就是说, 只需要pf的值变化, 即可触发.

|--frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java

//转了一圈还是回到了这里.    /** {@inheritDoc} */    @Override    public void layoutWindowLw(WindowState win, WindowManager.LayoutParams attrs,            WindowState attached) {        ...//AnsonCode 2016.12.21String mapPkg = "com.autonavi.amapauto";if(mapPkg.equals(attrs.packageName) && deadareaSide > 0){/****** resolution 1 //pf parentFrame//vf visibleFrame//df displayFrame//cf contentFrame//of overScanFrame//dcf decorContentFrame************//******** resolution 2 ************///0:off; 5:left; 6:rightint offset = 480;String b = pf.toShortString();if(deadareaSide == 5){pf.left  += offset;pf.right += offset;}else if(deadareaSide == 6){pf.left  -= offset;pf.right -= offset;}Log.d("ALog", "PhoneWindowManager.layoutWindowLw pfBefore(" + b + "): pfAfter(" + pf.toShortString() + ")");}        win.computeFrameLw(pf, df, of, cf, vf, dcf);        // Dock windows carve out the bottom of the screen, so normal windows        // can't appear underneath them.        if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleOrBehindKeyguardLw()                && !win.getGivenInsetsPendingLw()) {            setLastInputMethodWindowLw(null, null);            offsetInputMethodWindowLw(win);        }    }

OK, 完成


测试流程如下:

新增APP并把主题设置为Theme.Halo.Dialog.

APP打开后会显示在屏幕中间;

通过发送广播告诉PhoneWindowManager, 去修改pf的值.

带过渡动画的位移实现.


0 0
原创粉丝点击