悬浮窗的实现(如360悬浮窗效果)
悬浮窗实现
相信大家,都知晓360的悬浮窗口,非常潇洒。。。
如图:
现在,我也实现了具有吸附效果的悬浮窗。有图有真相...
看图: 吸附屏幕两侧的效果
废话少说,看代码。代码中,有详细注释...
布局文件:floating.xml(悬浮窗的布局)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="wrap_content" tools:context=".MainActivity" android:orientation="horizontal" > <ImageView android:id="@+id/icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/rekoo" /> <LinearLayout android:id="@+id/floats" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:background="@drawable/settings_bg_right" android:layout_marginTop="2dp" android:visibility="gone" > <LinearLayout android:id="@+id/btn1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:layout_marginLeft="2dp" > <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/settings_bbs_pressed" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="论坛" android:textColor="@android:color/white" /> </LinearLayout> <LinearLayout android:id="@+id/btn2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:orientation="vertical" > <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/settings_bind_phone_pressed" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="电话" android:textColor="@android:color/white" /> </LinearLayout> <LinearLayout android:id="@+id/btn3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:orientation="vertical" > <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/settings_service_pressed" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="关闭" android:textColor="@android:color/white" /> </LinearLayout> </LinearLayout> </LinearLayout>
源码:
package org.lqh.floatDemo; import android.app.Activity; import android.content.Context; import android.graphics.PixelFormat; import android.graphics.Rect; import android.os.Bundle; import android.view.Display; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.Toast; public class MainActivity extends Activity implements OnClickListener { private WindowManager windowManager = null; private WindowManager.LayoutParams windowManagerParams = null; private float mTouchX; private float mTouchY; private float x; private float y; private float mStartX; private float mStartY; private View view; private ImageView icon; private LinearLayout floats; private LinearLayout btn1; private LinearLayout btn2; private LinearLayout btn3; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE);//取消标题栏 getWindow().setFlags(WindowManager.LayoutParams. FLAG_FULLSCREEN , WindowManager.LayoutParams. FLAG_FULLSCREEN);//全屏 setContentView(R.layout.activity_main); view = LayoutInflater.from(this).inflate(R.layout.floating, null); icon = (ImageView) view.findViewById(R.id.icon); floats = (LinearLayout) view.findViewById(R.id.floats); btn1 = (LinearLayout) floats.findViewById(R.id.btn1); btn2 = (LinearLayout) floats.findViewById(R.id.btn2); btn3 = (LinearLayout) floats.findViewById(R.id.btn3); btn1.setOnClickListener(this); btn2.setOnClickListener(this); btn3.setOnClickListener(this); createView(); } private void createView() { // 1、获取WindowManager对象 windowManager = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE); // 2、设置LayoutParams(全局变量)相关参数 windowManagerParams = new WindowManager.LayoutParams(); // windowManagerParams = ((FloatApplication) getApplication()).getWindowParams(); //3、设置相关的窗口布局参数 (悬浮窗口效果) windowManagerParams.type = LayoutParams.TYPE_PHONE; // 设置window type windowManagerParams.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明 //4、设置Window flag == 不影响后面的事件 和 不可聚焦 windowManagerParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE; /* * 注意,flag的值可以为: * LayoutParams.FLAG_NOT_TOUCH_MODAL 不影响后面的事件 * LayoutParams.FLAG_NOT_FOCUSABLE 不可聚焦 * LayoutParams.FLAG_NOT_TOUCHABLE 不可触摸 */ //5、 调整悬浮窗口至左上角,便于调整坐标 windowManagerParams.gravity = Gravity.LEFT | Gravity.TOP; // 以屏幕左上角为原点,设置x、y初始值 windowManagerParams.x = 0; windowManagerParams.y = 80; //6、设置悬浮窗口长宽数据 windowManagerParams.width = LayoutParams.WRAP_CONTENT; windowManagerParams.height = LayoutParams.WRAP_CONTENT; //获得屏幕的宽高 Display display = windowManager.getDefaultDisplay(); final int screenWith = display.getWidth(); int screenHeight = display.getHeight(); System.out.println("screenWith="+screenWith+",screenHeight="+screenHeight); icon.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { //1、获取到状态栏的高度 Rect frame = new Rect(); icon.getWindowVisibleDisplayFrame(frame); int statusBarHeight = frame.top; System.out.println("状态栏高度:"+statusBarHeight); //2、获取相对屏幕的坐标,即以屏幕左上角为原点 。y轴坐标= y(获取到屏幕原点的距离)-状态栏的高度 x = event.getRawX(); y = event.getRawY() - statusBarHeight; // statusBarHeight是系统状态栏的高度 System.out.println("x="+x+",y="+y); //3、处理触摸移动 switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 捕获手指触摸按下动作 // 获取相对View的坐标,即以此View左上角为原点 mTouchX = event.getX(); mTouchY = event.getY(); mStartX = x; mStartY = y; System.out.println(",mTouchX=" + mTouchX + ",mTouchY=" + mTouchY); break; case MotionEvent.ACTION_MOVE: // 捕获手指触摸移动动作 updateViewPosition(); break; case MotionEvent.ACTION_UP: // 捕获手指触摸离开动作 float left = x-mTouchX; if(left <= screenWith/2){//图标icon吸附在左边 x = mTouchX; }else {//图标icon吸附在右边 x = mTouchX + screenWith; } updateViewPosition(); //移动终点的坐标,重置为0 mTouchX = mTouchY = 0; //移动距离少于5 ,则视为点击,触发点击的回调 if ((x - mStartX) < 5 && (y - mStartY) < 5) { onClick(v); } break; } return true; } }); windowManager.addView(view, windowManagerParams); // 显示myFloatView图像 } /** * 用于更新 悬浮窗位置参数 * */ private void updateViewPosition() { windowManagerParams.x = (int) (x - mTouchX); windowManagerParams.y = (int) (y - mTouchY); System.out.println("wp.x="+windowManagerParams.x+",wp.y="+windowManagerParams.y); // 刷新屏幕显示 windowManager.updateViewLayout(view, windowManagerParams); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.icon: if (floats.getVisibility() == View.VISIBLE) { floats.setVisibility(View.GONE); } else { floats.setVisibility(View.VISIBLE); } break; case R.id.btn1: Toast.makeText(this,"亲,我是论坛!", 2).show(); break; case R.id.btn2: Toast.makeText(this,"亲,我是手机验证!", 2).show(); break; case R.id.btn3: windowManager.removeView(view); android.os.Process.killProcess(android.os.Process.myPid()); break; default: break; } } public void onDestroy() { super.onDestroy(); // 在程序退出(Activity销毁)时销毁悬浮窗口 // windowManager.removeView(view); } }
如有大家,不明白之处,尽情留言评价。。。