当前位置: 首页 > news >正文

株洲公司做网站网站续费价格

株洲公司做网站,网站续费价格,60天做网站,360网站建设公司Window表示一个窗口的概念#xff0c;在日常开发中直接接触Window的机会并不多#xff0c;但却会经常用到Window#xff0c;activity、toast、dialog、PopupWindow、状态栏等都是Window。在Android中Window是个抽象类#xff0c;并且仅有一个实现类PhoneWindow。 1、Window… Window表示一个窗口的概念在日常开发中直接接触Window的机会并不多但却会经常用到Windowactivity、toast、dialog、PopupWindow、状态栏等都是Window。在Android中Window是个抽象类并且仅有一个实现类PhoneWindow。 1、Window  Android中Window有应用Window、子Window及系统Window三种类型分别对应不同的层级范围层级越高显示越靠前这里的“靠前”是指层级大的Window会覆盖在层级小的Window上面。 应用Window对应层级范围是1~99每个activity就对应一个应用Window如果在activity中创建了一个应用Window那么当跳转到另外一个Activity时该Window会被覆盖。应用Window的高度不受状态栏影响。子Window对应层级范围是1000~1999PopupWindow默认就是一个子Window可以修改PopupWindow的Window类型如果在activity中创建了一个子Window那么当跳转到另外一个Activity时该Window也会被覆盖。子Window的高度受状态栏影响。系统Window对应层级范围是2000~2999toast、状态栏等都是系统Window如果创建了一个系统Window那么只有当该应用被销毁时该Window才被会关闭排除主动关闭所以可以用系统Window实现像360那样的悬浮小球。系统Window需要设置uses-permission android:nameandroid.permission.SYSTEM_ALERT_WINDOW /权限否则会抛异常在6.0以上需要动态申请。系统Window的高度不受状态栏影响。 前面说了Window的层级下面就来看一个示例。 //代码参考了PopupWindow的源代码。private void startWindow() {//拿到activity中的wm对象在attach中创建是一个WindowManagerImpl对象wm (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);frame new PopupDecorView(this);frame.setLayoutParams(new ActivityzhoLayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));View view View.inflate(this, R.layout.window_layout, null);Button bt view.findViewById(R.id.window_layout_button);bt.setOnClickListener(new OnClickListener() {Overridepublic void onClick(View v) {dismiss();}});//重新设置WindowManager.LayoutParams的值WindowManager.LayoutParams p createPopupLayoutParams(frame.getWindowToken());frame.addView(view);wm.addView(frame, p);}private LayoutParams createPopupLayoutParams(IBinder windowToken) {final WindowManager.LayoutParams p new WindowManager.LayoutParams();//设置Window gravity。gravity 表示居中top表示位于顶部p.gravity Gravity.CENTER|Gravity.TOP;p.flags computeFlags(p.flags);//设置Window的类型其实这里我们也可以设置1~99、1000~1999、2000~2999之间的任意数字p.type LayoutParams.TYPE_APPLICATION;//设置Window Tokenp.token windowToken;//设置输入法模式p.softInputMode WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED;//设置Window动画p.windowAnimations 0;//设置Window像素格式p.format PixelFormat.TRANSLUCENT;// Used for debugging.p.setTitle(PopupWindow: Integer.toHexString(hashCode()));//设置Window宽p.width LayoutParams.MATCH_PARENT;//设置Window高p.height LayoutParams.WRAP_CONTENT;return p;}private int computeFlags(int curFlags) {curFlags ~(WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES |WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS |WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM |WindowManager.LayoutParams.FLAG_SPLIT_TOUCH);curFlags | WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;return curFlags;}//关闭Windowprivate void dismiss() {wm.removeView(frame);}private class PopupDecorView extends FrameLayout {public PopupDecorView(Context context) {super(context);}Overridepublic boolean dispatchKeyEvent(KeyEvent event) {if (event.getKeyCode() KeyEvent.KEYCODE_BACK) {if (getKeyDispatcherState() null) {return super.dispatchKeyEvent(event);}if (event.getAction() KeyEvent.ACTION_DOWN event.getRepeatCount() 0) {final KeyEvent.DispatcherState state getKeyDispatcherState();if (state ! null) {state.startTracking(event, this);}return true;} else if (event.getAction() KeyEvent.ACTION_UP) {final KeyEvent.DispatcherState state getKeyDispatcherState();if (state ! null state.isTracking(event) !event.isCanceled()) {dismiss();return true;}}return super.dispatchKeyEvent(event);} else {return super.dispatchKeyEvent(event);}}Overridepublic boolean dispatchTouchEvent(MotionEvent ev) { // if (mTouchInterceptor ! null mTouchInterceptor.onTouch(this, ev)) { // return true; // }return super.dispatchTouchEvent(ev);}} 复制代码 WindowManager.LayoutParams用于描述Window的参数关于其详细参数可以参考Android Activity应用窗口的创建过程分析这篇文章。  先来看WindowManager.LayoutParams的参数type也就是Window类型。下面来看不同Window类型的显示效果 系统Window及应用Window显示效果 子Window显示效果  粉色部分就是创建的Window可以看出系统及应用Window不受状态栏影响而子Window却因为状态栏导致按钮超出Window范围。所以可以认为子Window的高度被被状态栏占去一部分而其他类型Window则不受此影响让WIndow居中时子Window在手机中的位置也会比其他类型Window的位置高一些这里就不验证了至于子Window为什么在状态栏的下面那是因为状态栏的层级比子Window层级要高。  WindowManager.LayoutParams的flags也是一个非常重要的参数由于类型比较多这里就主要介绍以下几个类型。 FLAG_NOT_TOUCH_MODAL在此模式下系统会将当前Window区域以外的单击事件传递给底层的Window当前Window区域内的单击事件则自己处理。一般都需要开启此标记FLAG_NOT_FOCUSABLE在此模式下Window不能获取焦点也不能接受各种输入事件此标记会同时开启FLAG_NOT_TOUCH_MODAL最终事件会直接传递给下层的具有焦点的Window。所以如果Window中有EditText等输入控件时就不应该启用此标记。FLAG_SHOW_WHEN_LOCKED开启此模式可以让Window显示在锁屏的界面。 WindowManager.LayoutParams中比较常用的参数就上面两个当然也可以设置Window的宽高、动画、token等等这里就不一一叙述了。  从上面示例可以看出Window并不实际存在它是以一个View的形式展示在屏幕上。 2、WindowManager  WindowManager的主要功能是提供简单的API使得使用者可以方便地将一个View作为一个窗口添加到系统中它是一个接口继承自ViewManager接口ViewManager接口比较简单只有以下三个方法。 public interface ViewManager {public void addView(View view, ViewGroup.LayoutParams params);public void updateViewLayout(View view, ViewGroup.LayoutParams params);public void removeView(View view); } 复制代码 从方法名也可以看出对Window的增删改就是针对View的增删改。方法虽然只有三个但已经完全够用了。WindowManager的具体实现是WindowManagerImpl。 public final class WindowManagerImpl implements WindowManager {private final WindowManagerGlobal mGlobal WindowManagerGlobal.getInstance();private final Context mContext;//父Windowprivate final Window mParentWindow;private IBinder mDefaultToken;...//添加ViewOverridepublic void addView(NonNull View view, NonNull ViewGroup.LayoutParams params) {applyDefaultToken(params);mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);}//更新ViewOverridepublic void updateViewLayout(NonNull View view, NonNull ViewGroup.LayoutParams params) {applyDefaultToken(params);mGlobal.updateViewLayout(view, params);}...//异步移除ViewOverridepublic void removeView(View view) {mGlobal.removeView(view, false);}//同步移除ViewOverridepublic void removeViewImmediate(View view) {mGlobal.removeView(view, true);}... } 复制代码 这里采用了代理模式将所有操作交给WindowManagerGlobal来执行。首先来看Window的添加。 2.1、添加Window  在前面的例子中可以看到创建一个Window就是向WindowManagerImpl中添加一个View而WindowManagerImpl又将操作交给了WindowManagerGlobal来处理下面就来看看WindowManagerGlobal中addView的实现。 public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow) {//检查参数if (view null) {throw new IllegalArgumentException(view must not be null);}if (display null) {throw new IllegalArgumentException(display must not be null);}if (!(params instanceof WindowManager.LayoutParams)) {throw new IllegalArgumentException(Params must be WindowManager.LayoutParams);}//拿到Window的宽高、type等布局参数final WindowManager.LayoutParams wparams (WindowManager.LayoutParams) params;...ViewRootImpl root;View panelParentView null;synchronized (mLock) {...//查找View是否已经存在WindowManager不允许同一个View被添加两次int index findViewLocked(view, false);if (index 0) {//如果View已在被销毁的列表中那么就先销毁列表中存在的Viewif (mDyingViews.contains(view)) {// Dont wait for MSG_DIE to make its way through roots queue.mRoots.get(index).doDie();} else {//很常见的一个异常表示不能重复添加同一Viewthrow new IllegalStateException(View view has already been added to the window manager.);}// The previous removeView() had not completed executing. Now it has.}//如果是子Window则需要先找到它的父Viewif (wparams.type WindowManager.LayoutParams.FIRST_SUB_WINDOW wparams.type WindowManager.LayoutParams.LAST_SUB_WINDOW) {final int count mViews.size();for (int i 0; i count; i) {if (mRoots.get(i).mWindow.asBinder() wparams.token) {panelParentView mViews.get(i);}}}//创建一个新的ViewRootImplroot new ViewRootImpl(view.getContext(), display);//给View设置参数view.setLayoutParams(wparams);//保存ViewmViews.add(view);//保存ViewRootImplmRoots.add(root);//保存参数mParams.add(wparams);//绘制View、添加Windowtry {// 将作为窗口的控件设置给ViewRootImpl。这个动作将导致ViewRootImpl向WMS添加新的窗口、申请Surface以及托管控件在Surface上的重绘动作。这才是真正意义上完成了窗口的添加操作root.setView(view, wparams, panelParentView);} catch (RuntimeException e) {// BadTokenException or InvalidDisplayException, clean up.if (index 0) {removeViewLocked(index, true);}throw e;}}} 复制代码 在addView方法中主要做了参数检查、查找子Window的父View、创建ViewRootImpl对象并通过ViewRootImpl的setView方法来实现View的绘制及Window添加操作。下面来看ViewRootImpl中setView方法的实现。 public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {synchronized (this) {if (mView null) {//保存当前ViewmView view;...//保存参数attrs mWindowAttributes;...//绘制View。requestLayout();...try {...res mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,getHostVisibility(), mDisplay.getDisplayId(),mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,mAttachInfo.mOutsets, mInputChannel);} catch (RemoteException e) {....} finally {if (restore) {attrs.restore();}}...//添加失败if (res WindowManagerGlobal.ADD_OKAY) {mAttachInfo.mRootView null;//添加失败mAdded false;mFallbackEventHandler.setView(null);unscheduleTraversals();setAccessibilityFocus(null, null);//返回错误的原因相比很多错误信息大家都会遇到过switch (res) {//token出错case WindowManagerGlobal.ADD_BAD_APP_TOKEN:case WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN:throw new WindowManager.BadTokenException(Unable to add window -- token attrs.token is not valid; is your activity running?);case WindowManagerGlobal.ADD_NOT_APP_TOKEN:throw new WindowManager.BadTokenException(Unable to add window -- token attrs.token is not for an application);case WindowManagerGlobal.ADD_APP_EXITING:throw new WindowManager.BadTokenException(Unable to add window -- app for token attrs.token is exiting);//添加Window已存在case WindowManagerGlobal.ADD_DUPLICATE_ADD:throw new WindowManager.BadTokenException(Unable to add window -- window mWindow has already been added);case WindowManagerGlobal.ADD_STARTING_NOT_NEEDED:// Silently ignore -- we would have just removed it// right away, anyway.return;case WindowManagerGlobal.ADD_MULTIPLE_SINGLETON:throw new WindowManager.BadTokenException(Unable to add window mWindow -- another window of type mWindowAttributes.type already exists);//未申请权限当创建系统Window时是需要申请权限的case WindowManagerGlobal.ADD_PERMISSION_DENIED:throw new WindowManager.BadTokenException(Unable to add window mWindow -- permission denied for window type mWindowAttributes.type);case WindowManagerGlobal.ADD_INVALID_DISPLAY:throw new WindowManager.InvalidDisplayException(Unable to add window mWindow -- the specified display can not be found);//window类型未在1~991000~1999,2000~2999这个范围内。case WindowManagerGlobal.ADD_INVALID_TYPE:throw new WindowManager.InvalidDisplayException(Unable to add window mWindow -- the specified window type mWindowAttributes.type is not valid);}throw new RuntimeException(Unable to add window -- unknown error code res);}...}}} 复制代码 该方法真正意义上完成了View的绘制及Window的添加操作来看requestLayout与mWindowSession.addToDisplay这两个方法。前者主要是申请Surface以及托管控件在Surface上的重绘动作即View的测量、布局、绘制流程。关于该方法详细内容可以参考Android源码分析之View绘制流程、《深入理解Android 卷III》第六章 深入理解控件ViewRoot系统这两篇文章。后者主要向WindowManagerService(WMS)添加新的窗口。  总体来说WindowManagerGlobal通过父窗口调整了布局参数之后将新建的ViewRootImpl、控件以及布局参数保存在mRootsmViews及mParams这三个数组中然后将View交给新建的ViewRootImpl进行处理从而完成了窗口的添加。  WindowManagerGlobal管理窗口的原理如下图所示。 来自于《深入理解Android 卷III》第六章 深入理解控件ViewRoot系统2.2、更新Window  相对于添加Window更新Window就简单很多了主要是修改布局参数然后调用ViewRootImpl.setLayoutParams来更新View。 public void updateViewLayout(View view, ViewGroup.LayoutParams params) {if (view null) {throw new IllegalArgumentException(view must not be null);}if (!(params instanceof WindowManager.LayoutParams)) {throw new IllegalArgumentException(Params must be WindowManager.LayoutParams);}final WindowManager.LayoutParams wparams (WindowManager.LayoutParams)params;//修改view的布局参数view.setLayoutParams(wparams);synchronized (mLock) {int index findViewLocked(view, true);//查找view对应的ViewRootImplViewRootImpl root mRoots.get(index);//移除旧的布局参数mParams.remove(index);//添加新的布局参数mParams.add(index, wparams);//更新布局参数root.setLayoutParams(wparams, false);}}复制代码 代码还是比较简单的下面就来看ViewRootImpl中setLayoutParams方法的实现。 void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) {synchronized (this) {//修改布局参数的操作...//对View进行重新测量、布局、绘制mWindowAttributesChanged true;scheduleTraversals();}} 复制代码 该方法也比较简单主要就是调用scheduleTraversals方法来对View进行重新测量、布局及绘制。scheduleTraversals在这里就不详细讲解了在View的绘制流程中已经讲解的很清楚了。  总体上来说Window的更新操作就是对View的重新测量、布局及绘制。 2.2、关闭Window  关闭Window调用的是WindowManagerGlobal的removeView方法。 public void removeView(View view, boolean immediate) {if (view null) {throw new IllegalArgumentException(view must not be null);}synchronized (mLock) {int index findViewLocked(view, true);View curView mRoots.get(index).getView();removeViewLocked(index, immediate);if (curView view) {return;}throw new IllegalStateException(Calling with view view but the ViewAncestor is attached to curView);}}//移除Viewprivate void removeViewLocked(int index, boolean immediate) {ViewRootImpl root mRoots.get(index);View view root.getView();if (view ! null) {//拿到输入法管理InputMethodManager imm InputMethodManager.getInstance();if (imm ! null) {//关闭输入法Windowimm.windowDismissed(mViews.get(index).getWindowToken());}}//返回true表示异步删除false表示同步删除boolean deferred root.die(immediate);if (view ! null) {view.assignParent(null);if (deferred) {//异步删除只是将view添加到mDyingViews这个集合即可。mDyingViews.add(view);}}}//该方法在ViewRootImpl中boolean die(boolean immediate) {//立即移除Viewif (immediate !mIsInTraversal) {doDie();return false;}...//异步移除ViewmHandler.sendEmptyMessage(MSG_DIE);return true;} 复制代码 最终还是通过ViewRootImpl来实现的Window的关闭immediate为true时则代表立即删除当前Window的信息及资源释放否则异步执行。当异步移除View时也是调用了ViewRootImpl的doDie方法只不过异步需要排队而已。 void doDie() {//如果在非UI线程则报错checkThread();...synchronized (this) {if (mRemoved) {return;}mRemoved true;if (mAdded) {//资源释放dispatchDetachedFromWindow();}if (mAdded !mFirst) {destroyHardwareRenderer();...}mAdded false;}//从mRoots、mViews及mParams这三个数组中移除信息WindowManagerGlobal.getInstance().doRemoveView(this);} 复制代码 在该方法里主是调用dispatchDetachedFromWindow进行资源释放在dispatchDetachedFromWindow中会释放Surface所占内存、从WMS中移除Window、停止动画、线程等。最后刷新WindowManagerGlobal中mRoots、mViews及mParams这三个数组的数据。  当调用ViewRootImpl的doDie方法后该ViewRootImpl也就完成了自己的使命了等待被GC回收。因此可以得出这样一个结论ViewRootImpl的生命从setView()开始到die()结束。 3、总结  到这里相必对WIndow及WindowManager就有了较深入的了解主要总结以下几点。 Window分为应用Window、子Window及系统Window不同类型的Window对应着不同的层级范围层级越高显示越靠前。子Window的高度受状态栏的影响。而系统Window及应用Window则无此限制所以实现一个子Window需要考虑状态栏的高度一个Window对应着一个ViewRootImpl也就是说ViewRootImpl与Window同生共死。Window的更新其实对View的重新执行测量、布局及绘制。【参考资料】 《Android艺术探索》 Android Activity应用窗口的创建过程分析 Android Window 机制探索 《深入理解Android 卷III》第四章 深入理解WindowManagerService 《深入理解Android 卷III》第六章 深入理解控件ViewRoot系统 [深入理解Android卷一全文-第八章]深入理解Surface系统
http://www.zqtcl.cn/news/387990/

相关文章:

  • 企业网站禁忌手机端网站开发页
  • 深圳外贸商城网站建设wordpress 空搜索
  • 做微信的网站有哪些shop商城系统
  • 网站落地页如何做优化大师免费下载安装
  • 本地计算机做网站服务器做算命网站
  • 广州网站建设公司万齐网络科技做围棋题网站
  • 运动服装商城网站建设引流推广
  • 武进区城乡建设局网站聊城商城网站建设
  • 做网站开发赚钱吗网站建设电子书资料
  • wordpress 回收站在哪个文件夹建站之星模板好吗
  • 怎么用dw做博客网站天使投资平台官网
  • 淮安市网站建设crm网站
  • 门户网站主要特点和功能深圳地铁优化
  • 银川网站推广方式湖南建工交通建设有限公司网站
  • 知道网站域名怎么联系怎么创建自己的公司网站
  • 淘宝网站开发多少金额网站优化 福州
  • 百度推广让我先做虚拟网站后进一步优化落实
  • 好的网站建设启示汕头网页设计网站方案
  • 深圳网站制作开发免费精准客户软件
  • 网站超链接用什么南宁行业平台开发公司
  • 注册门户网站襄樊seo快速排名
  • 优秀的手机网站iis 设置此网站的访问权限
  • 用nat123做自己的网站深圳市建设工程质量检测中心官网
  • 网上做衣服的网站废旧网站哪个做的最好
  • 网站开发设置网页端口wordpress 知识库
  • 网站建设的方法有四种开发一款新闻app需要多少钱
  • 成都网站建站公司2023年防疫新政策
  • 17做网店一样的网站十大互联网培训机构
  • 中企网络科技建站施工企业oa办公系统
  • 成都网站推广公司排名淘宝商家网站建设