Android之Window、WindowManager(一):PopupWindow添加浮动窗口内部过程
来源:互联网 发布:邓亚萍 20亿 知乎 编辑:程序博客网 时间:2024/05/01 17:06
通常情况下,如果想显示一个界面,首先想到的是建立一个Activity,然后所有的操作在Activity里面实现,或者是一个Dialog或者Toast。本文通过对PopupWindow的实现过程解析,指出添加界面的另外一种方式:直接用WindowManager显示添加或删除View的过程。
一、PopupWindow向Window添加视图的过程
PopupWindow是最简单的浮动窗口,显示在当前activity窗口上面,显示一个PopupWindow的代码非常简单,如下:
<span style="font-size:18px;">//弹出pop窗口private void PopView(){View view =View.inflate(this, R.layout.list_item, null);PopupWindow popup=new PopupWindow(view,LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT,true);popup.setBackgroundDrawable(getResources().getDrawable(R.drawable.ic_launcher));popup.showAsDropDown(bt);}</span>
很显然,new PopupWindo()以及setBackgroundDrawabl()都只是做了一些初始化的工作,Android加载PopupWindow浮动窗口的所有逻辑过程和工作,都是在showAsDropDown()方法中进行的,以此为突破口,可以逐级分析浮动窗口内部加载过程。
<span style="font-size:18px;"> /** * Display the content view in a popup window at the specified location. If the popup window cannot fit on screen, it will be clipped. See android.view.WindowManager.LayoutParams for more information on how gravity and the x and y parameters are related. */ public void showAtLocation(View parent, int gravity, int x, int y) { showAtLocation(parent.getWindowToken(), gravity, x, y); }</span>
parent一般是当前activity的view,主要是传递popupwindow当前activity界面的IBinder,继续往下走:
public void showAtLocation(IBinder token, int gravity, int x, int y) { WindowManager.LayoutParams p = createPopupLayout(token); ... invokePopup(p); }
核心方法只有两个:createPopupLayout和invokePopup。createPopupLayout主要是设置PopupWindow相对窗体的LayoutParams:
private WindowManager.LayoutParams createPopupLayout(IBinder token) { // 生成layout parameters WindowManager.LayoutParams p = new WindowManager.LayoutParams(); // 默认gravity在左上角 // X、Y分别是相对偏移量 p.gravity = Gravity.START | Gravity.TOP; p.width = mLastWidth = mWidth; p.height = mLastHeight = mHeight; //必须设置背景 if (mBackground != null) { p.format = mBackground.getOpacity(); } else { p.format = PixelFormat.TRANSLUCENT; } // p.flags = computeFlags(p.flags); // p.type = mWindowLayoutType; // p.token = token; // p.softInputMode = mSoftInputMode; p.setTitle("PopupWindow:" + Integer.toHexString(hashCode())); return p; }
invokePopup最终调用WindowManager.addView()方法,将PopupWindow中的内容视图及其LayoutParams属性,添加到Window:
/** * 将PopupWindow的内容视图添加到window manger */ private void invokePopup(WindowManager.LayoutParams p) { if (mContext != null) { p.packageName = mContext.getPackageName(); } mPopupView.setFitsSystemWindows(mLayoutInsetDecor); setLayoutDirectionFromAnchor(); mWindowManager.addView(mPopupView, p); //将view添加到window中,p是相对window的属性 }
分析到这里,我们可以总结一下:
Android平台是一个又一个的Activity组成的,每一个Activity有一个或者多个View构成。通常情况下,如果想显示一个界面,首先想到的是建立一个Activity,然后所有的操作在Activity里面实现,或者是一个Dialog或者Toast。这种方式固然简单,但是在有些情况下,我们要求的只是简单的显示,用Activity显然是多余,这个时候,我们如何处理呢?
通过PopupWindow的实现过程,我们了解,原来整个Android的窗口机制是基于一个叫做WindowManager,这个接口可以添加view到屏幕,也可以从屏幕删除view。它面向的对象一端是屏幕,另一端就是View,直接忽略我们以前的Activity或者Dialog之类的东东。其实我们的Activity或者Diolog底层的实现也是通过WindowManager,这个WindowManager是全局的,整个系统就是这个唯一的东东。它是显示View的最底层了。
所以,PopupWindow的过程,其实就是直接用WindowManager显示View的过程。
二、模仿PopupWindow的一个自定义CustomPopupWindow
这个Demo仅仅实现了showAtLocation、createPopupLayout、invokePopup三个方法,就可以实现简单的PopupWindow效果。
自定义CustomPopupWindow控件类:
package com.custom.view;import android.content.Context;import android.graphics.PixelFormat;import android.os.IBinder;import android.view.Gravity;import android.view.View;import android.view.WindowManager;import android.widget.PopupWindow;public class CustomPoupuWindow {private int height;private int width;private View contView;private Context context;private WindowManager wm;public CustomPoupuWindow(View contView,int width,int height){this.contView=contView;this.context=contView.getContext();this.width=width;this.height=height;wm=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);}//在指定位置显示popupwindow public void showAtLocation(int gravity, int x, int y) { WindowManager.LayoutParams p = createPopupLayout(); //p.windowAnimations = computeAnimationResource(); //preparePopup(p); if (gravity == Gravity.NO_GRAVITY) { gravity = Gravity.TOP | Gravity.START; } p.gravity = gravity; p.x = x; p.y = y; invokePopup(p); } //设置popupWindow的contView相对window的属性 private WindowManager.LayoutParams createPopupLayout() { //获取WindowManager // generates the layout parameters WindowManager.LayoutParams p = new WindowManager.LayoutParams(); // these gravity settings put the view at the top left corner of the // screen. The view is then positioned to the appropriate location // by setting the x and y offsets to match the anchor's bottom // left corner p.gravity = Gravity.START | Gravity.TOP; p.width = width; p.height = height; /* if (mBackground != null) { p.format = mBackground.getOpacity(); } else { p.format = PixelFormat.TRANSLUCENT; }*/ p.format = PixelFormat.TRANSLUCENT; p.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN; p.type = WindowManager.LayoutParams.TYPE_PHONE; //p.token = token; //p.softInputMode = mSoftInputMode; p.setTitle("CustomPopupWindow:" ); return p; } private void invokePopup(WindowManager.LayoutParams p) { //mPopupView.setFitsSystemWindows(mLayoutInsetDecor); //setLayoutDirectionFromAnchor(); wm.addView(contView, p); }}
调用CustomPopupWindow过程
private void CustomPopView(){View view =View.inflate(this, R.layout.list_item, null);CustomPoupuWindow popup=new CustomPoupuWindow(view,LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);popup.showAtLocation( Gravity.NO_GRAVITY, 0, 100);}
自定义XML文件:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/file_name" android:layout_gravity="center_vertical" android:layout_marginLeft="20dp" android:background="@drawable/ic_launcher" /> </LinearLayout>
效果图:
- Android之Window、WindowManager(一):PopupWindow添加浮动窗口内部过程
- Android解析WindowManager(三)Window的添加过程
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Unity自定义窗体插件工具
- android bsdiff 增量升级更新 热补丁 hotpatch(一)
- hdoj 2187 悼念512汶川大地震遇难同胞——老人是真饿了
- 怎样才是理想的程序员
- 【Unity3D ugui】使用艺术字
- Android之Window、WindowManager(一):PopupWindow添加浮动窗口内部过程
- SpringMVC 基于注解的Controller @RequestMapping @RequestParam..
- codeforces 508 E. Arthur and Brackets
- 动态规划-最长递增序列(LIS)【模板】
- Mongodb 实现数据自动在后台删除--根据一个截止时间
- testNG+httpclient接口测试
- lampp 修改MySQL数据库存储路径
- android杂记7:drawable state各个属性详解
- 共同头部+ViewPager+ListView