Shape Drawable
ShapeDrawable 은 2차원 그래픽을 동적으로 그려야할 때 요긴하게 사용할 수 있다. 프로그래밍을 통해서 기본적인 도형을 ShapeDrawable 상에 그릴 수 있고, 원하는 스타일 요소도 적용할 수 있다.
ShapeDrawable 은 Drawable 의 서브클래스이기 때문에 Drawable 가 사용되는 곳에서 ShapeDrawable 역시 사용 가능하다. 예를 들어 어떤 view 의 setBackgroundDrawable 메소드를 통해서 ShapeDrawable 을 배경으로 설정할 수 있다. 또한 커스텀 뷰 안에서 ShapeDrawble 을 그리게 하고, 커스텀 뷰를 레이아웃에 추가시킬 수도 있다.
ShapeDrawable 은 내부적으로 draw() 메소드를 가지고 있기 때문에 View 클래스를 상속하는 커스텀 뷰를 만든 뒤에 onDraw() 메소드에서 ShapeDrawable 의 draw() 메소드를 호출하여 2차원 그래픽을 그리는 뷰를 구현할 수도 있다. 다음은 그 예이다.
class CustomDrawableView(context: Context) : View(context) {
private val drawable: ShapeDrawable = run {
val x = 10
val y = 10
val width = 300
val height = 50
contentDescription = context.resources.getString(R.string.my_view_desc)
ShapeDrawable(OvalShape()).apply {
// If the color isn't set, the shape uses black as the default.
paint.color = 0xff74AC23.toInt()
// If the bounds aren't set, the shape can't be drawn.
setBounds(x, y, x + width, y + height)
}
}
override fun onDraw(canvas: Canvas) {
drawable.draw(canvas)
}
}
이제 코드상에서 다른 커스텀 뷰를 사용하는 것처럼 위 커스텀 뷰도 자유롭게 사용할 수 있다.
private lateinit var customDrawableView: CustomDrawableView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
customDrawableView = CustomDrawableView(this)
setContentView(customDrawableView)
}
ShapeDrawable 은 android.graphics.drawable 패키지의 드로어블 클래스들과 같이 public method 들을 통해서 컬러, 투명도, dither, 불투명도 등을 적용할 수 있다.
ShapeDrawable 은 기본적으로 Shape 객체를 전달받으며, screen 상엣의 해당 Shape 객체를 관리한다. 어떤 Shape 도 주어지지 않는다면 기본적으로 RectShape 를 취한다.
ShapeDrawable 왜 사용할까?
Canvas 객체를 이용하면 ShapeDrawable 을 사용하지 않고도 다양한 2차원 도형을 그릴 수가 있는데 왜 ShapeDrawable 을 굳이 사용하는 걸까? ShapeDrawable 을 사용하면 공통적으로 재사용 될 수 있는 어떤 모양(Shape)에 대해서 해당 Shape 를 그리는 작업을 독립적인 객체로 분리해서 작성할 수 있기 때문이다. Canvas 의 메소드를 순차적으로 작성한 코드의 형태는 imperative 하기 때문에 해당 코드들의 최종적으로 나타내고자 하는 형태를 한 눈에 알아보기 어렵다. 어떤 형태를 ShapeDrawable 로 만들어서 그리면 해당 클래스의 이름을 통해 이 드로어블이 어떤 형태를 그리고자 하는 건지 한 눈에 알아보기 쉽기 때문에 사용하는 것 같다.
예제
class SquareRoundedDrawable : ShapeDrawable {
private val cornerRadius = 18f
private val fillPaint = paint
var checked = false
constructor(view: View) : super(RectShape()) {
fillPaint.isAntiAlias = true
}
override fun onDraw(shape: Shape, canvas: Canvas, fillPaint: Paint) {
canvas.drawRoundRect(RectF(0f, 0f, shape.width, shape.height), cornerRadius, cornerRadius, fillPaint)
}
fun setFillColor(color: Int) {
fillPaint.color = color
}
}
...
val shape = SquareRoundedDrawable(view)
view.setBackgroundDrawable(shape)
참고자료
- https://developer.android.com/guide/topics/graphics/drawables#shape-drawable
- Do it! 안드로이드 앱 프로그래밍