https://github.com/umano/AndroidSlidingUpPanel
패널을 위로 스와이프하는 경우 메인 영역 어둡게 처리하기
- ViewGroup의 child를 그릴때 drawChild가 호출되므로 여기에서 처리하도록 한다.
- slideable view가 있고 main view인 경우에 main view를 어둡게 처리한다.
- 그림을 그리는 영역을 canvas.getClipBounds로 얻어온다.
- 이 영역의 bottom을 slideable view의 top과 비교하여 작은 값으로 바꿔준다. -> slideable view는 어둡게 처리할 필요 없다.
- 지정된 fade color로부터 alpha를 얻어온 후 slide offset의 비율에 따라 어두운 정도를 계산한다.
- 계산된 alpha로 다시 color값을 만든 후 이 color를 canvas.drawRect에 지정한다.
Shadow를 slideable view 위에 표시하기
- draw를 override하여 구현한다.
- draw는 drawChild에 의해 호출된다.
- View 소스를 보면 drawing step에 대해 아래와 같은 설명이 있다.
- 1 Draw the background
- 2 If necessary, save the canvas' layers to prepare for fading
- 3 Draw view's content
- 4 Draw children
- 5 If necessary, draw the fading edges and restore layers
- 6 Draw decorations (scrollbars for instance)
- shadow drawable을 xml로 만든다: gradient
- draw(Canvas c)를 override 하여 여기서 shadow drawable을 지정한 위치에 그린다.
- slideable view의 top으로부터 shadow drawable을 놓을 위치(drawable의 top과 bottom)를 파악한다.
onSaveInstanceState
- slide state 정보를 저장하여 onRestoreInstanceState 호출 시 다시 저장할 수 있도록 한다.
class LayoutParams extends ViewGroup.MarginLayoutParams
- weight를 지정하여 percentage로 height를 정할 수 있도록 한다.
- ViewGroup의 generateLayoutParams이 호출될 때 이 LayoutParams를 생성하여 리턴하여 이 layout이 사용되도록 한다.
- checkLayoutParams가 false를 리턴하는 경우 generateLayoutParams이 호출된다.
- onLayout에서 margin이 크기 계산에 사용될 수 있도록하기 위해 사용된다.
class DragHelperCallback extends ViewDragHelper.Callback
- tryCaptureView
- dragging을 허용하는 slideable view를 리턴하도록 한다.
- getViewVerticalDragRange
- slide range를 리턴한다.
- onViewDragStateChanged
- drag state가 바뀌면 slide offset을 계산한 후 이 값에 따른 state를 저장한다.
- onViewPositionChanged
- slideable view의 위치에 따라 main view의 크기를 조절한다.
- 보통은 현재 상태 그대로 유지.
- collapsed 상태이고 overlay가 아닐 때 height를 match_parent로 변경한다.
- onViewReleased
- dragging하다가 손을 뗀 경우 호출된다.
- slideable view를 최종으로 위치시킬 top 위치를 계산한 후 settleCapturedViewAt를 사용하여 적용한다.
- clampViewPositionVertical
- collapsed와 expanded 사이로 해서 top의 위치를 리턴한다. 이 값으로 slideable view의 위치를 이동한다.
mFirstLayout
- layout을 다시 정하는 경우 사용된다.
- true로 설정
- anchor point를 새로 설정할 때
- onAttachedToWindow와 onDetachedFromWindow가 호출될 때
- onSizeChanged가 호출될 때 height가 변경되었을 때
- false로 설정
- onLayout이 끝난 경우
- onLayout
- slide offset 새로 계산
- slideable view의 경우 새로 계산된 slide offset 값에 따라 새로 위치가 계산되어야 함
setWillNotDraw(false)
- 직접 draw를 그린다는 것을 의미한다. onDraw가 호출되도록 한다.
onMeasure
- child로 두개만 가지는지를 확인한다. 첫번째가 main view이고 두번째가 slideable view이다.
- main view와 slideable view의 width와 height를 계산한다.
- main view
- overlay가 아닌 경우 height에서 panel의 height를 뺀다.
- slideable view
- slide range를 지정한다: height - panel height
onLayout
- slide state에 따라 slide offset(0 ~ 1)을 계산한다.
- slide offset에 따라 slideable view의 top을 계산한 후 이를 적용한다.
- parallax가 지정된 경우 main view의 위치를 ViewCompat.setTranslationY함수를 사용해서 slide offset의 비율만큼 옮겨준다.
computeScroll
- 스크롤시 호출되는 함수
- 보통 특별한 작업이 필요한 것이 아니면 여기서 사용되는 것과 같이 쓰면 된다: continueSettling와 ViewCompat.postInvalidateOnAnimation의 조합
requestLayout과 invalidate의 사용
- layout부터 다시 그려야 하는 경우는 requestLayout을 호출하고 view의 내용만 다시 그려야 하는 경우는 invalidate를 호출해준다.
터치 이벤트 처리
- 뷰의 터치 이벤트 관련 함수에서 ViewDragHelper의 관련 함수를 호출해준다.
- dispatchTouchEvent
- dragging중일때는 바로 onTouchEvent를 호출한다.
- onInterceptTouchEvent
- mDragHelper.shouldInterceptTouchEvent(ev)를 호출해준다.
- true를 리턴하면 자기 자신의 onTouchEvent를 호출하고 false를 리턴하면 자식의 onTouchEvent가 호출된다.
- 터치 포인트가 slideable view 영역 안이 아니면 mDragHelper.cancel()를 호출하고 false를 리턴한다.
- onTouchEvent
- mDragHelper.processTouchEvent(ev)를 호출해준다.
터치 영역이 특정 View에서 이루어진 것인지 확인하기
- 확인을 원하는 View의 getLocationOnScreen함수를 호출하여 스크린 기준 기준점의 위치를 알아낸다. -> viewLocation
- 자기 자신의 getLocationOnScreen함수를 호출하여 스크린 기준 기준점의 위치를 알아낸다. 여기에 터치 포인트를 더하여 스크린의 어디에서 터치가 일어났는지 알아낸다. -> screenX, screenY
- 앞에서 찾은 값의 비교로 터치 포인트가 View안에서 일어난 것인지 확인 가능
댓글 없음:
댓글 쓰기