模仿qq视频通话的悬浮按钮的实例代码,如下所示;
public class floatingwindowservice extends service{ private static final string tag="ontouchlistener"; private static view mview = null; private static windowmanager mwindowmanager = null; private static context mcontext = null; public static boolean isshown = false; public windowmanager.layoutparams params = null; private int pixel; private int theoffset; @override public void oncreate() { super.oncreate(); } @override public int onstartcommand(intent intent, int flags, int startid) { pixel = intent.getintextra("pixel",1); showpopupwindow(this); return super.onstartcommand(intent, flags, startid); } /** * 显示弹出框 * * @param context * */ private void showpopupwindow(final context context) { if (isshown) { return; } isshown = true; // 获取应用的context mcontext = context.getapplicationcontext(); // 获取windowmanager mwindowmanager = (windowmanager) mcontext.getsystemservice(context.window_service); params = new windowmanager.layoutparams(); mview = setupview(context); // 类型 params.type = windowmanager.layoutparams.type_system_alert; int flags=windowmanager.layoutparams.flag_not_focusable; params.flags = flags; params.format = pixelformat.translucent; params.width = windowmanager.layoutparams.wrap_content; params.height = windowmanager.layoutparams.wrap_content; params.gravity = gravity.center; mwindowmanager.addview(mview, params); } /** * 隐藏弹出框 */ private static void hidepopupwindow() { if (isshown && null != mview) { mwindowmanager.removeview(mview); isshown = false; } } private int x=0; private int y=0; private int startx=0; private int starty=0; private view setupview(final context context) { view view = layoutinflater.from(context).inflate(r.layout.popupwindow, null); textview tv= (textview) view.findviewbyid(r.id.title); int w = view.measurespec.makemeasurespec(0,view.measurespec.unspecified); int h = view.measurespec.makemeasurespec(0,view.measurespec.unspecified); tv.measure(w, h); theoffset=(pixel-tv.getmeasuredwidth())/2-50; tv.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { intent intent =new intent(context,mainactivity.class); context.startactivity(intent); // toast.maketext(context,"点击事件",toast.length_long).show(); } }); tv.setontouchlistener(new view.ontouchlistener() { @override public boolean ontouch(view v, motionevent event) { switch (event.getaction()){ case motionevent.action_move: int newx= (int) (event.getrawx()-x); int newy= (int) (event.getrawy()-y); params.x=newx+startx; params.y=newy+starty; mwindowmanager.updateviewlayout(mview,params); break; case motionevent.action_down: x= (int) event.getrawx(); y= (int) event.getrawy(); break; case motionevent.action_up: if(params.x>=0){ params.x=theoffset; mwindowmanager.updateviewlayout(mview,params); } if(params.x<=-0){ params.x=-theoffset; mwindowmanager.updateviewlayout(mview,params); } log.i(tag,params.x+""); log.i(tag,params.y+""); //判断 从按住到抬起时候的移动距离, 如果如果移动距离大于20 那么就拦截事件,否则就不拦截事件,主要是处理点击事件的冲突 if(math.abs(startx-params.x)>20 ||math.abs(starty-params.y)>20 ){ //记录上一次的偏移量 startx=params.x; starty=params.y; return true; }else { startx=params.x; starty=params.y; return false; } } return false; } }); return view; } @nullable @override public ibinder onbind(intent intent) { return null; } @override public void ondestroy() { super.ondestroy(); if (mview != null) { isshown=false; mwindowmanager.removeview(mview); } } }
main
@override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); findviewbyid(r.id.open).setonclicklistener(this); findviewbyid(r.id.close).setonclicklistener(this); }
-点击开启 关闭悬浮按钮
@override public void onclick(view v) { switch (v.getid()){ case r.id.open: //判断是否拥有悬浮权限 //op 的值是 0 ~ 47,其中0代表粗略定位权限,1代表精确定位权限,24代表悬浮窗权限。(具体可以看看android源码在android.app下就有个appopsmanager类) if(utils.checkop(this,24)==0) { intent intent=new intent(mainactivity.this, floatingwindowservice.class); intent.putextra("pixel",utils.pixel(this)[0]); startservice(intent); }else { //引导用户进入悬浮权限设置界面 intent intent = new intent(settings.action_manage_overlay_permission, uri.parse("package:" + getpackagename())); startactivityforresult(intent, 200); } break; case r.id.close: stopservice(new intent(mainactivity.this,floatingwindowservice.class)); break; } }
判断权限 -获取屏幕的宽高
public class utils { public static int checkop(context context, int op){ final int version = build.version.sdk_int; if (version >= 19){ object object = context.getsystemservice("appops"); class c = object.getclass(); try { class[] carg = new class[3]; carg[0] = int.class; carg[1] = int.class; carg[2] = string.class; method lmethod = c.getdeclaredmethod("checkop", carg); return (integer) lmethod.invoke(object, op, binder.getcallinguid(), context.getpackagename()); } catch(nosuchmethodexception e) { e.printstacktrace(); } catch (illegalaccessexception e) { e.printstacktrace(); } catch (illegalargumentexception e) { e.printstacktrace(); } catch (invocationtargetexception e) { e.printstacktrace(); } } return -1; } /** * 获取屏幕的宽高 * @param context * @return */ public static int[] pixel(activity context){ displaymetrics dm = new displaymetrics(); context.getwindowmanager().getdefaultdisplay().getmetrics(dm); return new int[]{dm.widthpixels,dm.heightpixels}; } }
--popupwindow填充布局文件
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <linearlayout android:id="@+id/popup_window" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:color/white" android:orientation="vertical" > <textview android:background="@mipmap/ic_launcher" android:id="@+id/title" android:layout_width="50dp" android:layout_height="50dp"/> </linearlayout> </linearlayout>
以上所述是小编给大家介绍的android开发模仿qq视频通话悬浮按钮(实例代码),希望对大家有所帮助
如对本文有疑问, 点击进行留言回复!!
荐 面试官:kafka日志段如何读写都不知道,好意思说精通Kafka吗?
荐 如何写出一份“有理有据使人信服”的Android项目设计文档
荐 灵魂一问,Android中有代替HashMap的方法吗?
intent.setFlag的参数 FLAG_ACTIVITY_CLEAR_TASK 说明
网友评论