티스토리 뷰

728x90

 아래 예제는 Android studio 1.2를 기반으로 작성한 코드입니다.


 안드로이드 WindowManagert의 OnTouch event 처리 방법을 소개합니다. WindowManager은 Activity를 벗어나서 처리하는 부분으로 앱을 벗어나서 자유롭게 사용할 수 있는 Layout 입니다. 이 레이아웃을 사용한 앱으로는 페이스북의 Message 앱이 가장 유명하며, 구현이 가장 잘 되어 있습니다. 우선 최종적으로 2개의 예제를 작성하였습니다.


 이번 글은 가장 기본적인 좌표 이동 방법을 소개하고 다음 글에서는 좀 더 Smooth한 이동을 위한 에니메이션 처리 방법을 살펴보겠습니다.



목차

 - WindowManager의 OnTouch Event 처리하기

 - WindowManager의 Animation을 이용한 Smooth한 OnTouch Event 처리



예제 영상

 아래 영상은 기본적인 OnTouch 이벤트 처리한 예제입니다. Smooth 보다는 자연스럽게 따라오지는 않지만 아래의 화면만 가지고는 확인할 수는 없습니다.
다음글에서 2개를 함께 놓고 비교해보도록 하겠습니다.


사용한 API

 - WindowManagerhttp://developer.android.com/reference/android/view/WindowManager.html



예제코드 - windowManager init.

 WindowManager를 이용하여 아래와 같이 Layout을 초기화 합니다. WindowManager는 Context.getSystemService(Context.WINDOW_SERVICE)을 이용하여 초기화 후 사용합니다.

 windowManager에 addView를 하기위해서는 Layout과 LayoutParams를 각각 초기화 하고, addView를 진행합니다.


 LayoutParams에는 width, heigh를 지정하고, x, y 좌표와 Type, flag, format을 각각 지정합니다.

  - type 지정자는 아래와 같습니다.

  Type은 해당 레이아웃이 어느 위치에 보여질지를 지정하는 것입니다. Notification 위에 올릴것인지 Notification 아래에 올릴것인지 등 아래와 같은 설정값을 가집니다. 자세한 내용은 API 문서를 참고하시면 됩니다.


  - flag 지정자는 아래와 같습니다.

 flag는 해당 버튼을 누를 수 있는 버튼으로 만들것인지, 그냥 단순히 보여주는 형태로 제공될것인지 등에 대하여 설정할 수 있습니다.


 - gravity는 왼쪽 상단을 0, 0의 위치로 설정하였습니다. 

   예를 들어 TOP, CENTER_HORIZONTAL를 기준으로 하게된다면 상단 가운데 부분이 0, 0이 되며 가운데 이전은 - 값을 가지게 됩니다.

    /**
     * Window View 를 초기화 한다. X, Y 좌표는 0, 0으로 지정한다.
     */
    private void initWindowLayout() {
        windowView = (LinearLayout) layoutInflater.inflate(R.layout.window_layout, null);
        windowViewLayoutParams = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT,
                0, 0, // X, Y 좌표
                WindowManager.LayoutParams.TYPE_TOAST,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
                PixelFormat.TRANSLUCENT);
        windowViewLayoutParams.gravity = Gravity.TOP | Gravity.LEFT;
        windowManager.addView(windowView, windowViewLayoutParams);
        windowView.setOnTouchListener(this);
    }


예제 코드 - onTouch 부분

    private float prevX;
    private float prevY;
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: // 처음 위치를 기억해둔다.
                prevX = event.getRawX();
                prevY = event.getRawY();
                break;

            case MotionEvent.ACTION_MOVE:
                float rawX = event.getRawX(); // 절대 X 좌표 값을 가져온다.
                float rawY = event.getRawY(); // 절대 Y 좌표값을 가져온다.

                // 이동한 위치에서 처음 위치를 빼서 이동한 거리를 구한다.
                float x = rawX - prevX;
                float y = rawY - prevY;

                setCoordinateUpdate(x, y);

                prevX = rawX;
                prevY = rawY;
                break;
        }
        return false;
    }

   /**
     * 이동한 거리를 x, y를 넘겨 LayoutParams에 갱신한다.
     * @param x
     * @param y
     */
    private void setCoordinateUpdate(float x, float y) {
        if (windowViewLayoutParams != null) {
            windowViewLayoutParams.x += (int) x;
            windowViewLayoutParams.y += (int) y;

            windowManager.updateViewLayout(windowView, windowViewLayoutParams);
        }
    }


마무리

 위와 같은 간단한 코드를 통해 WindowManager의 ViewLayout을 이동할 수 있습니다. 다음 글에서는 여기에 Animation을 추가하여 좀 더 Smooth한 이동이 가능한 Window Layout을 구현해보도록 하겠습니다.




댓글