[안드로이드] 커스텀 컴포넌트 만들기
- 프로그래밍 정보
- 2010. 9. 22.
반응형
읽기전에 손가락 한번 클릭~ >_<
고마워요 ~ Chu ~ ♥
안드로이드의 커스텀 컴포넌트에 관한 글입니다.
커스텀 확장 뷰 생성하기
안드로이드의 기초 레이아웃인 뷰와 뷰그룹에서는 컴포넌트화 된 모델을 제공해 줍니다. UI 를 디자인하는데 필요한 미리 정의된 뷰와 뷰 그룹의 하위 클래스 ( 위젯과 레이아웃 ) 를 가지고 있습니다.
이런것들 중에서 새로운 것을 만들기 위해 자신만의 뷰 클래스를 만들수도 있고, 기존의 위젯-레이아웃을 조금만 수정하고 싶다면 상속받은 뒤 메소드를 오버라이드 하는 방식을 사용합니다.
순서
1. 사용할 클래스에서 기존의 뷰 또는 뷰 하위클래스를 상속 받습니다.
2. 슈퍼클래스의 메소드를 오버라이드 합니다. ( 오버라이드할 슈퍼클래스의 메소드들은 on....() 으로 시작됩니다. )
3. 새로운 클래스를 기존의 뷰클래스를 대신하여 사용합니다.
[ 상속받은 클래스는 액티비티 내부에서 이너클래스(Inner Class) 로 정의할 수 있는데요, 이것은 그 액티비티 내부에서만 쓰일 수 있으므로, 어플리케이션 내에서 더 넓게 사용할 수 있는 public 뷰를 만드는것이 더 유리합니다 ]
2. 슈퍼클래스의 메소드를 오버라이드 합니다. ( 오버라이드할 슈퍼클래스의 메소드들은 on....() 으로 시작됩니다. )
3. 새로운 클래스를 기존의 뷰클래스를 대신하여 사용합니다.
[ 상속받은 클래스는 액티비티 내부에서 이너클래스(Inner Class) 로 정의할 수 있는데요, 이것은 그 액티비티 내부에서만 쓰일 수 있으므로, 어플리케이션 내에서 더 넓게 사용할 수 있는 public 뷰를 만드는것이 더 유리합니다 ]
완전한 커스텀 컴포넌트
완전한 커스텀 컴포넌트란, 만들고자 하는 어떠한 디자인으로도 컴포넌트를 만들 수 있다는 것을 의미합니다. 예를들어, " A " 라는 디자인을 하고싶은데, 이것이 내장된 컴포넌트를 어떻게 조합하더라도 만들 수 없는 경우가 있을 수도 있습니다.
즉, 원하는 방식으로 보여지고 동작하는 컴포넌트를 만들 수 있다는 얘기인데, 구글에서는 상상력과 스크린의 크기, 사용가능한 프로세스 파워만이 제약조건이 될 수 있다고 말하고 있네요 ㅎㅎ 재미있군요 ㅎ
커스텀 컴포넌트의 생성하는 순서
1. 뷰 ( View ) 클래스를 상속합니다.
2. XML 내에 속성과 파라미터를 가지는 생성자를 만들수 있고, 그것을 사용할 수 있습니다.
3. 이벤트 리스너, 속성, 접근자 및 수정자 등을 추가하여 동작을 결정합니다.
4. onMeasure() 메소드와 onDraw() 메소드를 오버라이드하여 구현을 해야합니다. 이때 둘다 디폴트 동작구조는 onDraw() 는 아무런 일도 하지않고, onMeasure() 는 100X100 의 크기로 설정되기 때문에 알맞게 수정해야 합니다.
5. 추가적으로 필요한 메소드들을 추가합니다.
2. XML 내에 속성과 파라미터를 가지는 생성자를 만들수 있고, 그것을 사용할 수 있습니다.
3. 이벤트 리스너, 속성, 접근자 및 수정자 등을 추가하여 동작을 결정합니다.
4. onMeasure() 메소드와 onDraw() 메소드를 오버라이드하여 구현을 해야합니다. 이때 둘다 디폴트 동작구조는 onDraw() 는 아무런 일도 하지않고, onMeasure() 는 100X100 의 크기로 설정되기 때문에 알맞게 수정해야 합니다.
5. 추가적으로 필요한 메소드들을 추가합니다.
onDraw() 와 onMeasure() 구현하기
onDraw() 는 캔버스(Canvas) 를 파라미터로 전달하며, 그 캔버스위에 원하는 것. 즉, 2D 그래픽이나 기타 다른것들을 구현합니다
이것은 3D 그래픽에는 적용되지 않는데, 3D 그래픽을 쓰려면 서피스뷰(SurfaceView) 를 상속해야 하며, 별도의 스레드에서 그리기를 해야되기 때문입니다.
onMeasure() 는 정확한 값을 가지고 오버라이드 해야되는데요, 부모(parent) 의 요구조건과 측정된 너비와 높이를 가지고 setMeasuredDimension() 메소드를 호출해야만 합니다. 만약 이 메소드를 호출하지 않으면 측정 시점에서 예외가 발생합니다.
onMeasure() 메소드 구현 순서
1. onMeasure() 메소드에 너비와 높이를 파라미터로 전달합니다. ( widthMeasureSpec, heightMeasureSpec 은 정수형 값 입니다. )
2. onMeasure() 메소드에서 요구하는 너비와 높이를 계산합니다. 즉, 요구하는 값이 부모의 값보다 크다면 부모는 잘라내기, 스크롤, 예외발생, 재시도( onMeasure() 다시호출) 등을 선택할 것입니다.
3. 계산되어진 너비와 높이를 가지고 setMeasuredDimension(int width, int height) 를 호출합니다. 위에서 언급했지만 호출하지 않으면 예외가 발생합니다.
2. onMeasure() 메소드에서 요구하는 너비와 높이를 계산합니다. 즉, 요구하는 값이 부모의 값보다 크다면 부모는 잘라내기, 스크롤, 예외발생, 재시도( onMeasure() 다시호출) 등을 선택할 것입니다.
3. 계산되어진 너비와 높이를 가지고 setMeasuredDimension(int width, int height) 를 호출합니다. 위에서 언급했지만 호출하지 않으면 예외가 발생합니다.
▶ 그 밖의 뷰에서 프레임워크가 호출하는 다른 메소드들..
⊙ 생성자 : 소스코드에서 뷰가 생성될 때 호출되는 형태와, 레이아웃 파일에서 뷰가 전개(inflate) 될 때 호출되는 형태 두가지가 있습니다. 두번째 형태는 레이아웃에 정의된 속성을 분석한 후 적용합니다.
⊙ onFinishInflate() : 뷰와 그 하위 자식들이 XML 에서 전개 된 후 호출됩니다.
⊙ onMeasure(int, int) : 뷰와 그 자식들에 대한 크기를 결정하기 위해 호출됩니다.
⊙ onLayout(boolean, int, int, int, int) : 뷰가 그 자식들에게 크기와 위치를 할당할 때 호출됩니다.
⊙ onSizeChanged(int, int, int, int) : 뷰의 크기가 바뀔 때 호출됩니다.
⊙ onDraw(Canvas) : 뷰가 컨텐츠를 그릴 때 호출되지요
⊙ onKeyDown(int, KeyEvent) : 새로운 키 이벤트 발생시 호출됩니다.
⊙ onKeyUp(int, KeyEvent) : 키 업 이벤트 발생시에 호출됩니다.
⊙ onTrackballEvent(MotionEvent) : 트랙볼 모션 이벤트 발생시에 호출됩니다.
⊙ onTouchEvnet(MotionEvent) : 터치스크린의 모션 이벤트 발생시에 호출됩니다.
⊙ onFocusChanged(boolean, int, Rect) : 뷰가 포커스를 가지거나 잃을 때 호출됩니다.
⊙ onWindowFocusChanged(boolean) : 뷰를 포함한 윈도우가 포커스를 가지거나 잃을 때 호출됩니다.
⊙ onAttachedToWindow() : 뷰가 윈도우에 포함될 때 호출됩니다.
⊙ onDetachedFromWindow() : 뷰가 윈도우에서 분리될 때 호출됩니다.
⊙ onWindowVisibillityChanged(int) : 뷰를 포함한 윈도우가 보여지는 상태가 변할 때 호출됩니다.
⊙ onFinishInflate() : 뷰와 그 하위 자식들이 XML 에서 전개 된 후 호출됩니다.
⊙ onMeasure(int, int) : 뷰와 그 자식들에 대한 크기를 결정하기 위해 호출됩니다.
⊙ onLayout(boolean, int, int, int, int) : 뷰가 그 자식들에게 크기와 위치를 할당할 때 호출됩니다.
⊙ onSizeChanged(int, int, int, int) : 뷰의 크기가 바뀔 때 호출됩니다.
⊙ onDraw(Canvas) : 뷰가 컨텐츠를 그릴 때 호출되지요
⊙ onKeyDown(int, KeyEvent) : 새로운 키 이벤트 발생시 호출됩니다.
⊙ onKeyUp(int, KeyEvent) : 키 업 이벤트 발생시에 호출됩니다.
⊙ onTrackballEvent(MotionEvent) : 트랙볼 모션 이벤트 발생시에 호출됩니다.
⊙ onTouchEvnet(MotionEvent) : 터치스크린의 모션 이벤트 발생시에 호출됩니다.
⊙ onFocusChanged(boolean, int, Rect) : 뷰가 포커스를 가지거나 잃을 때 호출됩니다.
⊙ onWindowFocusChanged(boolean) : 뷰를 포함한 윈도우가 포커스를 가지거나 잃을 때 호출됩니다.
⊙ onAttachedToWindow() : 뷰가 윈도우에 포함될 때 호출됩니다.
⊙ onDetachedFromWindow() : 뷰가 윈도우에서 분리될 때 호출됩니다.
⊙ onWindowVisibillityChanged(int) : 뷰를 포함한 윈도우가 보여지는 상태가 변할 때 호출됩니다.
커스텀 뷰 예제
커스텀 뷰 예제는 안드로이드에서 제공하는 샘플들 중에서 API Demos 의 CustomView 예제가 있는데, 이 예제의 컴스텀 뷰는 LabelView 클래스에서 정의되어 있습니다.
LabelView 샘플은 커스텀 컴포넌트를 이해하기에 아주 적합합니다.
뜯어보자면...
1. 완전한 커스텀 컴포넌트를 위해 뷰 클래스를 상속 받았습니다.
2. 생성자는 inflation 파라미터를 가지고 있습니다 ( XML 에서 정의됨 )
또한 LabelView 를 위해 정의된 속성들을 가지고 있지요.
3. 라벨에 표시할 public 메소드를 사용하고 있습니다
( setText(), setTextColor() 등 )
4. 그리기를 수행할 때 필요한 크기를 설정하기 위하여 onMeasure() 메소드가 있습니다.
이 예제의 실제 작업처리는 private measureWidth() 메소드에서 수행하도록 되어 있네요
5. 캔버스에 라벨을 그리기 위해 onDraw() 메소드를 오버라이드 했습니다. 추가로 custom_view_1.xml 에 보면 android: 네임스페이스 와 app: 네임스페이스가 있는데요, app: 네임스페이스는 LabelView 가 작업하는 커스텀 파라미터이며, R 클래스의 styleable 내부클래스에서 정의됩니다.
합성 ( Compound ) 컴포넌트
완전한 커스텀 컴포넌트를 만들기 보다는, 기존의 컨트롤들을 조합하여 구성하는 컴포넌트를 만들려면 합성 컴포넌트를 사용하면 됩니다.
이것은 하나로 취급될 수 있는 아이템들을 그룹안에서 합쳐놓는 방식이며, 안드로이드에는 이런것을 위해 제공되는 두 개의 뷰가 존재합니다.
바로 Spinner 와 AutoCompleteTextView 가 그것이지요.
합성 컴포넌트 만들기
1. 일반적인 시작점은 레이아웃이 됩니다. 따라서 하나의 레이아웃을 확장하는 클래스를 만들고, 컴포넌트가 구조화 될 수 있도록 다른 레이아웃을 포함합니다. 컴포넌트에 포함된 레이아웃은 XML 에서 선언하거나 소스코드에서 추가할 수 있습니다.
2. 새로운 클래스의 생성자에서 슈퍼클래스의 생성자를 먼저 호출해 줍니다. 그 다음에 새로운 컴포넌트 안에서 다른 뷰를 구성합니다. 이것 또한 XML 로 선언할 수 있으며, 속성과 파라미터를 만들어 사용할 수도 있습니다.
3. 알맞은 이벤트 리스너를 구현해 줍니다.
4. 레이아웃을 상속하는 경우에는 onDraw() 나 onMeasure() 메소드를 오버라이드 하지 않아도 됩니다. 왜냐하면 레이아웃은 디폴트 동작 구조가 있기 때문입니다. 만약 필요하다면 오버라이드 해도 무방합니다.
5. onKeyDown() 메소드 같은 다른 on....() 메소드를 오버라이드 할 수 있습니다.
2. 새로운 클래스의 생성자에서 슈퍼클래스의 생성자를 먼저 호출해 줍니다. 그 다음에 새로운 컴포넌트 안에서 다른 뷰를 구성합니다. 이것 또한 XML 로 선언할 수 있으며, 속성과 파라미터를 만들어 사용할 수도 있습니다.
3. 알맞은 이벤트 리스너를 구현해 줍니다.
4. 레이아웃을 상속하는 경우에는 onDraw() 나 onMeasure() 메소드를 오버라이드 하지 않아도 됩니다. 왜냐하면 레이아웃은 디폴트 동작 구조가 있기 때문입니다. 만약 필요하다면 오버라이드 해도 무방합니다.
5. onKeyDown() 메소드 같은 다른 on....() 메소드를 오버라이드 할 수 있습니다.
▶ 커스텀 컴포넌트를 레이아웃으로 사용하면서의 장점은 무엇일까요?
1. XML 로 레이아웃을 만들 수 있고, 소스코드에서 동적으로 만들어서 추가할 수도 있습니다.
2. onDraw() 와 onMeasure() 메소드를 오버라이드 하지 않아도 됩니다.
3. 복잡한 뷰를 생성할 수도 있고, 그것들이 하나의 컴포넌트처럼 재사용 할 수도 있습니다.
합성 컴포넌트 예제
합성 컴포넌트도 마찬가지로 안드로이드 샘플의 API Demos 의 Views/Lists 안에 있는 Example4 와 Example6 클래스가 해당되는 예제입니다.
이것들은 SpeechView 기능을 합니다. SpeechView 란 말 그대로 연설문 보여주기 같은 기능입니다.
자바 클래스는 List4.java 와 List6.java 클래스이고, 이 클래스는 합성 컴포넌트 생성을 위해 LinearLayout 을 상속했네요~
커스텀 컴포넌트에 관한 글이었습니다.
꽤 긴글이 되어 버렸네요...;;
다음 포스팅엔 커스텀 컴포넌트에 이어지는 글인 이미 존재하는 뷰를 수정해서 커스텀 뷰를 만드는 것을 살펴보죠
반응형