[안드로이드] 커스텀 컴포넌트 만들기

반응형



이어지는 글     
커스텀 컴포넌트 만들기        ◀ 현재 위치
이미 존재하는 뷰를 수정하기

읽기전에 손가락 한번 클릭~ >_<

고마워요 ~ Chu ~ ♥


안드로이드의 커스텀 컴포넌트에 관한 글입니다.


커스텀 확장 뷰 생성하기

안드로이드의 기초 레이아웃인 뷰와 뷰그룹에서는 컴포넌트화 된 모델을 제공해 줍니다. UI 를 디자인하는데 필요한 미리 정의된 뷰와 뷰 그룹의 하위 클래스 ( 위젯과 레이아웃 ) 를 가지고 있습니다.

이런것들 중에서 새로운 것을 만들기 위해 자신만의 뷰 클래스를 만들수도 있고, 기존의 위젯-레이아웃을 조금만 수정하고 싶다면 상속받은 뒤 메소드를 오버라이드 하는 방식을 사용합니다.

순서
1. 사용할 클래스에서 기존의 뷰 또는 뷰 하위클래스를 상속 받습니다.

2. 슈퍼클래스의 메소드를 오버라이드 합니다. ( 오버라이드할 슈퍼클래스의 메소드들은 on....() 으로 시작됩니다. )

3. 새로운 클래스를 기존의 뷰클래스를 대신하여 사용합니다.
[ 상속받은 클래스는 액티비티 내부에서 이너클래스(Inner Class) 로 정의할 수 있는데요, 이것은 그 액티비티 내부에서만 쓰일 수 있으므로, 어플리케이션 내에서 더 넓게 사용할 수 있는 public 뷰를 만드는것이 더 유리합니다 ]


완전한 커스텀 컴포넌트

완전한 커스텀 컴포넌트란, 만들고자 하는 어떠한 디자인으로도 컴포넌트를 만들 수 있다는 것을 의미합니다. 예를들어, " A " 라는 디자인을 하고싶은데, 이것이 내장된 컴포넌트를 어떻게 조합하더라도 만들 수 없는 경우가 있을 수도 있습니다.

즉, 원하는 방식으로 보여지고 동작하는 컴포넌트를 만들 수 있다는 얘기인데, 구글에서는 상상력과 스크린의 크기, 사용가능한 프로세스 파워만이 제약조건이 될 수 있다고 말하고 있네요 ㅎㅎ 재미있군요 ㅎ

커스텀 컴포넌트의 생성하는 순서
1. 뷰 ( View ) 클래스를 상속합니다.

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) 를 호출합니다. 위에서 언급했지만 호출하지 않으면 예외가 발생합니다.


▶ 그 밖의 뷰에서 프레임워크가 호출하는 다른 메소드들..
⊙ 생성자 : 소스코드에서 뷰가 생성될 때 호출되는 형태와, 레이아웃 파일에서 뷰가 전개(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) : 뷰를 포함한 윈도우가 보여지는 상태가 변할 때 호출됩니다.


커스텀 뷰 예제

커스텀 뷰 예제는 안드로이드에서 제공하는 샘플들 중에서 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 ) 컴포넌트

완전한 커스텀 컴포넌트를 만들기 보다는, 기존의 컨트롤들을 조합하여 구성하는 컴포넌트를 만들려면 합성 컴포넌트를 사용하면 됩니다.

이것은 하나로 취급될 수 있는 아이템들을 그룹안에서 합쳐놓는 방식이며, 안드로이드에는 이런것을 위해 제공되는 두 개의 뷰가 존재합니다.
바로 SpinnerAutoCompleteTextView 가 그것이지요.

합성 컴포넌트 만들기
1. 일반적인 시작점은 레이아웃이 됩니다. 따라서 하나의 레이아웃을 확장하는 클래스를 만들고, 컴포넌트가 구조화 될 수 있도록 다른 레이아웃을 포함합니다. 컴포넌트에 포함된 레이아웃은 XML 에서 선언하거나 소스코드에서 추가할 수 있습니다.

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 을 상속했네요~







커스텀 컴포넌트에 관한 글이었습니다.
꽤 긴글이 되어 버렸네요...;;

다음 포스팅엔 커스텀 컴포넌트에 이어지는 글인 이미 존재하는 뷰를 수정해서 커스텀 뷰를 만드는 것을 살펴보죠
 



반응형

댓글

Designed by JB FACTORY