Android窗口化app位移

简介: Android窗口化app位移

强制移动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.21
  String 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:right
    int 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的值.


带过渡动画的位移实现.


相关文章
|
3月前
|
XML Java 数据库
安卓项目:app注册/登录界面设计
本文介绍了如何设计一个Android应用的注册/登录界面,包括布局文件的创建、登录和注册逻辑的实现,以及运行效果的展示。
277 0
安卓项目:app注册/登录界面设计
|
4天前
|
Dart 前端开发 Android开发
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
5月前
|
Android开发
Android Stadio Build 窗口字符串乱码问题
在使用Android Studio过程中,如果遇到Build窗口字符串乱码问题,可以通过编辑`studio.vmoptions`文件添加`-Dfile.encoding=UTF-8`配置并重启Android Studio来解决。
205 1
Android Stadio Build 窗口字符串乱码问题
|
21天前
|
存储 监控 API
app开发之安卓Android+苹果ios打包所有权限对应解释列表【长期更新】-以及默认打包自动添加权限列表和简化后的基本打包权限列表以uniapp为例-优雅草央千澈
app开发之安卓Android+苹果ios打包所有权限对应解释列表【长期更新】-以及默认打包自动添加权限列表和简化后的基本打包权限列表以uniapp为例-优雅草央千澈
|
4月前
|
Java 数据库 Android开发
一个Android App最少有几个线程?实现多线程的方式有哪些?
本文介绍了Android多线程编程的重要性及其实现方法,涵盖了基本概念、常见线程类型(如主线程、工作线程)以及多种多线程实现方式(如`Thread`、`HandlerThread`、`Executors`、Kotlin协程等)。通过合理的多线程管理,可大幅提升应用性能和用户体验。
165 15
一个Android App最少有几个线程?实现多线程的方式有哪些?
|
4月前
|
存储 开发工具 Android开发
使用.NET MAUI开发第一个安卓APP
【9月更文挑战第24天】使用.NET MAUI开发首个安卓APP需完成以下步骤:首先,安装Visual Studio 2022并勾选“.NET Multi-platform App UI development”工作负载;接着,安装Android SDK。然后,创建新项目时选择“.NET Multi-platform App (MAUI)”模板,并仅针对Android平台进行配置。了解项目结构,包括`.csproj`配置文件、`Properties`配置文件夹、平台特定代码及共享代码等。
382 2
|
4月前
|
XML Android开发 数据格式
🌐Android国际化与本地化全攻略!让你的App走遍全球无障碍!🌍
在全球化背景下,实现Android应用的国际化与本地化至关重要。本文以一款旅游指南App为例,详细介绍如何通过资源文件拆分与命名、适配布局与方向、处理日期时间及货币格式、考虑文化习俗等步骤,完成多语言支持和本地化调整。通过邀请用户测试并收集反馈,确保应用能无缝融入不同市场,提升用户体验与满意度。
158 3
|
4月前
|
Java 数据库 Android开发
一个Android App最少有几个线程?实现多线程的方式有哪些?
本文介绍了Android应用开发中的多线程编程,涵盖基本概念、常见实现方式及最佳实践。主要内容包括主线程与工作线程的作用、多线程的多种实现方法(如 `Thread`、`HandlerThread`、`Executors` 和 Kotlin 协程),以及如何避免内存泄漏和合理使用线程池。通过有效的多线程管理,可以显著提升应用性能和用户体验。
132 10
|
3月前
|
安全 网络安全 Android开发
深度解析:利用Universal Links与Android App Links实现无缝网页至应用跳转的安全考量
【10月更文挑战第2天】在移动互联网时代,用户经常需要从网页无缝跳转到移动应用中。这种跳转不仅需要提供流畅的用户体验,还要确保安全性。本文将深入探讨如何利用Universal Links(仅限于iOS)和Android App Links技术实现这一目标,并分析其安全性。
491 0
|
4月前
|
API Android开发 数据安全/隐私保护
Android经典实战之窗口和WindowManager
本文介绍了Android开发中“窗口”的基本概念及其重要性。窗口是承载用户界面的基础单位,而`WindowManager`系统服务则负责窗口的创建、更新和移除等操作。了解这些概念有助于开发复杂且用户体验良好的应用。
90 2

热门文章

最新文章