Android中的几种小窗口实现
来源:互联网 发布:淘宝女童模特 编辑:程序博客网 时间:2024/06/10 09:23
在Android经常会碰到各种各样的小窗口,如退出弹窗、菜单弹窗、通知弹窗等等。本文就介绍几种实现小窗口的实例,以后根据情景具体选择实现方法。
惯例,先例出大纲:
- Activity式伪弹窗
- Dialog式弹窗
- Window式弹窗
开始正文~~
1。Activity式伪弹窗
该种情况,其实就是一个Activity,我们只是通过style的作用,把内容部分显示,其他部分都透明化了。
首先,在创建一个Activity和它的布局,这方面不讲了,就一般创建活动流程;
然后,在res/values/styles.xml中添加Activity的具体style,代码及注释如下:
<style name="MyActivityStyle"> <item name="android:windowBackground">@android:color/transparent</item> <!--设置dialog的背景--> <item name="android:windowFrame">@null</item> <!--Dialog的windowFrame框为无--> <item name="android:windowNoTitle">true</item> <!--是否有title--> <item name="android:windowIsFloating">true</item> <!--是否浮现在activity之上--> <item name="android:windowIsTranslucent">true</item> <!--是否半透明--> <item name="android:windowContentOverlay">@null</item> <!--对话框是否有遮盖,这个不设置的话,可能会出现边框黑线--> <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item> <!--动画--> <item name="android:backgroundDimEnabled">true</item> <!-- 背景是否模糊显示--> </style>
然后,在AndroidManifest.xml中设置Activity的style:
<activity android:name="com.wuxianxi.hunman.smallwindows.MyActivity" android:theme="@style/MyActivityStyle" > </activity>
最后,还要在Activity中实现点击事件,如点击空白区退出Activity,很简单:
@Override public boolean onTouchEvent(MotionEvent event) { //点击外围,退出窗口 this.finish(); return true; }
到此,Activity式伪弹窗已经完成,是不是很简单~~
2。Dialog式弹窗
这里MyDialog的style,使用与上面Activity窗口一样的style, 这部分在此就不多讲了, 下面主要讲MyDialog的自定义过程。
首先,MyDialog的sytle与上面一样,不重复粘贴了。
然后,自定义MyDialog的布局文件xml, 如下:
<?xml version="1.0" encoding="UTF-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="280dp" android:layout_height="wrap_content" android:gravity="center_horizontal" android:background="@drawable/btn_style_two_normal" android:orientation="vertical" > <TextView android:id="@+id/dialog_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:padding="5dp" android:textColor="#333" android:textSize="20sp" /> <TextView android:id="@+id/dialog_detail" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="1dp" android:gravity="center_horizontal" android:padding="10dp" android:textColor="#333" android:textSize="16sp" /> <FrameLayout android:layout_width="match_parent" android:layout_height="50dp" android:layout_marginTop="25dp" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="#EDEDED" > <TextView android:id="@+id/dialog_yes" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:text="Yes" android:textColor="#727272" android:textSize="16sp" /> <TextView android:id="@+id/dialog_no" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:text="No" android:textColor="#727272" android:textSize="16sp" /> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="#ccc" /> <View android:layout_width="1dp" android:layout_height="match_parent" android:layout_gravity="center" android:background="#ccc" /> </FrameLayout></LinearLayout>
然后自定义MyDialog的View类,继承于Dialog类。其中要注意的是实现了点击的回调实现。而MyDialog的style,我直接在里面定义了, 如果想更改style,也可以当参数传进来。代码如下:
package com.wuxianxi.hunman.smallwindows;import android.app.Dialog;import android.content.Context;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.widget.TextView;public class MyDialog extends Dialog implements android.view.View.OnClickListener { private Context mContext; private String mTitle; private String mDetail; private TextView mTextTitle; private TextView mTextDetail; private TextView mButtonYes; private TextView mButtonNo; private onClickInterface mOnclClickInterface; public MyDialog(Context context, String title, String detail) { super(context, R.style.MyDialogStyle); this.mContext = context; this.mTitle = title; this.mDetail = detail; } @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); initView(); } private void initView() { LayoutInflater inflater = LayoutInflater.from(mContext); View view = inflater.inflate(R.layout.layout_dialog, null); setContentView(view); mButtonYes = (TextView) view.findViewById(R.id.dialog_yes); mButtonNo = (TextView) view.findViewById(R.id.dialog_no); mTextTitle = (TextView) view.findViewById(R.id.dialog_title); mTextDetail = (TextView) view.findViewById(R.id.dialog_detail); mTextTitle.setText(mTitle); mTextDetail.setText(mDetail); mButtonYes.setOnClickListener(this); mButtonNo.setOnClickListener(this); } public interface onClickInterface { public void clickYes(); public void clickNo(); } public void setOnClickInterface(onClickInterface onclClickInterface) { this.mOnclClickInterface = onclClickInterface; } @Override public void onClick(View v) { switch (v.getId()) { case R.id.dialog_yes: mOnclClickInterface.clickYes(); break; case R.id.dialog_no: mOnclClickInterface.clickNo(); break; default: break; } }}
最后当然是在应用中调用MyDialog实例
//注意下面第一个参数不能为getApplicationContext(),而应该是Activity, 因为办有activity才能添加窗口 final MyDialog dialog = new MyDialog(MainActivity.this, "Hunman - Dialog", "Hunman is a Dialog\nYes or No!"); dialog.show(); dialog.setOnClickInterface(new MyDialog.onClickInterface() { @Override public void clickYes() { dialog.dismiss(); Toast.makeText(getApplicationContext(), "Yes, Hunman is Dialog", Toast.LENGTH_LONG).show(); } @Override public void clickNo() { dialog.dismiss(); Toast.makeText(getApplicationContext(), "Yes, Hunman is not Dialog", Toast.LENGTH_LONG).show(); } });
MyDialog的自定义完成,界面不美观,但流程大概是这样~
3。Window式小窗口
使用WindowManager可以显示在其他应用最上层,甚至手机桌面最上层显示窗口。比如电量不足的弹窗。。
这其中有几个知识点要提前了解一下,方便对下面应用实例的理解:
1)WindowManager的了解,这里主要是通过WindowManager.addView()来添加弹出窗口,通过WindowManager.removeView()来关闭弹出的窗口,另外有可能需要用到WindowManager.updateView(), WindowManager主要就这三个函数调用。
具体可能考我之前的一博客:
http://blog.csdn.net/wxx614817/article/details/50500771
2)WindowManager.layoutparams的理解,它是WindowManager 接口的嵌套类;它继承于 ViewGroup.LayoutParams; 它用于向WindowManager描述Window的管理策略。主要是了解LayoutParams 中的各个成员常量的应用情况,如type/flags等。这个网上很多说明文档~
好了, 概念不多说, 直接上代码:
首先, AndroidManifest.xml里添加权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
然后,弹窗的布局:
<?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:layout_gravity="center" android:gravity="center" android:background="@android:color/transparent" android:orientation="vertical" > <LinearLayout android:id="@+id/view_layout" android:layout_width="280dp" android:layout_height="wrap_content" android:background="@drawable/confirm_dialog_bg2" android:gravity="center_horizontal" android:orientation="vertical" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:padding="5dp" android:text="Hunman - Window" android:textColor="#333" android:textSize="20sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="1dp" android:gravity="center_horizontal" android:padding="10dp" android:text="Human is a Activity\nYes or No?" android:textColor="#333" android:textSize="16sp" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:layout_marginTop="33dp" > <Button android:id="@+id/window_yes" android:layout_width="110dp" android:layout_height="wrap_content" android:background="@drawable/btn_style_green" android:gravity="center" android:onClick="YesButton" android:text="Yes" android:textColor="#fff" android:textSize="16sp" /> <Button android:id="@+id/window_no" android:layout_width="110dp" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:background="@drawable/btn_style_white" android:gravity="center" android:onClick="NoButton" android:text="No" android:textColor="#333" android:textSize="16sp" /> </LinearLayout> </LinearLayout></LinearLayout>
后面当然是弹窗的实现,里面要注意LayoutParams.type常量,如果设置为WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,则像Home/Back键的触发,弹窗监听不到,作用于后面背景应用或桌面,所以弹窗就可以实现一些桌面悬浮按钮的功能。此处不用这个,而用了WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,上代码:
package com.wuxianxi.hunman.smallwindows;import android.content.Context;import android.graphics.PixelFormat;import android.graphics.Rect;import android.util.Log;import android.view.Gravity;import android.view.KeyEvent;import android.view.LayoutInflater;import android.view.MotionEvent;import android.view.View;import android.view.WindowManager;import android.view.WindowManager.LayoutParams;import android.widget.Button;import android.widget.Toast;public class MyWindow { private Context mContext; private WindowManager mwinWindowManager; private View mView; private static boolean isShow = false; public MyWindow(Context context) { mContext = context.getApplicationContext(); } public void showMyWindow() { if (isShow) { return; } mwinWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); //设置WindowManager.LayoutParams的属性 WindowManager.LayoutParams params = new WindowManager.LayoutParams(); //类型 params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; //flags //如果设置了WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,弹出的View没焦点,收不到Back键的事件 //当按Back、Home键时,背景应用退出,弹出的view就可以悬浮在桌面了。 params.flags = WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; params.format = PixelFormat.TRANSLUCENT; params.width = LayoutParams.MATCH_PARENT; params.height = LayoutParams.MATCH_PARENT; params.gravity = Gravity.CENTER; //初始化View mView = initView(mContext); //点击back键,关闭window mView.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { Log.d("wxx", "onKey"); switch (keyCode) { case KeyEvent.KEYCODE_BACK: Log.d("wxx", "onKey BACK"); hideMyWindow(); return true; default: return false; } } }); mwinWindowManager.addView(mView, params); isShow = true; } private View initView(Context context) { LayoutInflater inflater = LayoutInflater.from(context); View view = inflater.inflate(R.layout.layout_window, null); Button btnYes = (Button) view.findViewById(R.id.window_yes); btnYes.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(mContext, "Window yes!", Toast.LENGTH_LONG).show(); hideMyWindow(); } }); Button btnNO = (Button) view.findViewById(R.id.window_no); btnNO.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(mContext, "Window No!", Toast.LENGTH_LONG).show(); hideMyWindow(); } }); //点击window窗口外围,关闭window final View wView = view.findViewById(R.id.view_layout); view.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { int x = (int) event.getX(); int y = (int) event.getY(); Rect rect = new Rect(); wView.getGlobalVisibleRect(rect); if (!rect.contains(x, y)) { hideMyWindow(); } return false; } }); return view; } public void hideMyWindow() { if (isShow && mView != null) { mwinWindowManager.removeView(mView); isShow = false; } }}
这里面有个小缺憾,就是代码里面的OnKeyListener不起作用,发现背景应用也不起作用,不明白为什么,一直没找到原因,那位大神如能给点意见,小弟万分感激。。
到此,三种方式的弹窗都已经完成~~
需要代码的,到我GitHub上面取,链接:
https://github.com/BabyWu/SmallWindows/tree/master/SmallWindows
- Android中的几种小窗口实现
- Android 7.0中的多窗口实现解析
- Android 7.0中的多窗口实现解析
- Android 7.0中的多窗口实现解析一
- Android 7.0中的多窗口实现解析
- Android 7.0中的多窗口-分屏-实现解析
- Android中的dialog窗口
- android弹出窗口实现
- 实现android悬浮窗口
- Android-聊天窗口实现
- Android实现悬浮窗口
- Android 多窗口实现
- Android 实现顶层窗口、悬浮窗口
- Android 实现顶层窗口、浮动窗口
- android WindowManager实现悬浮窗口
- android悬浮窗口的实现
- android悬浮窗口的实现
- android悬浮窗口的实现
- 规则
- 读写png
- android 来电拦截
- 待翻译---- Understanding Spring MVC Model and Session Attributes
- 时间戳日期相互转换
- Android中的几种小窗口实现
- leetcode219---Contains Duplicate II
- ZYNQ HLS图像处理加速总结(二)——Processing System软件部分
- 阿里云云服务器ECS Windows Server 2012 R2 64位标准版PHP环境搭建
- python中的lib的一些安装方法
- Android进阶——安卓接入微信,获取OpenID
- leetcode之Convert Sorted Array to Binary Search Tree
- NSData有值,NSData转换成NSString为nil
- Windows系统下查看JDK的版本和安装路径!