출처
: http://devlsh.tistory.com/entry/OpenGL-Surfaceview-에서-Navigation-Drawer-Sliding-Menu-구현시-주의사항
: https://stackoverflow.com/a/22402713
예전에 개발하면서 문제 됬던 내용 정리 하는 차원에서 작성한다.
1. 재현현상
OpenGL, Surfaceview 위에 Navigation Drawer 구현시 Drag 속도가 현저히 떨어지거나 Drag 중에 검은색 화면으로 잔상이 생기는 문제가 발생된다.
2. 수정방법
내가 작업한 앱의 최소 서비스 지원 OS 버전이 Android 2.2 부터 였다. -_-; 그렇다.. Navigation Drawer API를 사용못한다 ..
그래서 android-support-v4 에서 지원하는 Navigation Drawer 지원하나 찾아봣다.. 안된다 -_-;
어쩔수 없이 Navigation Drawer, View Pager Open Souce를 분석하여 비슷한 동작이 되게 구현을 하였고,
Fragment 를 이용하여 View가 독립적으로 Life Cycle 이루어지게 구현하였다.
근데 위에 재현현상과 같은 문제점이 발견되었다.. 그래서 차근차근 삽질했다..
일단 Drag 속도를 최적화 하기위해 찾던중 Android 3.0 이상부터 하드웨어 가속 처리를 이용해서 어느 정도 해결하였고
그 다음.. 잔상이 나오는 문제는 하드웨어 가속처리를 해도 계속 발생하였다. 그래서 또 고민했다..
그러다가 Canvas API 중에 clipRect 이용하여 해결 하였다.
방법은 아래 그림과 같이 하여 메뉴 영역과 메뉴 영역이 아닌 부분을 clipRect API로 분리하여서로 화면 갱신이 영향을 안받게 처리 하였다.
소스 구현 내용중에 위에 해당되는 부분이다.
001 | public class FadeLayout extends ViewGroup { |
005 | private final static boolean HARDWARE_FADE_LAYOUT = false ; |
007 | public FadeLayout(Context context) { |
011 | private CustomViewAbove mAbove; |
013 | private View mContent; |
015 | private CustomViewBehind mBehind; |
017 | private SlidingMenu mSlidingMenu; |
019 | public void setBehind(CustomViewBehind mBehind) { |
020 | this .mBehind = mBehind; |
023 | public void setRootView(SlidingMenu slidingMenu) { |
024 | this .mSlidingMenu = slidingMenu; |
027 | public void setContent(View content) { |
028 | this .mContent = content; |
031 | public void setAbove(CustomViewAbove mAbove) { |
032 | this .mAbove = mAbove; |
040 | public boolean isHardwareaccelerated() { |
041 | return HARDWARE_FADE_LAYOUT; |
045 | protected void onLayout( boolean changed, int l, int t, int r, int b) { |
049 | public void draw(Canvas canvas) { |
054 | protected void dispatchDraw(Canvas canvas) { |
055 | super .dispatchDraw(canvas); |
056 | if (!HARDWARE_FADE_LAYOUT && isRefresh()) { |
058 | drawFadeContent(canvas); |
063 | * 지도화면 영역 페이드 처리 메뉴 영역이 아닌 부분 |
067 | private void drawFadeContent(Canvas canvas) { |
069 | if (mSlidingMenu.isFadeEnabled()) { |
070 | final int color = Color.argb(mAbove.getFadeAlpha(), 0 , 0 , 0 ); |
071 | final int right = mAbove.getRight() - mAbove.getCustomScrollX(); |
073 | canvas.clipRect( 0 , 0 , mAbove.getRight(), mAbove.getBottom() - mBehind.getSelectViewHeight(), Op.DIFFERENCE); |
074 | canvas.drawColor(color); |
078 | canvas.clipRect( 0 , mAbove.getBottom() - mBehind.getSelectViewHeight(), right, mAbove.getBottom(), Op.DIFFERENCE); |
079 | canvas.drawColor(color); |
085 | * OPENGL 부분 갱신을 위해 지도영역만 갱신한다. |
089 | private void drawClipMap(Canvas canvas) { |
091 | canvas.clipRect( 0 , 0 , mAbove.getRight() - mAbove.getCustomScrollX(), mAbove.getBottom()); |
092 | mContent.draw(canvas); |
096 | private boolean isRefresh() { |
097 | if (mContent != null && mAbove != null && mBehind != null && mSlidingMenu != null ) { |
위에 방식처럼 번거럽게 처리하기 싫으면 어플 자체에 하드웨어 가속처리를 넣어주면 된다 ^^
근데 그렇게 되면 겹쳐서 배치된 UI Eevent 처리가 문제될 수가 있다.
Have you tried using implementing onDrawerSlide on the drawerListener of the drawerLayour
like this
@Override
public void onDrawerSlide(View drawerView, float slideOffset)
{
super.onDrawerSlide(drawerView, slideOffset);
mDrawerLayout.bringChildToFront(drawerView);
mDrawerLayout.requestLayout();
}