顶级窗口会显示在所有视图之上,可以利用此特性用来显示优先级高的业务。
我把它可分为常规式顶级窗口和遮罩式顶级窗口。
常规式顶级窗口不影响其他组件获取焦点(图1);遮罩式顶级窗口顾名思义就是把其他组件都遮住了(图2)。
??????????????????????????? 图1
?
?
?????????????????????? ???? 图2
?
实现方式:
先启动一个服务(aidl),由该服务去绘制窗口,并对外提供绘制接口(实现见下面代码);
单独写一个应用(如上),用来连接服务并显示顶级窗口。
?
?
服务端控制顶级窗口显示与销毁的代码:
/** * 该服务用来测试顶级窗口的设置. * @author QiShuang * */public class MService extends Service { private static final int WRAP = WindowManager.LayoutParams.WRAP_CONTENT; private static final int FILL = WindowManager.LayoutParams.FILL_PARENT; /** 常规的顶级窗口--该顶级view下的部件可以继续操作 */ public static final int TYPE_TOPLEVEL_WIN_NORMAL = 1; /**遮罩式(模式)顶级窗口--该顶级view下的部件被遮住,不可以操作 */ public static final int TYPE_TOPLEVEL_WIN_MODAL = 2; private WindowManager wm; private View subView; @Override public void onCreate() { super.onCreate(); showToast("remote service onCreate..."); } @Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId); showToast("remote service onStart..."); } @Override public IBinder onBind(Intent intent) { showToast("remote service onBind..."); return iBinder; } @Override public boolean onUnbind(Intent intent) { showToast("remote service onUnbind..."); return super.onUnbind(intent); } @Override public void onDestroy() { super.onDestroy(); showToast("remote service onDestroy..."); } public void showToast(String msg) { Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); } private Handler handler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case 1: {// drawTopWindow wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); subView = getLayout(); WindowManager.LayoutParams mWmlp = getWinLayParams(msg.arg1); wm.addView(subView, mWmlp); break; } case 2: {// cancelTopWindow if(wm!=null && subView!=null){ wm.removeViewImmediate(subView); subView=null; } break; } } }; }; private IBinder iBinder = new IService.Stub() { public void drawTopWin(int type) throws RemoteException { Message msg = new Message(); msg.what = 1; msg.arg1 = type; handler.sendMessage(msg); //10s后消失 handler.postDelayed(new Runnable() { public void run() { handler.sendEmptyMessage(2); } }, 10000); } public void cancelTopWin() throws RemoteException { handler.sendEmptyMessage(2); } }; // 构造布局View private View getLayout() { LinearLayout layout = new LinearLayout(this);// layout.setLayoutParams(new LinearLayout.LayoutParams(WRAP,WRAP)); layout.setBackgroundColor(Color.YELLOW); layout.setOrientation(LinearLayout.VERTICAL); layout.setGravity(Gravity.CENTER); TextView tx = new TextView(this); tx.setLayoutParams(new LinearLayout.LayoutParams(200,100)); tx.setTextColor(Color.BLUE); tx.setGravity(17); tx.setText("我站在山峰之巅!!!"); Button btn = new Button(this); btn.setLayoutParams(new LinearLayout.LayoutParams(WRAP,WRAP)); btn.setText("OK"); btn.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { handler.sendEmptyMessage(2); } }); layout.addView(tx); layout.addView(btn); return layout; } private LayoutParams getWinLayParams(int type) { WindowManager.LayoutParams wlp = new WindowManager.LayoutParams(FILL,WRAP); wlp.alpha = 0.5f; wlp.dimAmount = .5f; if(type==TYPE_TOPLEVEL_WIN_MODAL){//模式顶级窗口 wlp.flags = WindowManager.LayoutParams.FLAG_DIM_BEHIND;//任何部件都在其之下,可以通过dimAmount(0~1.0)设置透明度 }else if(type==TYPE_TOPLEVEL_WIN_NORMAL){//常规顶级窗口 wlp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; // 不抢聚焦点 } wlp.flags = wlp.flags | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; wlp.flags = wlp.flags | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; //allow window to extend outside of the screen wlp.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; //系统提示类型 wlp.width = WRAP;//WindowManager.LayoutParams.MATCH_PARENT; wlp.height = WRAP;//WindowManager.LayoutParams.MATCH_PARENT; wlp.gravity = Gravity.CENTER; return wlp; }}
?
step1:设置WindowManager.LayoutParams属性(flags、type很重要);
step2:定义要在窗口中显示的view;
step3:将view加入到WindowManager中。
?
此功能会涉及到以下2个权限,加入到manifest.xml中即可:
<uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
?<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
1 楼 凌波微步1206 2012-03-19
74.行 private IBinder iBinder = new IService.Stub() {
IService.Stub看不懂!出错了 麻烦楼主讲解下
IService.Stub看不懂!出错了 麻烦楼主讲解下

2 楼 xiaofeng001 2012-03-28
凌波微步1206 写道
74.行 private IBinder iBinder = new IService.Stub() {
IService.Stub看不懂!出错了 麻烦楼主讲解下
IService.Stub看不懂!出错了 麻烦楼主讲解下

好久没有搞Android了,记得IService.Stub是根据IService.aidl文件自动生成的一个代理类。你可以在aidl文件中定义业务接口,我只在其中定义了drawTopWin()和cancelTopWin()方法,希望对你有用。