实现原理是用WindowManager添加视图,生命周期可以不跟随某一页面或某一应用,可以全屏浮动(状态栏除外)。只有一个主类FloatView。在应用中new一下就可以显示了。
需要添加权限:<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
需要添加权限:<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
参考了网上很多的例子,谢谢大家的分享。
主类FloatView贴在下面,详细的大家可以下载项目看看。
package com.example.testandroidproject;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;
public class FloatView extends ImageView implements OnTouchListener{
private float x; //touch事件相对于屏幕的位置
private float y;
private float mTouchX; //touch事件相对于控件左上角的位置
private float mTouchY;
private float mStartX;
private float mStartY;
private int screenWidth;//屏幕宽度
private int width;//控件宽度
private int statusBarHeight;//状态栏高度
private boolean is_translucent = true;//按钮是否是半透明效果,默认为true
private WindowManager windowManager;
private WindowManager.LayoutParams windowManagerParams;//此windowManagerParams用以保存悬浮窗口的属性
private OnClickListener mClickListener;
private final int SMALL_ALPHA = 100;//最小透明度
private final int BIG_ALPHA = 200;//最大透明度
private final int MSG_TRANSLUCENT = 1;//使按钮变半透明
//handler使用弱引用避免内存泄漏
private WeakReference
handler = new WeakReference
(new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch(msg.what){
case MSG_TRANSLUCENT:
alphaAnimator(BIG_ALPHA,SMALL_ALPHA);
is_translucent = true;
break;
}
}
});
public FloatView(Context context) {
this(context,null);
}
public FloatView(Context context, AttributeSet attrs) {
super(context, attrs);
DisplayMetrics dm = getResources().getDisplayMetrics();
screenWidth = dm.widthPixels;
statusBarHeight = getStatusHeight(context);
setPadding(0, 10, 0, 10);
//设置图片
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
setImageBitmap(bitmap);
setBackgroundResource(R.drawable.selector_bg_float_view);//设置背景点击效果
setViewAlpha(SMALL_ALPHA);//设置半透明效果
setOnTouchListener(this);//设置点击事件监听
windowManagerParams = new WindowManager.LayoutParams();
windowManagerParams.type = LayoutParams.TYPE_PHONE; // 设置window type
windowManagerParams.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明
//设置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 不可触摸 */
// 调整悬浮窗口至左上角,便于调整坐标
windowManagerParams.gravity = Gravity.LEFT | Gravity.TOP;
// 以屏幕左上角为原点,设置x、y初始值
windowManagerParams.x = 0;
windowManagerParams.y = 0;
// 设置悬浮窗口长宽数据
windowManagerParams.width = LayoutParams.WRAP_CONTENT;
windowManagerParams.height = LayoutParams.WRAP_CONTENT;
windowManager = (WindowManager) getContext()
.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
windowManager.addView(this, windowManagerParams); //显示FloatView
}
@Override
public boolean onTouch(View v, MotionEvent event) {
int ea = event.getAction();
if(is_translucent){
setViewAlpha(BIG_ALPHA);
is_translucent = false;
}
// 获取相对屏幕的坐标,即以屏幕左上角为原点
x = event.getRawX();
y = event.getRawY()-statusBarHeight; // statusBarHeight是系统状态栏的高度
switch(ea){
case MotionEvent.ACTION_DOWN:
setPressed(true);
// 获取相对View的坐标,即以此View左上角为原点
mTouchX = event.getX();
mTouchY = event.getY();
mStartX = x;
mStartY = y;
break;
case MotionEvent.ACTION_MOVE:
updateViewPosition(x-mTouchX,y-mTouchY);
break;
case MotionEvent.ACTION_UP:
if ((x - mStartX) < 5 && (y - mStartY) < 5&&mClickListener!=null)
mClickListener.onClick(this);
if(x<=screenWidth/2)
horizontalTranslate(x-mTouchX,0);
else
horizontalTranslate(x-mTouchX,screenWidth-width);
setPressed(false);//恢复未选中状态
handler.get().removeMessages(MSG_TRANSLUCENT);
handler.get().sendEmptyMessageDelayed(MSG_TRANSLUCENT, 3000);
default:
break;
}
return true;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//获取测试完成后的宽度
width = getWidth();
}
/**
* 获得状态栏的高度
*
* @param context
* @return
*/
private int getStatusHeight(Context context) {
int statusBarHeight = 0;
try {
Class
c = Class.forName("com.android.internal.R$dimen");
Object o = c.newInstance();
Field field = c.getField("status_bar_height");
int x = (Integer) field.get(o);
statusBarHeight = getResources().getDimensionPixelSize(x);
} catch (Exception e) {
e.printStackTrace();
}
return statusBarHeight;
}
/**
* 水平平移属性动画
* @param xStart 水平移动开始位置
* @param xEnd 水平移动结束位置
*/
private void horizontalTranslate(float xStart,float xEnd){
if(xStart==xEnd)
return;
ValueAnimator animation = ValueAnimator.ofFloat(xStart,xEnd);
animation.setDuration(300);
animation.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float x = (Float)animation.getAnimatedValue();
updateViewPosition(x,y-mTouchY);
}
});
animation.setInterpolator(new DecelerateInterpolator());
animation.start();
}
/**
* 渐变透明度
* @param startA
* @param endA
*/
private void alphaAnimator(int startA,int endA){
ValueAnimator animation = ValueAnimator.ofInt(startA,endA);
animation.setDuration(1000);
animation.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int value = (int)animation.getAnimatedValue();
setViewAlpha(value);
}
});
animation.setInterpolator(new AccelerateInterpolator());
animation.start();
}
/**
* 设置透明度
* @param alpha
*/
private void setViewAlpha(int alpha){
getBackground().setAlpha(alpha);
setImageAlpha(alpha);
}
/**
* 更新浮动窗口位置参数
* @param x
* @param y
*/
private void updateViewPosition(float x,float y) {
windowManagerParams.x = (int) x;
windowManagerParams.y = (int) y;
windowManager.updateViewLayout(this, windowManagerParams); // 刷新显示
}
@Override
public void setOnClickListener(OnClickListener l) {
this.mClickListener = l;
}
/**
* 销毁控件
*/
public void destroy(){
windowManager.removeView(this);
}
}
项目资源下载地址:http://download.csdn.net/detail/igaocx/9690182