๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๋นˆ ๊ตฌ๋ฉ ์ฑ„์šฐ๊ธฐ

[Android] View ๋ฌธ์„œ ์ฝ๊ธฐ

https://developer.android.com/reference/android/view/View

 

๋ทฐ ์‚ฌ์šฉํ•˜๊ธฐ 

๋ชจ๋“  ๋ทฐ๋“ค์„ ํ•˜๋‚˜์˜ ํŠธ๋ฆฌ ์•ˆ์— ๋ฐฐ์—ด๋œ๋‹ค. ์ฝ”๋“œ๋กœ๋“ , xml ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ์ด๋“  ๋ทฐ๋“ค์ด ํŠธ๋ฆฌ์— ์ถ”๊ฐ€๋œ๋‹ค. 

๋ทฐ๋“ค์˜ ํŠธ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•œ ํ›„์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ช‡ ๊ฐ€์ง€ ์ผ๋ฐ˜์ ์ธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

- properteis ์„ค์ • : ์˜ˆ๋ฅผ ๋“ค๋ฉด, TextView์— text๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ. ๋ทฐ์˜ ์„œ๋ธŒํด๋ž˜์Šค๋งˆ๋‹ค properties์™€ properties๋ฅผ ์„ธํŒ…ํ•˜๋Š” ๋ฉ”์†Œ๋“ค์ด ๋‹ค์–‘ํ•˜๊ฒŒ ์กด์žฌํ•œ๋‹ค. xml ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ์—์„œ ๋นŒ๋“œ ์‹œ์— ์ด ์•Œ๋ ค์ง„ ์†์„ฑ๋“ค์ด ์„ค์ •๋  ์ˆ˜ ์žˆ๋‹ค.

- focus ์„ค์ • : ์‚ฌ์šฉ์ž ์ธํ’‹์— ๋”ฐ๋ฅธ ๋ฐ˜์‘์œผ๋กœ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ํฌ์ปค์Šค ์ด๋™์„ ์ฒ˜๋ฆฌํ•จ. requestFocus()๋ฅผ ํ˜ธ์ถœํ•ด ์›ํ•˜๋Š” ํŠน์ • ๋ทฐ์— ํฌ์ปค์Šค ์„ค์ • ๊ฐ€๋Šฅ

- listeners ์„ค์ • :  ๋ทฐ์— ๋ฌด์–ธ๊ฐ€ ์ผ์ด ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ์— ์•Œ๋ฆผ ๋ฐ›๊ธฐ ์œ„ํ•œ ๋ฆฌ์Šค๋„ˆ ์„ค์ •์ด ๊ฐ€๋Šฅํ•จ.

- visiblity ์„ค์ •: ๋ทฐ๋ฅผ ๋ณด์ผ์ง€ ์ˆจ๊ธธ์ง€ setVisibility()๋กœ ์„ค์ •ํ•จ.

 

๋ทฐ๋ฅผ measuring, layout, drawingํ•˜๋Š” ๊ฒƒ์€ Android ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ๋‹ด๋‹นํ•˜๊ณ  ์žˆ์–ด์„œ ViewGroup์„ ๊ตฌํ˜„ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์ง์ ‘ ํ˜ธ์ถœํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค.

 

custom view ๊ตฌํ˜„ํ•˜๊ธฐ

custom view๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์€ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ๋ชจ๋“  ๋ทฐ์—์„œ ํ˜ธ์ถœํ•˜๋Š” ๋ช‡๋ช‡์˜ ํ‘œ์ค€ ๋ฉ”์†Œ๋“œ๋“ค์„ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๋Š” ๊ฒƒ์—์„œ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ชจ๋“  ๋ฉ”์†Œ๋“œ๋“ค์„ ์˜ค๋ฒ„๋ผ์ด๋“œํ•  ํ•„์š”๋Š” ์—†๋‹ค. onDraw(android.graphics,Canvas)๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋„ custom view๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

 

Creation. ์ƒ์„ฑ
Constructure. ์ƒ์„ฑ์ž ์ฝ”๋“œ๋กœ ๋ทฐ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ํ˜ธ์ถœํ•˜๋Š” ์ƒ์„ฑ์ž ํ˜•์‹์ด ์žˆ๊ณ , ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ์—์„œ ๋ทฐ๋ฅผ ์ธํ”Œ๋ ˆ์ดํ•  ๋•Œ ํ˜ธ์ถœํ•˜๋Š” ์ƒ์„ฑ์ž ํ˜•์‹์ด ์žˆ๋‹ค.๋‘๋ฒˆ ์งธ ํ˜•์‹์€ ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ์—์„œ ์ •์˜ํ•œ ์†์„ฑ๋“ค์„ ๋ถ„์„ํ•˜๊ณ  ์ ์šฉํ•ด์•ผ ํ•œ๋‹ค.
onFinishedInflate() XML ๋กœ๋ถ€ํ„ฐ ๋ทฐ์™€ ๋ชจ๋“  ์ž๋…€ ๋ทฐ๋“ค์ด ๋‹ค ์ธํ”Œ๋ ˆ์ดํŠธ๋œ ํ›„์— ํ˜ธ์ถœ๋œ๋‹ค.
Layout.
onMeasure(int, int) ๋ทฐ์™€ ๋ชจ๋“  ์ž๋…€ ๋ทฐ๋“ค์˜ ํฌ๊ธฐ๋ฅผ ์ •ํ•˜๊ธฐ ์œ„ํ•ด ํ˜ธ์ถœ๋œ๋‹ค.
onLayout(boolean, int, int, int, int) ๋ทฐ๊ฐ€ ๋ชจ๋“  ์ž์‹ ๋ทฐ์— ํฌ๊ธฐ์™€ ์œ„์น˜๋ฅผ ํ• ๋‹นํ•˜๊ธฐ ์œ„ํ•ด ํ˜ธ์ถœ๋œ๋‹ค.
onSizeChanged(int, int, int, int) ๋ทฐ์˜ ์‚ฌ์ด์ฆˆ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ํ˜ธ์ถœ๋œ๋‹ค.
Drawing
onDraw(android.graphics.Canvas) ๋ทฐ๊ฐ€ ์ž์‹ ์˜ ์ฝ˜ํ…์ธ ๋ฅผ ๋งŒ๋“ค์–ด์•ผํ•  ๋•Œ ํ˜ธ์ถœ๋œ๋‹ค.
Event Processing
onKeyDown(int, android.view.KeyEvent) ์ƒˆ๋กœ์šด ํ•˜๋“œ์›จ์–ด ํ‚ค ์ด๋ฒคํŠธ ๋ฐœ์ƒ์‹œ ํ˜ธ์ถœ๋œ๋‹ค.
onKeyUp(int, android.view.KeyEvent) ์ƒˆ๋กœ์šด ํ•˜๋“œ์›จ์–ด ์—… ํ‚ค ์ด๋ฒคํŠธ ๋ฐœ์ƒ์‹œ ํ˜ธ์ถœ๋œ๋‹ค.
onTrackballEvent(android.voew.MotionEvent) ํŠธ๋ž™๋ณผ ๋ชจ์…˜ ์ด๋ฒคํŠธ ๋ฐœ์ƒ์‹œ ํ˜ธ์ถœ๋œ๋‹ค.
onTouchEvent(android.view.MotionEvent) ์Šคํฌ๋ฆฐ ํ„ฐ์น˜ ๋ชจ์…˜ ์ด๋ฒคํŠธ ๋ฐœ์ƒ์‹œ ํ˜ธ์ถœ๋œ๋‹ค.
Focus
onFocusChanged(boolean, int, android.graphics.Rect) ๋ทฐ๊ฐ€ ํฌ์ปค์Šค๋ฅผ ์–ป๊ฑฐ๋‚˜ ์žƒ์„ ๋•Œ ํ˜ธ์ถœ๋œ๋‹ค.
onWindowFocusChnaged(boolean) ๋ทฐ๋ฅผ ํฌํ•จํ•˜๋Š” ์œˆ๋„์šฐ๊ฐ€ ํฌ์ปค์Šค๋ฅผ ์–ป๊ฑฐ๋‚˜ ์žƒ์„ ๋•Œ ํ˜ธ์ถœ๋œ๋‹ค.
Attaching
onAttachedToWindow() ๋ทฐ๊ฐ€ ์œˆ๋„์šฐ์— attached ๋œ ๊ฒฝ์šฐ์— ํ˜ธ์ถœ๋œ๋‹ค.
onDetachedFromWindow() ๋ทฐ๊ฐ€ ์œˆ๋„์šฐ์— detached ๋œ ๊ฒฝ์šฐ์— ํ˜ธ์ถœ๋œ๋‹ค.
onWindowVisibilityChanged(int) ๋ทฐ๋ฅผ ํฌํ•จํ•˜๋Š” ์œˆ๋„์šฐ์˜ visibility๊ฐ€ ๋ณ€ํ™”๋˜์—ˆ์„ ๊ฒฝ์šฐ ํ˜ธ์ถœ๋œ๋‹ค.

 

IDs

๋ทฐ๋“ค์€ ์ •์ˆ˜ ์•„์ด๋””๋“ค์ด ํ• ๋‹น๋œ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ xml ํŒŒ์ผ์—์„œ ํ• ๋‹น๋˜๊ณ , ๋ทฐ ํŠธ๋ฆฌ ์•ˆ์—์„œ ํŠน์„ฑ ๋ทฐ๋ฅผ ์ฐพ๋Š”๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

ํŠธ๋ฆฌ ์ „์ฒด์—์„œ ์ด ์•„์ด๋””๊ฐ€ ๊ณ ์œ ํ•  ํ•„์š”๋Š” ์—†๋Š”๋ฐ, ์ตœ์†Œํ•œ ํ˜„์žฌ ๋ณด๊ณ  ์žˆ๋Š” ํŠธ๋ฆฌ ๋‚ด์—์„œ๋Š” ๊ณ ์œ ํ•˜๋„๋ก ํ™•์ธํ•˜๋Š” ๊ฒŒ ์ข‹๋‹ค.

 

Positions

๋ทฐ๋Š” ์ง์‚ฌ๊ฐํ˜•์˜ ์˜์—ญ์„ ๊ฐ–๋Š”๋‹ค. ์™ผ์ชฝ ์ƒ๋‹จ ์ขŒํ‘œ๋ฅผ ํ•œ ์Œ์œผ๋กœ ๊ฐ€์ง€๋Š” ์œ„์น˜ ๊ฐ’๊ณผ, ๋„ˆ๋น„์™€ ๋†’์ด๋กœ ํ‘œํ˜„๋˜๋Š” 2์ฐจ์› ๊ฐ’์„ ๊ฐ€์ง„๋‹ค. ์œ„์น˜์™€ ์ฐจ์›์˜ ๋‹จ์œ„๋Š” ํ”ฝ์…€์ด๋‹ค. 

getLeft()๋กœ ๋ทฐ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์ง์‚ฌ๊ฐํ˜•์˜ X ์ขŒํ‘œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , getTop()์œผ๋กœ ๋ทฐ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์ง์‚ฌ๊ฐํ˜•์˜ Y์ขŒํ‘œ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ด ๋ฉ”์†Œ๋“œ ๋‘˜ ๋‹ค ๋ถ€๋ชจ ๋ทฐ๋กœ๋ถ€ํ„ฐ ์ƒ๋Œ€์ ์ธ ์œ„์น˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด getLeft()๋กœ 20์„ ๋ฐ˜ํ™˜๋ฐ›๋Š”๋‹ค๋ฉด, ์ด ๋ทฐ๋Š” ์ง์ ‘์ ์ธ ๋ถ€๋ชจ๋ทฐ์˜ ์™ผ์ชฝ ๊ฐ€์žฅ์ž๋ฆฌ์—์„œ ์˜ค๋ฅธ์ชฝ์œผ๋กœ 20 ํ”ฝ์…€ ๋–จ์–ด์ง„ ๊ณณ์— ์œ„์น˜ํ•œ ๊ฒƒ์ด๋‹ค.

์ถ”๊ฐ€๋กœ, ๋ถˆํ•„์š”ํ•œ ๊ณ„์‚ฐ์„ ๋ง‰๊ธฐ ์œ„ํ•ด ์—ฌ๋Ÿฌ ํŽธ๋ฆฌํ•œ ๋ฉ”์†Œ๋“œ๋“ค์„ ์ œ๊ณตํ•˜๋Š”๋ฐ, getRight(), getBottom()๋“ฑ์ด ์žˆ๋‹ค. ์ด ๋ฉ”์†Œ๋“œ๋“ค์€ ๋ทฐ๊ฐ€ ๋‚˜ํƒ€๋‚˜๋Š” ์ •์‚ฌ๊ฐํ˜•์˜ ์˜ค๋ฅธ์ชฝ์˜ ์ขŒํ‘œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์•„๋ž˜ ๊ฐ€์žฅ์ž๋ฆฌ์˜ ์ขŒํ‘œ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, geRight(),๋Š” getLeft()+getWidth() ๊ฐ’๊ณผ ๋น„์Šทํ•˜๋‹ค.

 

Size, padding ๊ทธ๋ฆฌ๊ณ  margins

๋ทฐ์˜ ์‚ฌ์ด์ฆˆ๋Š” width์™€ height๋กœ ํ‘œํ˜„๋œ๋‹ค. ๋ทฐ๋Š” ์‹ค์ œ๋กœ ๋‘ ์Œ์˜ width์™€ height ๊ฐ’๋“ค์„ ๊ฐ€์ง„๋‹ค. 

์ฒซ ๋ฒˆ์งธ ์Œ์€ measured width์™€ measured height ์ด๋‹ค. ์ด ์น˜์ˆ˜๋Š” ๋ทฐ์˜ ๋ถ€๋ชจ ์•ˆ์—์„œ ์›ํ•˜๋Š” ํฌ๊ธฐ๋ฅผ ์ •์˜ํ•œ๋‹ค.(์ž์„ธํ•œ ๊ฒƒ์€ Layout์„ ์ฐธ๊ณ ) ์ด measured ์ˆ˜์น˜๋“ค์€ getMeasuredWidth()์™€ getMeasuredHeight()๋ฅผ ํ˜ธ์ถœํ•ด์„œ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

๋‘ ๋ฒˆ์งธ ์Œ์€ width์™€ height๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ ์•Œ๋ ค์ ธ ์žˆ๊ฑฐ๋‚˜, ๋•Œ๋•Œ๋กœ drawing width, drawing height๋กœ ์•Œ๋ ค์ ธ ์žˆ๋‹ค. ์ด ์ˆ˜์น˜๋“ค์€ drawing time์— after layout ํ›„์— ์Šคํฌ๋ฆฐ์—์„œ ๋ทฐ์˜ ์‹ค์ œ ์‚ฌ์ด์ฆˆ๋ฅผ ์ •์˜ํ•œ๋‹ค. ์ด ๊ฐ’๋“ค์€ ๊ทธ๋Ÿด ํ•„์š”๋Š” ์—†์œผ๋‚˜ measured width์™€ measured height์™€ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ๋‹ค. width์™€ height๋Š” getWidth(), getHeight()๋กœ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

์ด ์ˆ˜์น˜๋“ค์„ ์ธก์ •ํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋ทฐ๋Š” ๋ทฐ์˜ padding์„ ๊ณ ๋ คํ•œ๋‹ค. padding์€ ๋ทฐ์˜ ์™ผ์ชฝ, ์ƒ๋‹จ, ์˜ค๋ฅธ์ชฝ, ํ•˜๋‹จ ๋ถ€๋ถ„์ด ํ•„์…€๋กœ ํ‘œํ˜„๋œ๋‹ค. padding์œผ๋กœ ํŠน์ • ํ”ฝ์…€๋งŒํผ ๋ทฐ์˜ ์ฝ˜ํ…์ธ ๋ฅผ ๋ณด์™„ํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์™ผ์ชฝ 2 padding์€ ๋ทฐ์˜ ์ฝ˜ํ…์ธ ๋ฅผ ์™ผ์ชฝ ๊ฐ€์žฅ์ž๋ฆฌ์—์„œ ์˜ค๋ฅธ์ชฝ์œผ๋กœ 2 ํ”ฝ์…€๋งŒํผ ๋ฐ€์–ด๋‚ธ๋‹ค. padding์€ setPadding(int,int,int,int) ๋˜๋Š” setPaddingRelative(int,int,int,int) ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด ์„ค์ •ํ•  ์ˆ˜ ์žˆ๊ณ , getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom(), getPaddingStart(), getPaddingEnd()๋ฅผ ํ˜ธ์ถœํ•ด ์งˆ์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ทฐ๊ฐ€ padding์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , margin์— ๊ด€ํ•œ ์ง€์›์€ ์ œ๊ณตํ•  ์ˆ˜ ์—†๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ทฐ ๊ทธ๋ฃน์—์„œ๋Š” ๊ทธ๋Ÿฐ ์ง€์›์ด ๊ฐ€๋Šฅํ•˜๋‹ค. ๋” ์ž์„ธํ•œ ์ •๋ณด๋Š” ViewGroup๊ณผ ViewGroup.MarginLayoutParmas๋ฅผ ์ฐธ๊ณ ํ•˜๋ผ.

 

Layout

Layout์€ ๋‘ ๋‹จ๊ณ„ ๊ณผ์ •์ด๋‹ค. ์ธก์ • ๋‹จ๊ณ„์™€ ๋ ˆ์ด์•„์›ƒ ๋‹จ๊ณ„์ด๋‹ค. ์ธก์ • ๋‹จ๊ณ„๋Š” measure(int, int)๋กœ ๊ตฌํ˜„๋˜๊ณ , ๋ทฐ ํŠธ๋ฆฌ์—์„œ ํ•˜ํ–ฅ์‹ ๋ฐฉํ–ฅ์œผ๋กœ ์ง„ํ–‰๋œ๋‹ค. ๊ฐ ๋ทฐ๋Š” ํฌ๊ธฐ์— ๋Œ€ํ•œ ๋ช…์„ธ ์ •๋ณด๋ฅผ ์žฌ๊ท€ ๊ณผ์ • ๋™์•ˆ ํŠธ๋ฆฌ์— ๋ฐ€์–ด ๋„ฃ๋Š”๋‹ค. ์ธก์ • ๋‹จ๊ณ„ ํ›„์—๋Š” ๋ชจ๋“  ๋ทฐ์— ์ธก์ •๊ฐ’์ด ์ €์žฅ๋œ๋‹ค. ๋‘ ๋ฒˆ์งธ ๋‹จ๊ณ„๋Š” layout(int, int, int, int)์—์„œ ๋ฐœ์ƒํ•˜๊ณ , ๋˜ํ•œ ํ•˜ํ–ฅ์‹์ด๋‹ค. ์ด ๊ณผ์ • ๋™์•ˆ ๊ฐ ๋ถ€๋ชจ๋Š” ์ธก์ • ๋‹จ๊ณ„์—์„œ ๊ณ„์‚ฐ๋œ ํฌ๊ธฐ๋ฅผ ์ด์šฉํ•ด ๋ชจ๋“  ์ž๋…€๋“ค์„ ๋ฐฐ์น˜์‹œํ‚ค๋Š”๋ฐ์—(positioning) ์ฑ…์ž„์ด ์žˆ๋‹ค.

๋ทฐ์˜ measure() ๋ฉ”์†Œ๋“œ๊ฐ€ ๋ฐ˜ํ™˜ํ•  ๋•Œ์—, ๋ทฐ์˜ getMeasuredWidth()์™€ getMeasuredHeight()๊ฐ’์€ ๋ฐ˜๋“œ์‹œ ์„ค์ •๋˜์–ด์•ผ ํ•˜๋Š”๋ฐ, ๋ทฐ์˜ ๋ชจ๋“  ์ž์‹๋“ค๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋‹ค. ๋ทฐ์˜ ์ธก์ •๋œ ๋„ˆ๋น„์™€ ์ธก์ •๋œ ๋†’์ด ๊ฐ’์€ ๋ทฐ์˜ ๋ถ€๋ชจ๊ฐ€ ๋ถ€๊ณผํ•œ ์ œ์•ฝ๋“ค์„ ์ค€์ˆ˜ํ•ด์•ผ ํ•œ๋‹ค.  ์ด๋ ‡๊ฒŒ ์ธก์ • ๋‹จ๊ณ„์˜ ๋์—์„œ ๋ชจ๋“  ๋ถ€๋ชจ๊ฐ€ ๋ชจ๋“  ์ž๋…€์˜ ์ธก์ •๊ฐ’์„ ๋ฐ›๋Š”๋‹ค. ๋ถ€๋ชจ ๋ทฐ๋Š” ์ž๋…€๋“ค์—๊ฒŒ์„œ ํ•œ ๋ฒˆ ์ด์ƒ์€ measure()๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด์„œ, ๋ถ€๋ชจ๋Š” ์ž๋…€๋“ค์ด ์–ผ๋งŒํผ ํฌ๊ธฐ๋ฅผ ์›ํ•˜๋Š”์ง€ ์•Œ์•„๋ณด๊ธฐ ์œ„ํ•ด ํ•œ ๋ฒˆ์€ ๋ถˆํŠน์ •ํ•œ ํฌ๊ธฐ๋กœ ์ž๋…€๋ฅผ ์ธก์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‚˜์„œ ๋งŒ์•ฝ ๋ชจ๋“  ์ž๋…€๋“ค์˜ ์ œํ•œ๋˜์ง€ ์•Š์€ ํฌ๊ธฐ์˜ ํ•ฉ์ด ๋„ˆ๋ฌด ํฌ๊ฑฐ๋‚˜ ๋„ˆ๋ฌด ์ž‘์œผ๋ฉด, ์‹ค์ œ ์ˆซ์ž๋กœ ๊ทธ๋“ค์˜ measure()๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค. 

์ธก์ • ๋‹จ๊ณ„๋Š” ํฌ๊ธฐ๋“ค์„ ์ „๋‹ฌํ•˜๊ธฐ ์šฐํ•ด  ๋‘ ํด๋ž˜์Šค๋“ค์„ ์‚ฌ์šฉํ•œ๋‹ค. MeasureSpect ํด๋ž˜์Šค๋Š” ๋ทฐ์— ์˜ํ•ด ๋ถ€๋ชจ๋“ค์ด ์–ผ๋งŒํผ ํŠน์ •๋˜๊ณ  ๋ฐฐ์น˜๋˜๊ธฐ๋ฅผ ์›ํ•˜๋Š”์ง€ ์ „ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค. ๊ธฐ๋ณธ LayoutParams ํด๋ž˜์Šค๋Š” ๋ทฐ์˜ ๋„ˆ๋ฏธ์™€ ๋†’์ด์— ๋Œ€ํ•ด ์–ผ๋งˆํผ ํฐ์ง€์— ๋Œ€ํ•ด์„œ๋งŒ ์„ค๋ช…ํ•œ๋‹ค. ๊ฐ demenstion์€, ์ด ์ค‘์— ํ•˜๋‚˜๋งŒ ๋ช…์‹œํ•œ๋‹ค. 

  • ์ •ํ™•ํ•œ ์ˆซ์ž
  • MATCH_PARENT, ๋ทฐ๊ฐ€ (ํŒจ๋”ฉ์„ ์ œ์™ธํ•˜๊ณ ) ๋ถ€๋ชจ๋งŒํผ ์‚ฌ์ด์ฆˆ๊ฐ€ ํฌ๊ธฐ๋ฅผ ์›ํ•œ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.
  • WRAP_CONTENT, ๋ทฐ๊ฐ€ (ํŒจ๋”ฉ์„ ํฌํ•จํ•ด) ๋‹จ์ง€ ์ฝ˜ํ…์ธ ๋ฅผ ๋„ฃ๊ธฐ์— ์ถฉ๋ถ„ํ•œ ์‚ฌ์ด์ฆˆ์ด๋ฉด ๋œ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.

ViewGroup์˜ ๋‹ค๋ฅธ ํ•˜์œ„ ํด๋ž˜์Šค๋“ค๊ณผ๋Š” ๋‹ค๋ฅธ LayoutParams์˜ ํ•˜์œ„ ํด๋ž˜์Šค๋“ค์ด ์กด์žฌํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, AbsoluteLayout์€ X์™€ Y ๊ฐ’์„ ์ถ”๊ฐ€ํ•œ LayoutParams์˜ ํ•˜์œ„ ํด๋ž˜์Šค์ด๋‹ค.

 

MeasureSpec๋“ค์€ ๋ถ€๋ชจ๋กœ๋ถ€ํ„ฐ ์ž๋…€๋กœ ํŠธ๋ฆฌ์— ์š”๊ตฌ์‚ฌํ•ญ๋“ค์„ ๋ฐ€์–ด๋„ฃ๋Š”๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. MeasureSpec์€ ์„ธ๊ฐ€์ง€ ๋ชจ๋“œ ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค. 

  • UNSPECIFIED : ๋ถ€๋ชจ๊ฐ€ ์ž๋…€๋ทฐ์˜ ํฌ๊ธฐ๋ฅผ ์ •ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด์„œ, LinearLayout์€ ๋†’์ด๋Š” UNSPECIFIED๋กœ, ๋„ˆ๋น„๋Š” EXACTLY 240์œผ๋กœ ์„ค์ •ํ•ด ์ž๋…€ ๋ทฐ์—์„œ measure()๋ฅผ ํ˜ธ์ถœํ•ด์„œ 240 ํ”ฝ์…€๋กœ ๋„ˆ๋น„ ๊ฐ’์ด ์ฃผ์–ด์ง€๋ฉด ์ž๋…€ ๋ทฐ๋Š” ์–ผ๋งˆ์˜ ๋†’์ด๋ฅผ ๊ฐ–๋Š”์ง€ ์•Œ์•„๋‚ผ ์ˆ˜ ์žˆ๋‹ค.
  • EXACTLY : ๋ถ€๋ชจ๊ฐ€ ์ž๋…€ ๋ทฐ์— ์ •ํ™•ํ•œ ์‚ฌ์ด์ฆˆ๋ฅผ ์ง€์ •ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. ์ž๋…€๋ทฐ๋Š” ์ด ํฌํ‚ค๋ฅผ ๋ฐ˜๋“œ์‹œ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๊ณ , ์ด ์‚ฌ์ด์ฆˆ ์ด๋‚ด์—์„œ ์ž๋…€๋ทฐ๋“ค์˜ ๋ชจ๋“  ํ•˜์œ„ ์ž์‹๋“ค์ด ๋ผ์›Œ ๋งž์ถฐ์ ธ์•ผํ•˜๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•œ๋‹ค.
  • AT_MOST : ๋ถ€๋ชจ๊ฐ€ ์ž๋…€ ๋ทฐ์— ์ตœ๋Œ€ ํฌ๊ธฐ๋ฅผ ์ •ํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค. ์ž๋…€๋ทฐ๋Š” ์ด ์‚ฌ์ด์ฆˆ ์ด๋‚ด์—์„œ ์ž๋…€๋ทฐ์˜ ๋ชจ๋“  ํ•˜์œ„ ์ž์‹๋“ค์ด ๋ผ์›Œ ๋งž์ถฐ์ ธ์•ผ ํ•˜๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•œ๋‹ค.

๋ ˆ์ด์•„์›ƒ์„ ์ดˆ๊ธฐํ™”ํ•˜๋ ค๋ฉด, requestLayout()์„ ํ˜ธ์ถœํ•œ๋‹ค. ์ด ๋ฉ”์†Œ๋“œ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ํ˜„์ œ ๊ฒฝ๊ณ„ ์ด๋‚ด์—์„œ ๋”์ด์ƒ ๋“ค์–ด๋งž์„ ์ˆ˜ ์—†๋‹ค๊ณ  ๋ทฐ๊ฐ€ ๋ฏฟ์„ ๋•Œ ๋ทฐ๊ฐ€ ์Šค์Šค๋กœ ํ˜ธ์ถœํ•œ๋‹ค.

 

Drawing ๊ทธ๋ฆฌ๊ธฐ

๊ทธ๋ฆฌ๊ธฐ๋Š” ํŠธ๋ฆฌ๋ฅผ ๋Œ๋ฉด์„œ ์—…๋ฐ์ดํŠธ๋ฅผ ์›ํ•˜๋Š” ์–ด๋–ค ๋ทฐ์—๋“ ์ง€ ๊ทธ๋ฆฌ๊ธฐ ๋ช…๋ น์–ด๋ฅผ ๊ธฐ๋กํ•˜๋ฉด ์ฒ˜๋ฆฌ๋œ๋‹ค. ์ดํ›„์—, ์ „์ฒด ํŠธ๋ฆฌ์˜ ๊ทธ๋ฆฌ๊ธฐ ๋ช…๋ น๋“ค์€ ํ™”๋ฉด์— ์‹คํ–‰๋˜๊ณ  ์ƒˆ๋กญ๊ฒŒ ๊ทธ๋ ค์ง„ ์˜์—ญ๋“ค์€ ๊ณ ์ •๋œ๋‹ค. 

์ด ํŠธ๋ฆฌ๋Š” ๋Œ€๊ฒŒ ์ˆœ์„œ๋Œ€๋กœ ๊ธฐ๋ก๋˜๊ณ  ๊ทธ๋ ค์ง€๋Š”๋ฐ, ๋ถ€๋ชจ๋Š” ๋ณธ์ธ์˜ ์ž๋…€๋“ค๋ณด๋‹ค ๋จผ์ €(๊ณต๊ฐ„์—์„œ๋Š” ๋’ค ์ชฝ์—) ๊ทธ๋ ค์ง€๊ณ , ํ˜•์ œ๋“ค์€ ํŠธ๋ฆฌ์—์„œ ๋“ฑ์žฅํ•˜๋Š” ์ˆœ์„œ๋Œ€๋กœ ๊ทธ๋ ค์ง„๋‹ค. ๋งŒ์•ฝ ๋ทฐ์— ๋ฐฑ๊ทธ๋ผ์šด๋“œ drawable์„ ์„ค์ •ํ•œ๋‹ค๋ฉด,  ๊ทธ ๋ทฐ๋Š” ๋ณธ์ธ์˜ onDraw() ๋ฉ”์†Œ๋“œ๋ฅผ๋‹ค์‹œ ํ˜ธ์ถœํ•˜๊ธฐ ์ „์— ๋ฐฑ๊ทธ๋ผ์šด๋“œ drawable์„ ๊ทธ๋ฆด ๊ฒƒ์ด๋‹ค. ์ž๋…€์˜ ๊ทธ๋ฆฌ๊ธฐ ์ˆœ์„œ๋Š” ViewGroup์˜ ์‚ฌ์šฉ์ž ์ง€์ • ์ž๋…€ ๊ทธ๋ฆฌ๊ธฐ ์ˆœ์„œ(custom child drawaing order)๋‚˜ ๋ทฐ๋“ค์—์„œ setZ(float)๋กœ Z ๊ฐ’์„ ์‚ฌ์šฉ์ž๊ฐ€ ์„ค์ •ํ•ด์„œ ์˜ค๋ฒ„๋ผ์ด๋“œํ•  ์ˆ˜ ์žˆ๋‹ค. 

๋ทฐ๋ฅผ ๊ฐ•์ œ๋กœ ๊ทธ๋ฆฌ๊ฒŒ ํ•˜๋ ค๋ฉด, invalidate()๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

 

์ด๋ฒคํŠธ ํ•ธ๋“œ๋ง๊ณผ ์“ฐ๋ ˆ๋“œ ์‹คํ–‰

๋ทฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ธฐ๋ณธ ์‚ฌ์ดํด์„ ๊ฐ€์ง„๋‹ค.

 

1. ์ด๋ฒคํŠธ๊ฐ€ ๋ฐ€๋ ค ๋“ค์–ด์˜ค๊ณ , ์ ์ ˆํ•œ ๋ทฐ์— ๋ณด๋‚ด์ง„๋‹ค. ๋ทฐ๋Š” ๊ทธ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ์–ด๋–ค ๋ฆฌ์Šคํ„ฐ๋“ค์—๊ฒŒ๋“  ์•Œ๋ ค์ค€๋‹ค.

2. ๋งŒ์•ฝ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ณผ์ •์—์„œ ๋ทฐ์˜ ๊ฒฝ๊ณ„(bounds)๊ฐ€ ๋ณ€๊ฒฝ๋  ํ•„์š”๊ฐ€ ์žˆ๋‹ค๋ฉด, ๋ทฐ๋Š” requestLayout()์„ ํ˜ธ์ถœํ•œ๋‹ค.

3. ๋น„์Šทํ•˜๊ฒŒ, ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ๊ณผ์ •์—์„œ ๋ทฐ์˜ ๋ชจ์Šต(appearance)์ด ๋ณ€๊ฒฝ๋  ํ•„์š”๊ฐ€ ์žˆ๋‹ค๋ฉด, ๋ทฐ๋Š” invalidate()๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

4. requestLayout()์ด๋‚˜ invalidate() ๋‘˜ ์ค‘์— ํ•˜๋‚˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค๋ฉด, ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ํŠธ๋ฆฌ๋ฅผ ์ธก์ •ํ•˜๊ณ (measuring), ์„ค๊ณ„ํ•˜๊ธฐ(laying out), ๊ทธ๋ฆฌ๊ธฐ(drawing)๋Š” ๊ฒƒ์„ ์ ์ ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•œ๋‹ค.

 

์ฃผ๋ชฉ : ์ „์ฒด ๋ทฐ ํŠธ๋ฆฌ๋Š” ๋‹จ์ผ ์“ฐ๋ ˆ๋“œ๋กœ ์‹คํ–‰๋œ๋‹ค. ์–ด๋Š ๋ทฐ์—์„œ๋“ ์ง€ ์–ด๋–ค ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋“ ์ง€ ํ•ญ์ƒ UI ์“ฐ๋ ˆ๋“œ์— ์žˆ์–ด์•ผ ํ•œ๋‹ค. ๋งŒ์•ฝ ๋‹ค๋ฅธ ์“ฐ๋ ˆ๋“œ๋“ค์—์„œ ์ž‘์—…ํ•˜๊ณ  ๊ทธ ์“ฐ๋ ˆ๋“œ์—์„œ ๋ทฐ์˜ ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•ด์•ผํ•œ๋‹ค๋ฉด, Handler๋ฅผ ์จ์•ผ ํ•œ๋‹ค.

 

ํฌ์ปค์Šค ์ฒ˜๋ฆฌ

ํ”„๋ ˆ์ž„ ์›Œํฌ๋Š” ์‚ฌ์šฉ์ž์˜ ์ธํ’‹์— ๋ฐ˜์‘ํ•˜๋Š” ์ผ๋ฐ˜์ ์ธ ํฌ์ปค์Šค ์›€์ง์ž„์„ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•œ๋‹ค. ์ด๊ฒƒ์€ ๋ทฐ๋“ค์ด ์ œ๊ฑฐ๋˜๊ฑฐ๋‚˜ ์‚ฌ๋ผ์งˆ ๋•Œ, ํ˜น์€ ์ƒˆ๋กœ์šด ๋ทฐ๊ฐ€ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ด์งˆ ๋•Œ ๊ฐ™์€ ํฌ์ปค์Šค์˜ ๋ณ€ํ™”๋„ ํฌํ•จํ•œ๋‹ค. ๋ทฐ๋“ค์€ isFocusable() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ํฌ์ปค์Šค๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š”์ง€๋ฅผ ๋ณด์—ฌ์ค€๋‹ค. ๋ทฐ๊ฐ€ ํฌ์ปค์Šค๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š”์ง€ ์•„๋‹Œ์ง€๋ฅผ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•ด์„œ, setFocusable(boolean)์„ ํ˜ธ์ถœํ•œ๋‹ค. ํ„ฐ์น˜ ๋ชจ๋“œ์ผ ๋•Œ, ๋ทฐ๋“ค์€ (์•„๋ž˜์˜ ๊ธฐ๋ก๋“ค์„ ๋ณด๋ฉด) ๋ทฐ๋“ค์€ isFocusableInTouchMode()๋ฅผ ํ†ตํ•ด ์—ฌ์ „ํžˆ ํฌ์ปค์Šค๋ฅผ ๊ฐ€์ง€๊ณ  ์‹ถ์–ดํ•˜๋Š”์ง€ ๋ณด์—ฌ์ฃผ๊ณ , setFocusableInTouchMode(boolean)์„ ํ†ตํ•ด ์ด๊ฒƒ์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค.

 

ํฌ์ปค์Šค ์ด๋™์€ ์ฃผ์–ด์ง„ ๋ฐฉํ–ฅ์œผ๋กœ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์ด์›ƒ์„ ์ฐพ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ๋‹ค. ํ”์น˜ ์•Š์€ ๊ฒฝ์šฐ์—, ์ด ๊ธฐ๋ณธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์˜๋„ํ•œ ํ–‰๋™์— ๋งž์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ƒํ™ฉ์—์„œ๋Š”, layout file์—์„œ XML ์†์„ฑ์„ ์ด์šฉํ•ด ๋ช…์‹œ์ ์œผ๋กœ ์˜ค๋ฒ„๋ผ์ด๋“œํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

nextFocusDown
nextFocusLeft
nextFocusRight
nextFocusUp

 

ํŠน์ • ๋ทฐ๊ฐ€ ํฌ์ปค์Šค๋ฅผ ๊ฐ€์ง€๊ธฐ ์œ„ํ•ด์„œ๋Š” requestFocus()๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

 

ํ„ฐ์น˜ ๋ชจ๋“œ

์‚ฌ์šฉ์ž๊ฐ€ D-pad์™€ ๊ฐ™์€ ๋ฐฉํ–ฅํ‚ค๋ฅผ ์ด์šฉํ•ด ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋Œ์•„๋‹ค๋‹ˆ๋Š” ์ค‘์—, ๋ฒ„ํŠผ๊ณผ ๊ฐ™์€ ์‹คํ–‰๊ฐ€๋Šฅํ•œ ์•„์ดํ…œ์— ํฌ์ปค์Šค๋ฅผ ์ค˜์„œ ์‚ฌ์šฉ์ž๊ฐ€ ๋ฌด์—‡์ด ์ž…๋ ฅ์„ ์ฃผ๋Š” ๋ณผ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๊ฒƒ์€ ํ•„์ˆ˜์ ์ด๋‹ค. ๋งŒ์•ฝ ์žฅ์น˜๊ฐ€ ํ„ฐ์น˜ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๊ณ  ์‚ฌ์šฉ์ž๊ฐ€ ๊ธฐ๊ธฐ๋ฅผ ํ„ฐ์น˜ํ•ด์„œ ์ธํ„ฐํŽ˜์ด์Šค์— ์ธํ„ฐ๋ ‰ํŒ…ํ•˜๊ธฐ ์‹œ์ž‘ํ•œ๋‹ค๋ฉด, ํŠน์ • ๋ทฐ์— ํ•ญ์ƒ ๊ฐ•์กฐํ‘œ์‹œ๋ฅผ ํ•˜๊ณ , ํฌ์ปค์Šค๋ฅผ ์ฃผ๋Š” ๊ฒƒ์ด ๋”์ด์ƒ ํ•„์ˆ˜์ ์ด์ง€ ์•Š๋‹ค. ์ด๊ฒƒ์ด 'ํ„ฐ์น˜ ๋ชจ๋“œ'๋ฅผ ์ด๋ฆ„์œผ๋กœ ํ•˜๋Š” ์ธํ„ฐ๋ ‰์…˜ ๋ชจ๋“œ์˜ ๋“ฑ์žฅ ์ด์œ ์ด๋‹ค. 

 

ํ„ฐ์น˜๊ฐ€ ๊ฐ€๋Šฅํ•œ ๊ธฐ๊ธฐ๋“ค์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์ผ๋‹จ ์Šคํฌ๋ฆฐ์„ ํ„ฐ์น˜ํ•˜๋ฉด, ๊ธฐ๊ธฐ๋Š” ํ„ฐ์น˜๋ชจ๋“œ๋กœ ์ง„์ž…ํ•œ๋‹ค. ์ด ๊ด€์ ์—์„œ ๋” ๋‚˜์•„๊ฐ€, ํ…์ŠคํŠธ ํŽธ์ง‘ ์œ„์ ฏ๋“ค ๊ฐ™์ด isFocusableInTouchMode()๊ฐ€ true์ธ ๋ทฐ๋“ค๋งŒ์ด ํฌ์ปค์Šค๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค. ๋ฒ„ํŠผ ๊ฐ™์ด ํ† ์น˜๊ฐ€ ๊ฐ€๋Šฅํ•œ ๋‹ค๋ฅธ ๋ทฐ๋“ค์€ ํ„ฐ์น˜๋˜๋„ ํฌ์ปค์Šค๋ฅผ ๊ฐ€์ง€์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๊ฒƒ๋“ค์€ ์˜ค์ง ํด๋ฆญ ๋ฆฌ์Šค๋„ˆ๋งŒ ์‹คํ–‰์‹œํ‚จ๋‹ค.

 

์‚ฌ์šฉ์ž๊ฐ€ D-pad ๋ฐฉํ–ฅ ๊ฐ™์€ ๋ฐฉํ–ฅํ‚ค๋ฅผ ๋ˆ„๋ฅด๋Š” ์–ด๋Š ๋•Œ์—๋“ ์ง€ ๋ทฐ ๊ธฐ๊ธฐ๋Š” ํ„ฐ์น˜๋ชจ๋“œ๋ฅผ ๋‚˜๊ฐ€๊ณ , ํฌ์ปค์Šค๋ฅผ ๊ฐ€์งˆ ๋ทฐ๋ฅผ ์ฐพ๋Š”๋‹ค. ๊ทธ๋ ‡๊ฒŒ ์‚ฌ์šฉ์ž๋Š” ์Šคํฌ๋ฆฐ์„ ๋‹ค์‹œ ํ„ฐ์น˜ํ•˜์ง€ ์•Š๊ณ ์„œ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค์™€ ์ธํ„ฐ๋ ‰ํŒ…์„ ์žฌ๊ฐœํ•œ๋‹ค.  

 

ํ„ฐ์น˜ ๋ชจ๋“œ ์ƒํƒœ๋Š” Activity๋“ค ๊ฐ„์— ์œ ์ง€๋œ๋‹ค. ๊ธฐ๊ธฐ๊ฐ€ ํ˜„์žฌ ํ„ฐ์น˜ ๋ชจ๋“œ ์ƒํƒœ์ธ์ง€ ์•Œ๊ธฐ ์œ„ํ•ด isInTouchMode()๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

 

์Šคํฌ๋กค๋ง

ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ๋ทฐ์˜ ๋‚ด์šฉ์„ ์Šคํฌ๋กคํ•˜๊ธฐ ์›ํ•˜๋Š” ๋ทฐ์— ๋Œ€ํ•ด ๊ธฐ๋ณธ์ ์ธ ์ง€์›์„ ์ œ๊ณตํ•œ๋‹ค. ์Šคํฌ๋กค๋ฐ”๋ฅผ ๊ทธ๋ ค์ฃผ๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜ ๋ฟ๋งŒ์ด ์•„๋‹ˆ๋ผ X์™€ Y ์Šคํฌ๋กค ์˜คํ”„์…‹์„ ์ถ”์ ํ•˜๋Š” ๊ฒƒ๋“ค์ด ์žˆ๋‹ค scrollBy(int, int), scrollTo(int, int), awakenScrollBars()๋กœ ๋” ์ƒ์„ธํ•œ ๊ฒƒ๋“ค์ด ์žˆ๋‹ค.

 

ํƒœ๊ทธ

ID์™€๋Š” ๋‹ค๋ฅด๊ฒŒ, ํƒœ๊ทธ๋Š” ๋ทฐ์˜ ์‹๋ณ„์„ ์œ„ํ•ด์„œ ์‚ฌ์šฉ๋˜์ง€๋Š” ์•Š๋Š”๋‹ค. ํƒœ๊ทธ๋Š” ๋ณธ์งˆ์ ์œผ๋กœ ๋ทฐ์— ํ• ๋‹ฌ๋  ์ˆ˜ ์žˆ๋Š” ์ถ”๊ฐ€์ ์ธ ์ •๋ณด ์กฐ๊ฐ์ด๋‹ค. ํƒœ๊ทธ๋Š” ๋ทฐ์™€ ๊ด€๋ จ๋œ ์ •๋ณด๋“ค์„ ๋ถ„๋ฆฌ๋œ ๊ตฌ์กฐ์— ์ €์žฅํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋ทฐ ์ž์ฒด์— ์ €์žฅํ•˜๋Š” ํŽธ์˜์„ฑ ๋•Œ๋ฌธ์— ์ž์ฃผ ์‚ฌ์šฉ๋œ๋‹ค.

 

ํƒœ๊ทธ๋Š” ๋ ˆ์ด์•„์›ƒ XML์—์„œ ๋ฌธ์ž์—ด ๊ฐ’์ด๋‚˜, android:tag ์†์„ฑ์„ ์จ์„œ ํ•˜๋‚˜์˜ ํƒœ๊ทธ๋‚˜ <tag> ์ž๋…€ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•ด ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํƒœ๊ทธ๋“ค๋กœ ๋ช…์‹œ๋  ์ˆ˜ ์žˆ๋‹ค.

 

<View ..
    android:tag="@string/mytag_value" />
<View ...>
    <tag android:id="@+id/mytag"
         android:value="@string/mytag_value" />
</View>

ํƒœ๊ทธ๋Š” setTag(java.lang.Object) ๋˜๋Š” setTag(int, java.lang.Object)๋ฅผ ์‚ฌ์šฉํ•ด ์ž„์˜์˜ ์˜ค๋ธŒ์ ํŠธ๋กœ ์ฝ”๋“œ์—์„œ ๋ช…์‹œ๋  ์ˆ˜ ์žˆ๋‹ค.

 

ํ…Œ๋งˆ

์ผ๋ฐ˜์ ์œผ๋กœ, ๋ทฐ๋“ค์€ ๊ทธ๋“ค์˜ ์ƒ์„ฑ์ž์—์„œ ์ œ๊ณต๋œ Context ๊ฐ์ฒด์˜ ํ…Œ๋งˆ๋ฅผ ์ด์šฉํ•ด ์ƒ์„ฑ๋œ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜, ๋ ˆ์ด์•„์›ƒ XML์—์„œ android:theme ์†์„ฑ์„ ์ด์šฉํ•˜๊ฑฐ๋‚˜ ์ฝ”๋“œ์—์„œ ContextThemeWrapper๋ฅผ ์ƒ์„ฑํ•˜์— ๋ณด๋‚ด์„œ ๋‹ค๋ฅธ ํ…Œ๋งˆ๋ฅผ ๋ช…์‹œํ•  ์ˆ˜ ์žˆ๋‹ค.

 

android:theme ์†์„ฑ์€ XML์—์„œ ์‚ฌ์šฉ๋˜๊ณ , ๋ช…์‹œ๋œ ํ…Œ๋งˆ๋Š” inflation context์˜ ํ…Œ๋งˆ(LayoutInflater๋ฅผ ๋ณด๋ผ)์— ์ตœ์ƒ๋‹จ์— ์ ์šฉ๋˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ์ž๋…€ ์š”์†Œ๋“ค๋ฟ๋งŒ์ด ์•„๋‹ˆ๋ผ ๋ทฐ ์ž์ฒด์— ์‚ฌ์šฉ๋œ๋‹ค.

 

๋‹ค์Œ์˜ ์˜ˆ์‹œ์—์„œ, ๋‘ ๋ทฐ๋“ค ๋ชจ๋‘ Materail dark color ์Šคํ‚ค๋งˆ๋ฅผ ์ด์šฉํ•ด ์ƒ์„ฑ๋  ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌ๋‚˜, ์˜ค๋ฒ„๋ ˆ์ด ํ…Œ๋งˆ๊ฐ€ ์†์„ฑ๋“ค์˜ ํ•˜์œ„ ์ง‘ํ•ฉ๋งŒ ์ •์˜ํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— inflation context์˜ ํ…Œ๋งˆ(e.g. Activity ํ…Œ๋งˆ)์—์„œ ์ •์˜๋œ android:colorAccent ๊ฐ’์€ ์œ ์ง€๋œ๋‹ค. 

 

<LinearLayout
        ...
        android:theme="@android:theme/ThemeOverlay.Material.Dark">
    <View ...>
</LinearLayout>

 

์†์„ฑ๋“ค

๋ทฐ ํด๋ž˜์Šค๋Š” TRNASLATION_X์™€ TRANSLATION_Y์™€ ๊ฐ™์ด ์—ฌ๋Ÿฌ ๋ณ€ํ™˜๊ณผ ๊ด€๋ จ๋œ ์†์„ฑ๋“ค ๋ฟ๋งŒ์ด ์•„๋‹ˆ๋ผ ALPHA ์†์„ฑ์„ ๊ฐ€์ง„๋‹ค.์ด ์†์„ฑ๋“ค์€ ๋น„์Šทํ•˜๊ฒŒ ์ด๋ฆ„์„ ๊ฐ€์ง„ setter/getter ๋ฉ”์†Œ๋“œ(ALPHA์— ๋Œ€ํ•ด์„œ๋Š” setAlpha(float)) ๋ฟ๋งŒ์ด ์•„๋‹ˆ๋ผ Property  ํ˜•์‹์—์„œ ๋‘˜๋‹ค ๊ฐ€๋Šฅํ•˜๋‹ค. ์ด ์†์„ฑ๋“ค์€ ์ง€์†์ ์ธ ์ƒํƒœ๋ฅผ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋ทฐ์—์„œ ๋ Œ๋”๋ง๊ณผ ๊ด€๋ จ๋œ ์†์„ฑ๋“ค๊ณผ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋‹ค. ์ด ์†์„ฑ๋“ค๊ณผ ๋ฉ”์†Œ๋“œ๋“ค์€ ๋˜ํ•œ Animator๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ์• ๋‹ˆ๋ฉ”์ด์…˜๋“ค๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๊ณ , ์ž์„ธํ•œ ๊ฒƒ์€ Animation ์„น์…˜์— ์žˆ๋‹ค.

 

์• ๋‹ˆ๋ฉ”์ด์…˜

 ์•ˆ๋“œ๋กœ์ด๋“œ 3.0์„ ์‹œ์ž‘ํ•˜๋ฉด์„œ, ๋ทฐ์— ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ฃผ๋Š” ์„ ํ˜ธ๋˜๋Š” ๋ฐฉ๋ฒ•์€ android.animation ํŒจํ‚ค์ง€์˜ API๋“ค์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์ด Animator ๊ธฐ๋ฐ˜ ํด๋ž˜์Šค๋“ค์€ ๋ทฐ ๊ฐ์ฒด์˜ ์‹ค์ œ๋กœ alpha์™€ translationX๊ฐ™์€ ์†์„ฑ ๊ฐ’๋“ค์„ ๋ฐ”๊พผ๋‹ค. ์ด ๋™์ž‘์€ 3.0 ์ด์ „์˜ Animation ๊ธฐ๋ฐ˜์˜ ํด๋ž˜์Šค๋“ค์˜ ๋™์ž‘๊ณผ ๋Œ€์กฐ๋˜๊ณ , ๋Œ€์‹ ์— ๋””์Šคํ”Œ๋ ˆ์ด์— ๋ทฐ๋ฅผ ์–ด๋–ป๊ฒŒ ๊ทธ๋ฆฌ๋Š” ์ง€๋ฅผ ์• ๋‹ˆ๋ฉ”์ด์…˜์œผ๋กœ ๋งŒ๋“ ๋‹ค. ํŠนํžˆ, ViewPropertyAnimator ํด๋ž˜์Šค๋Š” ํŠนํžˆ ์‰ฝ๊ณ  ํšจ์œจ์ ์œผ๋กœ ๋ทฐ ์†์„ฑ๋“ค์„ ์• ๋‹ˆ๋ฉ”์ด์…˜์œผ๋กœ ๋งŒ๋“ค์–ด์ค€๋‹ค.  

 

๊ทธ ๋Œ€์‹ ์—, ์–ด๋–ป๊ฒŒ ๋ทฐ๊ฐ€ ๋ Œ๋”๋ง๋˜๋Š”์ง€ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ฃผ๊ณ ์žํ•˜๋ฉด 3.0 ์ด์ „ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํด๋ž˜์Šค๋“ค์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. Animation ๊ฐ์ฒด๋ฅผ setAnimation(android.view.animation.Animation) ๋˜๋Š” startAnimation(android.view.animation.Animation)์„ ์‚ฌ์šฉํ•ด์„œ ๋ทฐ์— attach ํ•  ์ˆ˜ ์žˆ๋‹ค. ์• ๋‹ˆ๋ฉ”์ด์…˜์€ ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด์„œ ๋ทฐ์˜ ์Šค์ผ€์ผ, ํšŒ์ „ ๋ณ€ํ™˜๊ณผ ์•ŒํŒŒ๋ฅผ ๊ณ ์น  ์ˆ˜ ์žˆ๋‹ค. ๋งŒ์•ฝ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์ž์‹์ด ์žˆ๋Š” ๋ทฐ์— attach๋๋‹ค๋ฉด, ๊ทธ ์• ๋‹ˆ๋ฉ”์ด์…˜์€ ๋…ธ๋“œ์— ์˜ํ•ด ๊ณ ์ •๋œ ํ•˜์œ„ ํŠธ๋ฆฌ ์ „์ฒด์— ์˜ํ–ฅ์„ ์ค€๋‹ค. ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์‹œ์ž‘ํ•  ๋•Œ ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ์ ๋‹นํ•œ ๋ทฐ๋ฅผ ๋‹ค์‹œ ๊ทธ๋ฆฌ๋Š” ๊ฒƒ์„ ์ฒ˜๋ฆฌํ•  ๊ฒƒ์ด๋‹ค.

 

๋ณด์•ˆ

๋•Œ๋•Œ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‚ฌ์šฉ์ž์˜ ์ถฉ๋ถ„ํ•œ ์ •๋ณด์™€ ๋™์˜๋ฅผ ๊ฐ€์ง€๊ณ  ๊ถŒํ•œ ์š”์ฒญ์„ ํ—ˆ๋ฝํ•˜๊ฑฐ๋‚˜ ๊ตฌ๋งค๋ฅผ ์ง„ํ–‰ํ•˜๊ฑฐ๋‚˜ ๊ด‘๊ณ ๋ฅผ ํด๋ฆญํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๋™์ž‘์ด ์ž˜ ์ˆ˜ํ–‰๋˜๋Š” ์ง€๋ฅผ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋ถˆํ–‰ํžˆ๋„, ์•…์˜์ ์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๋ทฐ์˜ ์˜๋„๋œ ๋ชฉ์ ์„ ์ˆจ์…”๊ฑฐ ์‚ฌ์šฉ์ž๋ฅผ ์†์—ฌ ์ž์‹ ๋„ ๋ชจ๋ฅด๊ฒŒ ์ด ์ž‘์—…๋“ค์„ ์ง„ํ–‰ํ•˜๋ ค๊ณ  ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค. ํ•ด๊ฒฐ์ฑ…์œผ๋กœ, ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ๋ฏผ๊ฐํ•œ ๊ธฐ๋Šฅ์— ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์„ ์ œ๊ณตํ•˜๋Š” ๋ทฐ์˜ ๋ณด์•ˆ์„ ํ–ฅ์ƒ์‹œํ‚ค๋Š”๋ฐ ์“ฐ์ผ ์ˆ˜ ์žˆ๋Š” ํ„ฐ์น˜ ํ•„ํ„ฐ๋ง ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. 

 

ํ„ฐ์น˜ ํ•„ํ„ฐ๋ง์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด์„œ, setFilterTouchesWhenObscured(boolean)์„ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜  android:filterTouchesWhenObscured layout ์†์„ฑ์„ true๋กœ ์„ค์ •ํ•œ๋‹ค. ๊ฐ€๋Šฅํ•  ๋•Œ, ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ๋ทฐ์˜ ์œˆ๋„์šฐ๊ฐ€ ํ„ฐ์น˜๋œ ์œ„์น˜์— ๋‹ค๋ฅธ ๋ณด์ด๋Š” ์œˆ๋„์šฐ์— ์˜ํ•ด ์ž˜ ๋ณด์ด์ง€ ์•Š์„ ๋•Œ๋งˆ๋‹ค ์ž…๋ ฅ๋œ ํ„ฐ์น˜๋ฅผ ๋ฒ„๋ฆด ๊ฒƒ์ด๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ, ๋ทฐ๋Š” ํ„ฐ์น˜๊ฐ€ ํ† ์ŠคํŠธ, ๋‹ค์ด์–ผ๋กœ๊ทธ๋‚˜ ๋‹ค๋ฅธ ์œˆ๋„์šฐ๋ฅผ ๋šซ๊ณ  ์˜ค๋Š” ์–ธ์ œ๋“ ์ง€ ํ„ฐ์น˜๋ฅผ ๋ฐ›์ง€ ์•Š์„ ๊ฒƒ์ด๋‹ค.

 

๋ณด์•ˆ์— ๋Œ€ํ•ด ๋” ์„ธ๋ฐ€ํ•œ ์ œ์–ด๋ฅผ ์œ„ํ•ด์„œ๋Š”, ๊ณ ์œ  ๋ณด์•ˆ ์ •์ฑ…์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ onFilterTouchEventForSecurity(android.view.MotionEvent) ๋ฉ”์†Œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•˜๋ผ. MotionEvent#FLAG_WINDOW_IS_OBSCURED ๋˜ํ•œ ํ™•์ธํ•˜๋ผ.