1、申请悬浮与其他应用上的权限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
2、调用WindowManager.addView(view,params) 显示悬浮view。实现如微信视频通话,悬浮于所有应用之上
隐藏悬浮view mWindowManager.removeView(mview);
实现demo https://download.csdn.net/download/meixi_android/89447589
实现效果:
实现方法:
在自定义baseActivity里面添加viwe即可。在子activity里刷新悬浮View即可
public abstract class BaseActivity extends BaseCommonActivity {
LinearLayout saoli,ewmli;
ImageView imageView;
private QrCodeDialog mMQrCodeDialog;
public static final int SECURITY_ACTIVITY_REQUEST_DD = 30008;
//需要处理全屏逻辑之类的操作,在子类重写beforeSetContentView方法做处理
@Override
protected void beforeSetContentView() {
super.beforeSetContentView();
setTranslucentStatus();
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
//需要在每个Activity处理逻辑,直接在onCreate方法处理
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
createFloatActionButtons();
ObServernotice.getInstance().addObserver(observer);
}
MyObserver observer = new MyObserver() {
@Override
public void update(int id, int intparameter, final String string, Bitmap bitmap) {
if (id==999){
if (intparameter==0){
saoli.setVisibility(View.GONE);
ewmli.setVisibility(View.GONE);
}else if (intparameter==1){
saoli.setVisibility(View.VISIBLE);
ewmli.setVisibility(View.VISIBLE);
mMQrCodeDialog = new QrCodeDialog(BaseActivity.this) {
@Override
public String setIvQrCode() {
return QrActivity.QR_TAG_ORDER + string;
}
};
imageView.setImageBitmap(bitmap);
}
}
}
};
private void createFloatActionButtons() {
View v = getWindow().getLayoutInflater().inflate(R.layout.layout_float_action_buttons, null);
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
layoutParams.gravity = Gravity.BOTTOM | Gravity.RIGHT;
addContentView(v, layoutParams);
saoli = findViewById(R.id.saoli);
ewmli = findViewById(R.id.ewmli);
imageView = findViewById(R.id.ddmaimg);
initShowfloat();
saoli.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
scan();
}
});
ewmli.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mMQrCodeDialog != null) {
mMQrCodeDialog.show();
}
}
});
}
public void initShowfloat(){
int ss = ShareUtil.getSharedInt("floatint");
if (ss==1){
saoli.setVisibility(View.VISIBLE);
ewmli.setVisibility(View.VISIBLE);
}else {
saoli.setVisibility(View.GONE);
ewmli.setVisibility(View.GONE);
}
final String ewmstring =ShareUtil.getSharedString("ewmss");
if (!TextUtils.isEmpty(ewmstring)){
Bitmap bitmap = QRCodeEncoder.syncEncodeQRCode(QrActivity.QR_TAG_ORDER+ewmstring,
BGAQRCodeUtil.dp2px(BaseActivity.this, ResUtil.getPx(R.dimen.normal_340dp)),
ContextCompat.getColor(BaseActivity.this, R.color.black), null);
mMQrCodeDialog = new QrCodeDialog(BaseActivity.this) {
@Override
public String setIvQrCode() {
return QrActivity.QR_TAG_ORDER + ewmstring;
}
};
imageView.setImageBitmap(bitmap);
}
}
private void scan() {
startActivity(QrActivity.newIntent(this, 0));
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
PermissionUtil.getInstance(getApplicationContext())
.onRequestPermissionsResult(requestCode, permissions, grantResults);
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
protected void onDestroy() {
super.onDestroy();
ObServernotice.getInstance().removeObserver(observer);
observer = null;
}
}
方法二:
machine_state_view文件
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content"> <FrameLayout android:background="@mipmap/ic_jxz" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="gone" android:layout_gravity="right|top" android:text="2" > </TextView> </FrameLayout> </RelativeLayout>
AbstractDragFloatActionButton文件
/** *meixi */ public abstract class AbstractDragFloatActionButton extends RelativeLayout { private int parentHeight;//悬浮的父布局高度 private int parentWidth; public AbstractDragFloatActionButton(Context context) { this(context, null, 0); } public AbstractDragFloatActionButton(Context context, AttributeSet attrs) { this(context, attrs, 0); } public abstract int getLayoutId(); public abstract void renderView(View view); public AbstractDragFloatActionButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); View view= LayoutInflater.from(context).inflate(getLayoutId(), this); renderView(view); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { measureChildren(widthMeasureSpec, heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onLayout(boolean b, int i, int i1, int i2, int i3) { View view = getChildAt(0); view.layout(0,0,view.getMeasuredWidth(),view.getMeasuredHeight()); } private int lastX; private int lastY; private boolean isDrag; @Override public boolean onTouchEvent(MotionEvent event) { int rawX = (int) event.getRawX(); int rawY = (int) event.getRawY(); switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: setPressed(true);//默认是点击事件 isDrag=false;//默认是非拖动而是点击事件 getParent().requestDisallowInterceptTouchEvent(true);//父布局不要拦截子布局的监听 lastX=rawX; lastY=rawY; ViewGroup parent; if(getParent()!=null){ parent= (ViewGroup) getParent(); parentHeight=parent.getHeight(); parentWidth=parent.getWidth(); } break; case MotionEvent.ACTION_MOVE: isDrag = (parentHeight > 0 && parentWidth > 0);//只有父布局存在你才可以拖动 if(!isDrag) break; int dx=rawX-lastX; int dy=rawY-lastY; //这里修复一些华为手机无法触发点击事件 int distance= (int) Math.sqrt(dx*dx+dy*dy); isDrag = distance>0;//只有位移大于0说明拖动了 if(!isDrag) break; float x=getX()+dx; float y=getY()+dy; //检测是否到达边缘 左上右下 x=x<0?0:x>parentWidth-getWidth()?parentWidth-getWidth():x; y=y<0?0:y>parentHeight-getHeight()?parentHeight-getHeight():y; setX(x); setY(y); lastX=rawX; lastY=rawY; break; case MotionEvent.ACTION_UP: //如果是拖动状态下即非点击按压事件 setPressed(!isDrag); break; } //如果不是拖拽,那么就不消费这个事件,以免影响点击事件的处理 //拖拽事件要自己消费 return isDrag || super.onTouchEvent(event); } }
MachineStateView文件:
public class MachineStateView extends AbstractDragFloatActionButton { public static final String TAG = MachineStateView.class.getSimpleName(); public MachineStateView(Context context) { super(context); } public MachineStateView(Context context, AttributeSet attrs) { super(context, attrs); } public MachineStateView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public int getLayoutId() { return R.layout.machine_state_view;//拿到你自己定义的悬浮布局 } @Override public void renderView(View view) { //初始化那些布局 Log.e(TAG,"MachineStateView" + view.getId()); } }
引用MachineStateView即可
实现demo:https://download.csdn.net/download/meixi_android/12568936
在线bug交流:扣1085220040