728x90
- 이전 글
일부 속성 값을 사용자한테 입력받기
- 일부 속성의 값은 사용자에게 입력받는 것이 좋습니다.
- 텍스트 크기, 배경 원의 선 색상, 텍스트 색상 등
- 사용자에게 속성을 입력받기 위해 커스텀 뷰에서 사용할 커스텀 속성을 추가해야합니다.
- 사용자에게 값을 받을 수 있는 방법은 2가지 입니다.
- Activity/Fragment에서 전달받기
- xml(layout)에서 전달받기
0. 커스텀 속성 추가
- 자신의 커스텀 뷰에서 사용할 속성(Size, Color 등)을 정의할 수 있습니다.
- 커스텀 속성의 경우 values 디렉토리의 attrs.xml에 생성합니다.(안드로이드 뷰 클래스 가이드 참고)
- attrs.xml의 경우 프로젝트 생성 시 자동으로 생성되지 않으니 생성해주세요!
- attrs.xml에 아래와 같이 커스텀 속성을 추가했습니다.
<resources xmlns:tools="http://schemas.android.com/tools">
<declare-styleable name="RouletteView">
<attr name="rouletteBorderLineColor" format="reference|color"/>
<attr name="textColor" format="reference|color"/>
<attr name="rouletteSize" format="integer"/>
<attr name="textSize" format="reference|dimension"/>
<attr name="emptyMessage" format="string"/>
<attr name="rouletteBorderLineWidth" format="reference|dimension"/>
</declare-styleable>
</resources>
- <attr> 태그를 통해 커스텀 뷰에서 사용할 속성을 정의합니다.
- reference의 경우 xml에서 id값으로 추가가 가능하게합니다.
- ex) @color/white
- reference의 경우 xml에서 id값으로 추가가 가능하게합니다.
1. xml(layout)에서 전달받기
- CustomView 클래스에서 typedArray 객체를 통해 해당 스타일을 사용한다고 설정합니다.
class Roulette @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
...
init {
val typedArray = context.theme.obtainStyledAttributes(
attrs,
R.styleable.RouletteView,
defStyleAttr,
0
)
...
}
- 위에서 생성한 typedArray 객체를 통해 각 속성을 사용자가 추가한 데이터를 전달받을 수 있도록 하고 사용자가 아무것도 입력하지 않으면 기본값으로 초기화하도록 설정해줍니다.
class Roulette @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
private var textSize = 0f
private var textColor = Color.BLACK
private var rouletteBorderLineColor = Color.BLACK
private var rouletteBorderLineWidth = 0f
...
init {
val typedArray = context.theme.obtainStyledAttributes(
attrs,
R.styleable.RouletteView,
defStyleAttr,
0
)
rouletteBorderLineColor = typedArray.getColor(
R.styleable.RouletteView_rouletteBorderLineColor,
Color.BLACK
)
rouletteBorderLineWidth = typedArray.getDimension(
R.styleable.RouletteView_rouletteBorderLineWidth,
20f
)
textColor = typedArray.getColor(
R.styleable.RouletteView_textColor,
Color.BLACK
)
textSize = typedArray.getDimension(
R.styleable.RouletteView_textSize,
60f
)
typedArray.recycle()
...
}
- 코드 설명
- getColor()/getDimension()/getColor()/getDimension()
- 사용한 4개의 함수말고도 getBoolean()이나 getFloat()등이 있으며 위에서 추가한 속성에 맞게 사용해 변수를 초기화합니다.
- 파라미터는 대부분의 함수가 비슷합니다. getXXX(int index, <Type> defaultValue)
- int index
- index는 declare-styleable을 추가하면 자동으로 생성되는 <declare-styleable_name>_<attr_name>를 추가하면 됩니다.
- <Type> defaultValue
- defaultValue는 사용자가 속성을 추가하지 않으면 기본값으로 사용할 값을 추가하면 되며 각 속성에 맞는 타입의 데이터를 설정하면 됩니다.
- typedArray.recycle()
- typedArray 객체는 공유 리소스로 사용 후 재사용을 위해 생성자(또는 init{})에서 recycle()을 호출해야합니다.
- getColor()/getDimension()/getColor()/getDimension()
- xml에서 확인하기
- app 네임스페이스로 속성을 설정해줄 수 있습니다.
<com.jhdroid.view.Roulette
android:id="@+id/roulette"
android:layout_width="wrap_content"
android:layout_height="0dp"
app:rouletteSize="3"
app:textSize="40sp"
app:textColor="@color/white"
app:emptyMessage="Hello" />
- xml에서 직접 정의한 속성을 설정해주면 바로 View가 변하는 것을 확인할 수 있습니다.
2. Activity/Fragment에서 전달받기
- 상황에 따라 xml아니라 Activity/Fragment 등에서 UI를 변경하는 경우가 있기 때문에 사용자가 일부 속성을 코드로 설정할 수 있도록 해야합니다.
- 1. xml에서 전달받기 과정에서 등록한 속성 변수들의 getter & setter 함수를 생성합니다.
- 그 후 setter 함수의 `최하단`에 데이터를 받은 후 뷰를 갱신해주기 위해 invalidate() 함수를 추가합니다.
class Roulette @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
private var textSize = 0f
private var textColor = Color.BLACK
private var rouletteBorderLineColor = Color.BLACK
private var rouletteBorderLineWidth = 0f
...
init {
val typedArray = context.theme.obtainStyledAttributes(
attrs,
R.styleable.RouletteView,
defStyleAttr,
0
)
textColor = typedArray.getColor(
R.styleable.RouletteView_textColor,
Color.BLACK
)
textSize = typedArray.getDimension(
R.styleable.RouletteView_textSize,
60f
)
rouletteBorderLineColor = typedArray.getColor(
R.styleable.RouletteView_rouletteBorderLineColor,
Color.BLACK
)
rouletteBorderLineWidth = typedArray.getDimension(
R.styleable.RouletteView_rouletteBorderLineWidth,
20f
)
typedArray.recycle()
...
}
...
fun setTextSize(textSize: Float) {
this.textSize = textSize
invalidate()
}
fun getTextSize(): Float = textSize
fun setTextColor(textColor: Int) {
this.textColor = textColor
invalidate()
}
fun getTextColor(): Int = textColor
fun setRouletteBorderLineColor(borderLineColor: Int) {
this.rouletteBorderLineColor = borderLineColor
invalidate()
}
fun getRouletteBorderLineColor(): Int = rouletteBorderLineColor
fun setRouletteBorderLineWidth(width: Float) {
rouletteBorderLineWidth = width
invalidate()
}
fun getRouletteBorderLineWidth(): Float = rouletteBorderLineWidth
}
- 위 코드 처럼 각 속성에 맞게 변수를 생성하고 getter & setter 함수를 추가하면 Activity/Fragment에서 뷰의 속성을 변경할 수 있습니다.
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.activity = this
binding.roulette.apply {
setTextColor(R.color.black)
setRouletteBorderLineColor(R.color.white)
getTextColor()
getRouletteTextSize()
}
}
...
}
- setter 함수를 통해 속성을 설정할 수 있으며 설정된 속성의 값을 getter 함수를 통해 받아올 수 있습니다.
- setter의 경우 데이터를 설정함과 동시에 invalidate()를 호출하며 View를 새로 그릴 수 있도록 해줍니다.
requestLayout()에 대해
- 안드로이드 뷰 클래스 가이드를 보면 setter 함수에서 invalidate()함수와 함께 requestLayout() 함수도 호출하는 것을 확인할 수 있는데 invalidate()와 requestLayout()의 차이는 다음 뷰 라이프사이클을 이미지를 참고해주세요.
- invalidate()는 Custom View를 다시 그리게 해줍니다. - onDraw() 재호출
- requestLayout()는 Custom View의 레이아웃을 갱신하도록 합니다. - onMeasure() 재호출
- 일단 지금 상황에서는 requestLayout()을 사용할 필요가 없기 때문에 추가하지 않고 다음에 관련된 내용을 다루게 되면 더 자세한 설명과 함께 추가하는 과정을 알아보겠습니다(__)
* 글에 틀린 부분이 있으면 댓글 부탁드립니다 :D
728x90
'프로젝트 > Roulette Wheel View' 카테고리의 다른 글
[Roulette] 룰렛을 그리고 회전시키기 (3) - 회전 결과 리턴하기 (0) | 2021.03.01 |
---|---|
[Roulette] 룰렛을 그리고 회전시키기 (2) - 텍스트 쓰기, 애니메이션 적용 (0) | 2021.02.23 |
[Roulette] 룰렛을 그리고 회전시키기 (1) - 룰렛 그리기 (2) | 2021.02.19 |