목 차
1. View 클래스
2. 기본적인 View 클래스들
A. Button
B. ToggleButton
C. Checkbox
D. RatingBar
3. View에서의 Event 처리
4. Cusom View 만들 때 알아야 할 점
5. ViewGroup들
A. RadioGroup
B. TimePicker
C. DatePicker
D. WebView
6. View Size
7. 시리즈 연재
1. View 클래스
Activity는 한 화면의 UI를 담당한다. 안드로이드 플랫폼에서는 Activity를 구성하기 위한 많은 View들을(위젯) 제공해주고 있다.
가장 기본이 되는 것이 View이고 상속 구조는 다음과 같다.
View는 화면에 보이는 컴포넌트의 기능을 추상화하고 있는 클래스이다.
ViewGroup은 하나 이상의 뷰를 포함할 수 있는 View 클래스이다.
Layout은 ViewGroup을 상속받아 내부에 있는 뷰들의 배치에 대한 정책을 가지고 있는 클래스이다.
2. 기본적인 View 클래스들
View는 Activity의 UI를 구성하는 가장 기본이 되는 UI 컴포넌트다. 화면에 배치되면 유저에게는 다른 모양으로
(둥근 모양이나 타원형 등) 보일지라도 사각형 영역을 차지하게 된다.
View들은 기본적으로 다음과 같은 오퍼레이션을 지원한다.
visibility 설정 : show로 화면에 보이거나 hide로 화면에서 숨기는 기능
checked 상태 확인
리스너 설정 : 버튼의 경우 클릭, 옵션의 경우 선택, 체크박스의 경우 체크 이벤트
Property 설정 : 투명도, 배경, 회전 값 등
포커스 설정 : 포커스를 요청하거나 포커스 허용 여부 설정 등
A. Button
[이미지]
[Layout]
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="New Button" android:id="@+id/button" android:layout_gravity="center_horizontal" /> |
[code]
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_example_activty); Button button = (Button) this.findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(getApplicationContext(), "button clicked", Toast.LENGTH_LONG).show(); } }); } |
B. ToggleButton
두 가지 상태를 가진 버튼이다. On/Off 상태를 가지고 있고 라이트로 그 상태를 알린다.
[이미지]
[Layout]
<ToggleButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="New ToggleButton" android:id="@+id/toggleButton" android:layout_gravity="center_horizontal" android:checked="false" /> |
[code]
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_example_activty); ToggleButton toggleButton = (ToggleButton) this.findViewById(R.id.toggleButton); toggleButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ToggleButton toggleButton = (ToggleButton )v; Toast.makeText(getApplicationContext(), "is check? : " + toggleButton.isChecked(), Toast.LENGTH_LONG).show(); } }); } |
C. Checkbox
ToggleButton이랑 비슷하다. UI만 약간 다르다.
[이미지]
[Layout]
<CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="New CheckBox" android:id="@+id/checkBox" android:layout_gravity="center_horizontal" /> |
[code]
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_example_activty); CheckBox checkBox = (CheckBox) this.findViewById(R.id.checkBox); checkBox.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { CheckBox checkBox = (CheckBox ) v; Toast.makeText(getApplicationContext(), "is check? : " + checkBox.isChecked(), Toast.LENGTH_LONG).show(); } }); } |
D. RatingBar
마켓에서 점수 줄 때 사용하는 그 View이다.
[이미지]
[Layout]
<RatingBar android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/ratingBar" android:layout_gravity="center_horizontal" /> |
[code]
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_example_activty); RatingBar ratingBar = (RatingBar) this.findViewById(R.id.ratingBar); ratingBar.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() { @Override public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) { Toast.makeText(getApplicationContext(), "Rating : " + rating, Toast.LENGTH_LONG).show(); } }); } |
3. View에서의 Event 처리
View에 전달되는 이벤트는 다음과 같다.
터치 이벤트, 키보드/트랙볼/쿼티자판 이벤트 같은 유저 이벤트
Lifecycle 변경 같은 System 제어 이벤트
이벤트들은 View에 연결된 리스너(listener)를 통해서 처리된다. 안드로이드 플랫폼에는 이미 수많은 리스너 인터페이스들이 이벤트 처리를 위한 용도로 제공하고 있다. 리스너들은 특정한 이벤트가 발생하면 자동으로 호출되어서 이벤트를 처리하게 된다.
아래는 대표적인 리스너 인터페이스들이다.
OnClickListener.onClick() : View가 클릭이 되면 호출된다.
OnLongClickListener.onLongClick() : View가 일정시간동안 눌려진 상태면 호출된다.
OnFocusChangeListener.onFocusChange() : View가 포커스를 받거나 잃으면 호출된다.
OnKeyListener.onKey() : View가 H/W 키 이벤트를 받으면 호출된다.
4. Cusom View 만들 때 알아야 할 점
대부분의 경우, 안드로이드에서 제공해주는 View 들로 충분하지만 필요할 경우, 개발자가 직접 View를 정의해서 사용할 수도 있다. 이럴 경우 알고 있어야 되는 사항에 대해서 알아보자.
우선 View들은 Tree 형태로 구성이 된다. 이런 Tree 형태의 View를 그리는 데는 다음 3가지 과정을 거친다.
Measure : Tree를 순회하면서 각 View들의 면적을 계산한다.
Layout : Tree를 순회하면서 각 View들의 위치를 계산한다.
Draw : Tree를 순회하면서 View들을 그린다.
Button과 같이 이미 존재하는 안드로이드 View를 상속 받아서 Custom View를 구성할 경우에는 필요 없겠지만 View 클래스를 직접 상속을 받아서 Custom View를 만들기 위해서는 위의 내용이 숙지하고 있어야 한다. 아래는 View 클래스의 내의 관련된 메소드들이다. 즉, 해당 메소드들을 적절히 구현해줘야 한다.
onMeasure()
View의 면적을 결정한다. View Group이라면 Child View들의 면적 또한 포함한다.
onLayout()
child View들의 사이즈와 위치를 결정한다.
onDraw()
자신을 그린다.
onFocusChanged()
View의 포커스 변화에 대해서 설정한다. (포커스를 받으면 UI 상으로 표시되는 기능)
onKeyUp(), onKeyDown()
H/W Key Event를 처리한다.
onWindowVisibilityChanged()
View를 포함하고 있는 상위 Window 의 visibility 속성이 변경되면 호출된다.
5. ViewGroup들
ViewGroup은 유저에게 보이지는 않는다. 단지 다른 View 들을 포함하는 역할 만을 수행할 뿐이다.
즉, ViewGroup은 View들의 그룹핑이나 조직화에 사용되는 보이지 않는 컨테이너이다.
A. RadioGroup
여러 개의 Radio Button이나 CheckBox를 포함할 수 있는 ViewGroup이다.
오직 하나의 button이나 CheckBox 만이 선택될 수 있는 특징을 가진다.
[이미지]
[Layout]
<RadioGroup android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:id="@+id/radioGroup"> <RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="RadioButton1" android:id="@+id/radioButton1" android:checked="true" /> <RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="RadioButton2" android:id="@+id/radioButton2" android:checked="false" /> <RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="RadioButton3" android:id="@+id/radioButton3" android:layout_gravity="center_horizontal" android:checked="false" /> </RadioGroup> |
[code]
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_example_activty); RadioGroup radioGroup = (RadioGroup) this.findViewById(R.id.radioGroup); radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup group, int checkedId) { Toast.makeText(getApplicationContext(), "checkedId : " + checkedId, Toast.LENGTH_LONG).show(); } }); } |
B. TimePicker
유저가 시간을 선택할 수 있도록 View들을 묶어 놓은 ViewGroup이다.
[이미지]
[Layout]
<TimePicker android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/timePicker" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" /> |
[code]
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_example_activty); TimePicker timePicker = (TimePicker) this.findViewById(R.id.timePicker); timePicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() { @Override public void onTimeChanged(TimePicker view, int hourOfDay, int minute) { Toast.makeText(getApplicationContext(), hourOfDay + ":" + minute, Toast.LENGTH_LONG).show(); } }); } |
C. DatePicker
유저가 날짜를 선택할 수 있도록 View들을 묶어 놓은 ViewGroup이다.
[이미지]
[Layout]
<DatePicker android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/datePicker" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" /> |
[code]
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_example_activty); DatePicker datePicker = (DatePicker) this.findViewById(R.id.datePicker); datePicker.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { DatePicker datePicker = (DatePicker) v; Toast.makeText(getApplicationContext(), "" + datePicker.getDayOfMonth(), Toast.LENGTH_LONG).show(); } }); } |
D. WebView
웹페이지를 표시할 수 있는 ViewGroup이다.
[이미지]
[Layout]
<WebView android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/webView" /> |
[code]
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_example_activty); WebView webView = (WebView) this.findViewById(R.id.webView); webView.setWebViewClient(new WebClient()); webView.loadUrl("http://naver.com"); } class WebClient extends WebViewClient { public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } } |
6. View Size
View나 ViewGroup의 크기를 결정하기 위해서는 안드로이드에서 사용되고 있는 Size 용어들에 대해서 숙지하고 있어야 한다.
아래는 안드로이드에서 사용하고 있는 Size 단위 표이다.
dp/dip가 상대적으로 중요하니 조금 상세하게 정리해보자.
이를 위해 dpi (Dot Per Inch) 개념을 먼저 알아야 한다. dpi (Dot Per Inch) 는 1인치당 픽셀 수를 의미한다.
자~ 여기 레퍼런스 디바이스가 있다고 가정해보자. 이 디바이스는 1인치당 160개의 pixel을 가진다. (160 dpi) 당연히 이 디바이스에서 1인치를 그리기 위해서는 160px을 사용해야 한다. 그럼 1인치를 그리기 위한 dp는 어떻게 될까? dp 또한 160 dp가 필요하다. 즉, 160 dpi 디바이스에서는 dp와 px가 동일한 값이 된다.
안드로이드에서는 160 dpi를 기준으로 디바이스의 해상도에 이름을 붙였다. (아래 이름들이 익숙하지 않은가? drawable 디렉토리 이름으로도 사용된다)
ldpi (low dpi) : 120 dpi
mdpi (medium dpi) : 160 dpi ⇐ 기준
hdpi (high dpi) : 240 dpi
xhdpi (extra high dpi) : 320 dpi
xxhdpi (FHD 디바이스다) : 440 dpi
xxxhdpi (QHD 디바이스다) : 640 dpi
ldpi 디바이스에서는 1 dp는 1 px보다 작은 크기이고 hdpi 혹은 그 상위 디바이스에서는 1 dp는 1 px보다 큰 값이 된다.
계산해보면 아래와 같다.
ldpi : 1 dp = 0.75 px
mdpi : 1 dp = 1 px
hdpi : 1 dp = 1.5 px
xdpi : 1 dp = 2 px
정리하자면 px를 사용할 경우 디바이스의 해상도에 따라 View의 크기가 다르게 표시된다. in 혹은 mm을 사용할 경우 디바이스의 물리적인 크기가 커질 경우에 또 골치 아프다. 따라서 대부분의 경우에는 dp를 사용하고 글꼴 크기를 설정할 때는 sp를 사용하자. 사실 dp나 sp를 쓰지 않는 방법이 가장 좋다.
7. 시리즈 연재
'소프트웨어 > 안드로이드앱' 카테고리의 다른 글
안드로이드 머티리얼 디자인에 대해서 (Material Design) (0) | 2015.07.14 |
---|---|
[안드로이드 기초#7-2] UI 클래스들 (0) | 2015.07.06 |
[안드로이드 기초#6] 프래그먼트 (Fragment) (1) | 2015.07.04 |
[안드로이드 기초#5] 권한 (Permission) (0) | 2015.07.03 |
[안드로이드 기초#4] 인텐트 (Intent) (0) | 2015.07.02 |