我正在尝试学习如何创建一个类似于Android中Facebook聊天头信使图标的覆盖窗口。
我设法创建了以下类,它使我能够创建类似于 fb 聊天头的覆盖窗口视图。 但是,我在使用可点击侦听器和可触摸侦听器时遇到困难。如果我使用可点击侦听器,可触摸侦听器不起作用,反之亦然。
我希望覆盖窗口视图是可单击的,以便在我点击它时恢复应用程序,并且可以触摸以将图标移动到屏幕上的任何位置。
法典:
public class FloatingViewService extends Service {
private WindowManager mWindowManager;
private View mFloatingView;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate: Floating Service is create");
//the xml file
//Inflate the floating view layout we created
mFloatingView = LayoutInflater.from(this).inflate(R.layout.layout_floating_widget, null);
//Add the view to the window.
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
LAYOUT_FLAG,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
//Specify the view position
params.gravity = Gravity.TOP | Gravity.LEFT; //Initially view will be added to top-left corner
params.x = 0;
params.y = 100;
//Add the view to the window
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
mWindowManager.addView(mFloatingView, params);
//The root element of the iconView view layout
final View iconView = mFloatingView.findViewById(R.id.icon_view);
//the icon view inside the xml file
//Open the application on the tap click
iconView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Open the application with click.
Intent intent = new Intent(FloatingViewService.this, MyActivity.class);
startActivity(intent);
//close the service and remove view from the view hierarchy
stopSelf();
}
});
//Drag and move floating view using user's touch action.
mFloatingView.findViewById(R.id.root_container).setOnTouchListener(new View.OnTouchListener() {
private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//remember the initial position.
initialX = params.x;
initialY = params.y;
//get the touch location
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
return true;
case MotionEvent.ACTION_UP:
return true;
case MotionEvent.ACTION_MOVE:
//Calculate the X and Y coordinates of the view.
params.x = initialX + (int) (event.getRawX() - initialTouchX);
params.y = initialY + (int) (event.getRawY() - initialTouchY);
//Update the layout with new X & Y coordinate
mWindowManager.updateViewLayout(mFloatingView, params);
return true;
}
return false;
}
});
}
@Override
public void onDestroy() {
super.onDestroy();
if (mFloatingView != null) mWindowManager.removeView(mFloatingView);
}
}
您可以在触发
ACTION_DOWN事件时记录当前时间,因此您可以执行所需的操作,例如在ACTION_UP事件中处理 onclick。
public class FloatingViewService extends Service {
private WindowManager mWindowManager;
private View mFloatingView;
private long interval = 0;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate: Floating Service is create");
//the xml file
//Inflate the floating view layout we created
mFloatingView = LayoutInflater.from(this).inflate(R.layout.layout_floating_widget, null);
//Add the view to the window.
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
LAYOUT_FLAG,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
//Specify the view position
params.gravity = Gravity.TOP | Gravity.LEFT; //Initially view will be added to top-left corner
params.x = 0;
params.y = 100;
//Add the view to the window
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
mWindowManager.addView(mFloatingView, params);
//The root element of the iconView view layout
final View iconView = mFloatingView.findViewById(R.id.icon_view);
//the icon view inside the xml file
//Open the application on the tap click
iconView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Open the application with click.
Intent intent = new Intent(FloatingViewService.this, MyActivity.class);
startActivity(intent);
//close the service and remove view from the view hierarchy
stopSelf();
}
});
//Drag and move floating view using user's touch action.
mFloatingView.findViewById(R.id.root_container).setOnTouchListener(new View.OnTouchListener() {
private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
interval = System.currentTimeMillis();
//remember the initial position.
initialX = params.x;
initialY = params.y;
//get the touch location
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
return true;
case MotionEvent.ACTION_UP:
if ((System.currentTimeMillis() - interval) < 300) {
// if time is less than 300 ms it means the user has clicked your view.
// handle your click here
} else {
//Calculate the X and Y coordinates of the view and update view
params.x = initialX + (int) (event.getRawX() - initialTouchX);
params.y = initialY + (int) (event.getRawY() - initialTouchY);
//Update the layout with new X & Y coordinate
mWindowManager.updateViewLayout(mFloatingView, params);
}
return true;
case MotionEvent.ACTION_MOVE:
//Calculate the X and Y coordinates of the view.
params.x = initialX + (int) (event.getRawX() - initialTouchX);
params.y = initialY + (int) (event.getRawY() - initialTouchY);
//Update the layout with new X & Y coordinate
mWindowManager.updateViewLayout(mFloatingView, params);
return true;
}
return false;
}
});
}
@Override
public void onDestroy() {
super.onDestroy();
if (mFloatingView != null) mWindowManager.removeView(mFloatingView);
}
}