일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- nginx
- StatelessWidget
- first_app
- 앱 기획
- 호주 이민
- StatefulWidget
- Android
- progress
- Engineer Australia
- reverse proxy
- 블러 효과
- flutter
- HTML 게임 엔진
- 회전판
- OpenGL
- flutter progress dialog
- game engine
- PowerMockup
- 맨붕
- quintus
- ABEEK
- 기술인증
- 플러터
- first flutter app
- c++
- rotate circle
- c
- ipad
- 공학인증
- BlurDrawable
- Today
- Total
우동우동우's note
안드로이드 간단한 BlurDrawable 구현 본문
안드로이드에는 Blur 기능이 없다. 이미지가 있으면 해당 이미지에 대한 Blur기능은 있다. 하지만 뒤에 나타난 뷰들을 Blur 할 수 있는 기능은 없다. iOS는 어떻게 Blur가 지원되는 지 모르겠으나. 안드로이드는 구조적으로 Blur기능 구현이 어렵다. 안드로이드에서 View를 나타내기 위해서 Canvas를 이용하여 그리도록 되어 있다. Canvas는 사용하는 방법에 따라 여러가지로 구현이 가능하다. Bitmap에 Canvas를 이용해서 그림을 그릴 수도 있다. 그런데 안드로이드 View에서 사용하는 Canvas가 지정한 대상에 접근이 불가능하다. 그려지는 대상이 Native에 대상이 있기 때문이다. 어쩌면 NDK를 활용하면 접근이 가능할 수도 있을 것 같다. 이 이상으로 알아보기 위해서는 Android OS소스 분석을 해야하기 때문에.. 여기 까지만 알아봤다.
그럼 안드로이드에서 Blur기능을 구현하기가 어렵다는 것 까지 알아보았다. 어렵다가 꼭 불가능하다는 뜻은 아니다. 어려워도 가능하다. 여러가지 방법이 있겠지만 나는 가장 간단한 방법을 선택했다. Blur의 배경이 될 뷰의 스크린 샷을 뜨고 원하는 부분의 이미지를 잘라서 Blur 효과를 추가해서 그려주면 된다. 간단하죠?
자 그럼 소스로 넘어가서 보겠습니다.
일단 BlurDrawable의 사용 방법은 최대한 간단하게 구현하려고 계획했습니다. 그래서 먼저 다음과 같이 코드를 짜고 작업을 시작했습니다.
------------
BlurDrawable bd = new BlurDrawable(); bd.setBGView(bv); bd.setView(v); v.setBackgroundDrawable(bd);
------------
BlurDrawable을 선언하고 배경이 되는 View와 대상이 되는 View를 넣어주구로 BackgroudDrawable로 넣어주면 끝이다. 사용방법은 간단하게 정리를 했습니다!
자 이제 다음으로 BlurDrawable이 어떻게 구현됐는지 살펴보겠습니다.
먼저 배경이 될 View와 Blur이미지를 나타낼 View를 만들겠습니다.
-----------
<? xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <RelativeLayout android:id="@+id/background" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:background="@drawable/hydrangeas" > </RelativeLayout> <LinearLayout android:id="@+id/imageContainer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:orientation="vertical" > <ImageView android:id="@+id/image" android:layout_width="100dp" android:layout_height="100dp" /> </LinearLayout> </RelativeLayout>
-----------
배경이 되는 View는 RelativeLayout으로 구현이 되어 있습니다. 그리고 Blur를 표시할 View는 ImageView로 구현이 되어 있습니다. 굳이 ImageView로 만들 필요는 없습니다. 여기서 주의할 점은 표시할 View가 배경이 될 View에 포함이 되면 안된다는 것입니다. 이유는 View가 Update되면 Blur가 된 곳에 또 Blur를 하게 되기 때문입니다.
다음으로 BlueDrawable을 어떻게 구현했는지 보여드리겠습니다. BlurDrawable은 다해서 100줄이 안돼서 그냥 코드 전체를 놓고 설명하겠습니다.
-------------
public class BlurDrawable extends Drawable { private View bgView; private View view; private int size = 6; private int squal = size*size; private int[] pixels = new int[squal]; Bitmap viewBitmap; @Override public void draw(Canvas canvas) { bgView.setDrawingCacheEnabled(true); Bitmap bm = bgView.getDrawingCache(); if(bm == null){ return; } if(viewBitmap == null){ viewBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Config.ARGB_8888); } Rect pRect = new Rect(); Rect cRect = new Rect(); bgView.getGlobalVisibleRect(pRect); view.getGlobalVisibleRect(cRect); int sumR = 0, sumG = 0, sumB = 0; int red = 0, green = 0, blue = 0; for(int i = cRect.left - pRect.left; i < cRect.right - pRect.left; i++){ for(int j = cRect.top - pRect.top; j < cRect.bottom - pRect.top; j++){ bm.getPixels(pixels , 0, size, i - size/2, j - size/2, size, size); for(int k = 0; k < squal; k++){ sumR += (pixels[k] >> 16) & 0xFF ; sumG += (pixels[k] >> 8) & 0xFF ; sumB += pixels[k] & 0xFF ; } red = (sumR / squal); green = (sumG / squal); blue = (sumB / squal); int pixel = 0xFF000000 + (red << 16) + (green << 8) + blue; viewBitmap.setPixel(i - (cRect.left - pRect.left), j - (cRect.top - pRect.top), pixel ); sumR = sumG = sumB = 0; red = green = blue = 0; } } canvas.drawBitmap(viewBitmap, null, getBounds(), null); } public View getView() { return view; } public void setView(View view) { this.view = view; } public View getParentView() { return bgView; } public void setBGView(View parentView) { this.bgView = parentView; } @Override public int getOpacity() { return 0; } @Override public void setAlpha(int alpha) { } @Override public void setColorFilter(ColorFilter cf) { } }
-------------
방법은 간단합니다. bgView에서 캡쳐화면을 가져옵니다. DrawingCashe를 가져오는 것입니다. setDrawingCacheEnabled()함수와 getDrawingCache()함수를 이용하면 간단하게 Bitmap 형태로 가져올 수 있습니다.
다음으로 Bitmap 이미지를 하나 만듭니다. 이 이미지는 Blur를 나타낼 View의 사이즈에 맞춰서 만들도록 되어 있습니다.
각 뷰의 위치와 사이즈를 나타내는 Rect를 가져옵니다. getGlobalVisibleRect() 함수를 활용하면 쉽게 가져올 수 있습니다. BG View와 Blur View의 상대 위치를 파악해서 해당 부분에서 사용될 이미지를 추출하기 위해서입니다.
다음으로 for루프 안에 있는 내용은 Blur 로직을 간단하게 구현한 것입니다. Blur로직은 원하시는 로직으로 바꾸셔도 무방합니다.
마지막으로 bitmap을 그리면 됩니다.
간단하죠?
발전을 더욱 시키면 좋겠지만.. 재미삼아 만든 것이라.. 여기까지만 하겠습니다.
소스입니다. 참고하세요.
'Java & Android' 카테고리의 다른 글
[Android] Volley 예제 만들어 보기 (0) | 2016.06.15 |
---|---|
[Android] Volley 시작해보기 (0) | 2016.06.14 |
Eclipse에 ADT Plugin 설치 (0) | 2016.06.10 |
NumberPicker 포커스 해제하기 (0) | 2016.05.06 |
[Android] 다른 어플리케이션 실행방법 (0) | 2013.11.25 |