지난번에 자바로 android Floating Widget을 구현해보았다.
그런데 위젯을 움직인 후, 그 자리가 아닌 양 사이드로 보내고 싶어 다시 한번 공부한 후 구현해보았다.
WidgetService 코드만 바꿔주면 구현할 수 있었다.
import android.app.Service;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.os.Build;
import android.os.CountDownTimer;
import android.os.IBinder;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.Nullable;
import java.util.Calendar;
public class WidgetService extends Service {
int LAYOUT_FLAG;
View mFloatingView;
WindowManager windowManager;
ImageView imageClose;
TextView tvWidth;
float height, width;
// 플로팅 위젯 뷰가 왼쪽에 있는지 오른쪽에 있는지 확인하는 변수
// 처음에는 플로팅 위젯 뷰를 오른쪽에 표시하므로 false로 설정
private boolean isLeft = false;
@Nullable
@Override
public IBinder onBind(Intent intent){
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
}else{
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
}
// 우리가 만든 플로팅 뷰 레이아웃 확장
mFloatingView = LayoutInflater.from(this).inflate(R.layout.layout_widget, null);
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
LAYOUT_FLAG,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
// 보기 위치 지정
// 처음에는보기가 오른쪽 상단 모서리에 추가되며 필요에 따라 x-y 좌표를 변경
layoutParams.gravity = Gravity.TOP|Gravity.RIGHT;
layoutParams.x = 0;
layoutParams.y = 100;
WindowManager.LayoutParams imageParams = new WindowManager.LayoutParams( 140,
140,
LAYOUT_FLAG,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
imageParams.gravity = Gravity.BOTTOM|Gravity.CENTER;
imageParams.y = 100;
windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
imageClose = new ImageView(this);
imageClose.setImageResource(R.drawable.close);
imageClose.setVisibility(View.INVISIBLE);
windowManager.addView(imageClose, imageParams);
windowManager.addView(mFloatingView, layoutParams);
mFloatingView.setVisibility(View.VISIBLE);
height = windowManager.getDefaultDisplay().getHeight();
width = windowManager.getDefaultDisplay().getWidth();
tvWidth = (TextView) mFloatingView.findViewById(R.id.imageView);
// 사용자의 터치 동작을 사용하여 플로팅 뷰를 드래그하여 이동
tvWidth.setOnTouchListener(new View.OnTouchListener() {
int initialx, initialy;
float initialTouchX, initialTouchY;
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()){
case MotionEvent.ACTION_DOWN:
imageClose.setVisibility(View.VISIBLE);
//터치 위치 좌표 얻기
initialTouchX = motionEvent.getRawX();
initialTouchY = motionEvent.getRawY();
// 초기 위치 기억
initialx = layoutParams.x;
initialy = layoutParams.y;
return true;
case MotionEvent.ACTION_UP:
imageClose.setVisibility(view.GONE);
// 초기 좌표와 현재 좌표의 차이 가져 오기
layoutParams.x = initialx+(int) (initialTouchX-motionEvent.getRawX());
layoutParams.y = initialy+(int)(motionEvent.getRawY()-initialTouchY);
// 제거 이미지 주변 거리
if (layoutParams.y>(height * 0.6 )) {
stopSelf();
}
else {
//사용자가 플로팅 뷰를 드래그하면 위치 재설정
if ( layoutParams.x <= 500) {
isLeft = false;
layoutParams.x = 0;
windowManager.updateViewLayout(mFloatingView, layoutParams);
}
else {
isLeft = true;
layoutParams.x = 1000;
windowManager.updateViewLayout(mFloatingView, layoutParams);
}
}
return true;
case MotionEvent.ACTION_MOVE:
// 초기 좌표와 현재 좌표의 차이 가져 오기
layoutParams.x = initialx+(int)(initialTouchX-motionEvent.getRawX());
layoutParams.y = initialy +(int) (motionEvent.getRawY()- initialTouchY);
// 새로운 X 및 Y 좌표로 레이아웃 업데이트
windowManager.updateViewLayout(mFloatingView, layoutParams);
if (layoutParams.y> (height * 0.6)){
imageClose.setImageResource(R.drawable.close);
}
else {
imageClose.setImageResource(R.drawable.close);
}
return true;
}
return false;
}
});
return START_STICKY;
}
// 앱이 종료될때 실행
@Override
public void onDestroy(){
super.onDestroy();
if(mFloatingView != null){
windowManager.removeView(mFloatingView);
}
if (imageClose != null){
windowManager.removeView(imageClose);
}
}
}
바뀐 코드만을 보면 다음과 같다.
private boolean isLeft = false;
// 제거 이미지 주변 거리
if (layoutParams.y>(height * 0.6 )) {
stopSelf();
}
else {
//사용자가 플로팅 뷰를 드래그하면 위치 재설정
if ( layoutParams.x <= 500) {
isLeft = false;
layoutParams.x = 0;
windowManager.updateViewLayout(mFloatingView, layoutParams);
}
else {
isLeft = true;
layoutParams.x = 1000;
windowManager.updateViewLayout(mFloatingView, layoutParams);
}
}
뷰 위치에서 가운데를 기준으로 왼쪽에 위젯이 위치하면 왼쪽으로 보내고 오른쪽에 위치해 있으면 오른쪽으로 보내도록 했다. 그런데 위젯이 양 사이드로 움직일 때 너무 빠른 속도로 움직이는 것 같아 조금 느리게 움직이게 할 수 있는지 더 알아봐야 할 것 같다.
코드를 수정했다면 run을 눌러 잘 실행되는지 확인해본다.
위 코드를 실행하게 되면 다음 출력 화면과 같은 결과를 얻을 수 있다.
참고
'Develop > Java' 카테고리의 다른 글
[AWS] 아마존 웹 서비스 Android + Amazon Cognito 로그인 구현 (0) | 2021.07.15 |
---|---|
[AWS] 아마존 웹 서비스 Android + Amazon Cognito 구현 (0) | 2021.07.14 |
[AWS] 아마존 웹 서비스 Amplify + Android 프로젝트 연동 (0) | 2021.07.12 |
[Java] 자바 android Floating Widget 구현(3) (1) | 2021.07.12 |
[Java] 자바 android Floating Widget 구현(1) (0) | 2021.07.07 |