์๋๋ก์ด๋ ๊ธฐ๋ณธ ์์ ฏ ์์ ฏ ๋๋ ๋ ์ด์์์ด ์๊ตฌ์ฌํญ์ ๋ง์ง์๋๋ค๋ฉด View ์๋ธํด๋์ค๋ฅผ ์ง์ ๋ง๋ค ์ ์๋ค.
๊ธฐ์กด ์์ ฏ ๋๋ ๋ ์ด์์์ ์ฝ๊ฐ๋ง ์กฐ์ ํด์ผ ํ๋ ๊ฒฝ์ฐ ์์ ฏ ๋๋ ๋ ์ด์์์ ์๋ธํด๋์ค๋ก ๋ง๋ค๊ณ ๊ทธ ๋ฉ์๋๋ฅผ ์ฌ์ ์ ํ ์๋ ์๋ค.
- View or Layout์ ํ์ฅํ๋ ํด๋์ค๋ฅผ ์์ฑํ๋ค
- XML์์ ์์ฑ๊ณผ ๋งค๊ฐ๋ณ์๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ ์์ฑ์๋ฅผ ๋ง๋ ๋ค
- ์ํผํด๋์ค์ ์ผ๋ถ ๋ฉ์๋๋ฅผ ์ฌ์ ์ํ๋ค
- onDraw()
- onMeasure()
- onLayout()
- onSizeChanged()
- ํ์ํ ๋ค๋ฅธ on.. ๋ฉ์๋ ์ฌ์ ์
- ์๋ก ์์ฑํ ํ์ฅ ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ค
View๊ฐ ์์ฑ๋๊ณ , ParentView์ addView๊ฐ ํธ์ถ๋๋ฉด onAttachToWindow()
๊ฐ ํธ์ถ๋๊ณ , ํฌ๊ธฐ๋ฅผ ๊ฒฐ์ ํ๊ณ , ๋ ์ด์์์ ๊ทธ๋ฆฌ๊ณ , Canvas์์ ๊ทธ๋ฆฌ๋ onDraw()
๊น์ง ํธ์ถ๋๋ค.
๋ชจ๋ CustomView๋ ์์ฑ์์์ ์ถ๋ฐํ๋ค.
์์ฑ์์์ ์ด๊ธฐํํ๊ณ , default๊ฐ ๋ฑ์ ์ค์ ํ๋ค.
View๋ ์ด๊ธฐ ์ค์ ์ ์ฝ๊ฒ ์ธํ
ํ๊ธฐ์ํด AttributeSet์ด๋ผ๋ ์ธํฐํ์ด์ค๋ฅผ ์ง์ํ๋ค.
attrs.xmlํ์ผ(res/valeus/attrs.xml)์ ๋ง๋ค์ด ์ด๊ฒ์ ๋ถ๋ฆ์ผ๋ก์ ๋ทฐ์ ์ค์ ๊ฐ์ ์ฝ๊ฒ ์ค์ ํ ์ ์๋ค.
attrs.xml ํ์ผ์ ์๋์ ๊ฐ์ด ๋ฆฌ์์ค ์์ฑ
CustomView์ ์์ฑ์ ์ ๋ฌํ๋ฉด ์์ฑ์๋ก ์ ๋ฌํ๋ค
์์ฑ์์์๋ ์๋์ ๊ฐ์ด ์ค์ ํ ์์ฑ์ ๋ถ๋ฌ์จ๋ค
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0){
val strokeWidth = context.obtainStyledAttributes(attrs, R.styleable.NewAttr)
.getDimensionPixelSize(
R.styleable.NewAttr_strokeWidth,
context.resources.getDimensionPixelSize(R.dimen._2dp)
)
val color = context.obtainStyledAttributes(attrs, R.styleable.NewAttr)
.getColor(R.styleable.NewAttr_strokeColor, Color.WHITE)
}
Parent View๊ฐ addView(childView)
๋ฅผ ํธ์ถํ๊ณ ๋์ ํธ์ถ
View๋ layout์์์ ๊ฐ๊ฐ ์์ ์ width๋ height์ ๊ฐ์ง๋ค.
์์ ์ width, height๋ฅผ widthMeasureSpec(๋ถ๋ชจ์ปจํ
์ด๋์์ ์ ํ ๊ฐ๋ก), heightMeasureSpec(๋ถ๋ชจ์ปจํ
์ด๋์์ ์ ํ ์ธ๋ก)๋ผ ํ๋ค.
measure(widthMeasureSpec: Int, heightMeasureSpec: Int)
ํธ์ถ- ๋ถ๋ชจ๋ ธ๋์์ ์์๋ ธ๋๋ฅผ ๊ฒฝ์ ํ๋ฉฐ ์คํ๋๋ฉฐ, View์ ํฌ๊ธฐ๋ฅผ ์์๋ด๊ธฐ์ํด ํธ์ถ
- ์ค์ View์ ํฌ๊ธฐ๋ฅผ ์ธก์ ํ๋๊ฒ์ ์๋๋ฉฐ, ์ค์ ํฌ๊ธฐ๋
onMeasure(int,int)
์์ ์ธก์ ํ๋ค
onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int)
๋ฅผ ํธ์ถํ์ฌ View์ ํฌ๊ธฐ๋ฅผ ์์๋ธ๋ค
- View๊ฐ ์ํ๋ ์ฌ์ด์ฆ๋ฅผ ๊ณ์ฐ
- MeasureSpec ์ ๋ฐ๋ผ mode ๋ฅผ ๊ฐ์ ธ์จ๋ค
- MeasureSpec์ mode๋ฅผ ์ฒดํฌํ์ฌ ๋ทฐ์ ํฌ๊ธฐ๋ฅผ ์ ์ฉ
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val widthMode = MeasureSpec.getMode(widthMeasureSpec)
val widthSize = MeasureSpec.getSize(widthMeasureSpec)
val heightMode = MeasureSpec.getMode(heightMeasureSpec)
val heightSize = MeasureSpec.getSize(heightMeasureSpec)
val width = when (widthMode) {
MeasureSpec.EXACTLY -> widthSize
MeasureSpec.AT_MOST -> (paddingLeft + paddingRight + suggestedMinimumWidth).coerceAtMost(widthSize)
else -> widthMeasureSpec
}
val height = when (heightMode) {
MeasureSpec.EXACTLY -> heightSize
MeasureSpec.AT_MOST -> (paddingTop + paddingBottom + suggestedMinimumHeight).coerceAtMost(heightSize)
else -> heightMeasureSpec
}
setMeasuredDimension(width, height)
}
MeasureSpec.AT_MOST : wrap_content ์ ๋งคํ๋๋ฉฐ ๋ทฐ ๋ด๋ถ์ ํฌ๊ธฐ์ ๋ฐ๋ผ ํฌ๊ธฐ๊ฐ ๋ฌ๋ผ์ง๋ค
MeasureSpec.EXACTLY : fill_parent, match_parent ๋ก ์ธ๋ถ์์ ๋ฏธ๋ฆฌ ํฌ๊ธฐ๊ฐ ์ง์ ๋๋ค
MeasureSpec.UNSPECIFIED : Mode ๊ฐ ์ค์ ๋์ง ์์์ ๊ฒฝ์ฐ. ์์ค์์์ ์ฌ์ด์ฆ๋ฅผ ์ง์ ๋ฃ์์ ๋ ์ฌ์ฉ
layout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int)
ํธ์ถ- ๋ถ๋ชจ์์ ์์๋ ธ๋๋ฅผ ๊ฒฝ์ ํ ๋ ์คํ๋๋ฉฐ, View์ Child View๋ค์ ํฌ๊ธฐ์ ์์น๋ฅผ ํ ๋นํ๋ค
measure(int,int)
์ ์ํด ๊ฐ ๋ทฐ์ ์ ์ฅ๋ ํฌ๊ธฐ๋ฅผ ์ฌ์ฉํ์ฌ ์์น๋ฅผ ์ง์ ํ๋ค- CustomView๊ฐ ParentView์ผ๋ ์ฃผ๋ก ์ฐ์ธ๋ค.
- ๋์ด์ค๋ ํ๋ผ๋ฏธํฐ๋ ์ดํ๋ฆฌ์ผ์ด์ ์ ์ฒด๋ฅผ ๊ธฐ์ค์ผ๋ก ๋์ด์จ๋ค (์ฃผ์)
์ค์ ๋ก ๋ทฐ๋ฅผ ๊ทธ๋ฆฌ๋ ๋จ๊ณ์ด๋ค.
onDraw()
ํจ์๋ ๊ฐ๋ฐ์๊ฐ ์ํ๋๋๋ก ๊ตฌํํ ์ ์๋ Canvas๋ฅผ ์ ๊ณตํ๋ค.
onDraw()
๋ฅผ ์ค๋ฒ๋ผ์ด๋ํ๊ณ , Canvas์ ๊ทธ๋ฆฌ๊ณ ์ถ์ ์ ์ฉ์ ๊ทธ๋ฆฌ๋ฉด ๋๋ค.
Scroll ๋๋ Swipe๋ฅผ ํ ๋ onDraw()
๊ฐ ๋ค์ ํธ์ถ๋๋๋ฐ
onDraw()
ํจ์๋ ํธ์ถ ๋น์ฉ์ด ํฌ๋, ํ๋ฒ ์์ฑํ ๊ฐ์ฒด๋ฅผ ์ฌํ์ฉํ๋ ๋ก์ง์ ์ถ๊ฐํด์ฃผ๋๊ฒ์ด ์ข๋ค.
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
val width = measuredWidth + 0.0f
val height = measuredHeight + 0.0f
val circle = Paint()
circle.color = this.lineColor
circle.strokeWidth = 10f
circle.isAntiAlias = false
circle.style = Paint.Style.STROKE
canvas?.drawArc(
RectF(
10f, 10f, width - 10f, height - 10f
), -90f,
(this.curValue + 0.0f) / (this.maxValue + 0.0f) * 360, false, circle
)
val textp = Paint()
textp.color = Color.BLACK
textp.textSize = 30f
textp.textAlign = Paint.Align.CENTER
if (System.currentTimeMillis() / 1000 % 2 == 0L) {
canvas?.drawText(
"${this.curValue} / ${this.maxValue}",
(width / 2),
(height / 2),
textp
)
}
}
View์ text ๋๋ color๋ณ๊ฒฝ ๋ฑ ๋จ์ํ View๋ฅผ ๋ค์ ๊ทธ๋ฆด๋๋,
touch interaction๋ฑ์ด ๋ฐ์ํ ๋ onDraw()
๋ฅผ ํธ์ถํ๋ฉฐ View๋ฅผ ๋ค์ ๊ทธ๋ฆฐ๋ค.
measure()
๋ถํฐ ํธ์ถํ์ฌ ๋ค์ View๋ฅผ ๊ทธ๋ฆฐ๋ค.
๋ทฐ์ ์ฌ์ด์ฆ๊ฐ ๋ณ๊ฒฝ๋์์๋, ๊ทธ๊ฒ์ ๋ค์ ์ธก์ ํด์ผ๋ ๋ ํธ์ถํ๋ค.