https://github.com/tlaabs/TimetableView
시간표를 구현하기 위해 위의 라이브러리를 선택 했으나, 위의 라이브러리에는 몇 가지 지원 안되는 기능이 있었다.
- 테이블 헤더 높이 조절 불가
- 폰트 및 글자 크기 조절 불가
- 시간표 색상 선택 불가 (기본 컬러 조합으로 세팅 되어있음)
위의 기능들을 추가하기 위해 라이브러리 클래스를 상속받은 후 구현해보려고 했지만, 주요 메소드들이 private로 선언 되어있어서 상속으론 해결 불가
라이브러리 코드가 별로 길지 않아서 복사해서 새로 클래스를 만들기로 결정
수정 코드
1. 테이블 헤더 높이 조절
/** 테이블 헤더(맨 윗 줄) 생성 메소드 */
private fun createTableHeader() {
val tableRow = TableRow(context)
tableRow.layoutParams = createTableLayoutParam()
for (i in 0 until columnCount) {
val tv = TextView(context)
if (i == 0) { // 제일 첫 번째 칸은 모서리칸
tv.layoutParams = createTableRowParam(sideCellWidth, LayoutParams.WRAP_CONTENT) // -> 수정 1
} else {
tv.layoutParams = createTableRowParam(LayoutParams.WRAP_CONTENT) // -> 수정 2
}
tv.setTextColor(resources.getColor(R.color.colorHeaderText))
tv.setTextSize(
TypedValue.COMPLEX_UNIT_DIP,
DEFAULT_HEADER_FONT_SIZE_DP.toFloat()
)
tv.text = headerTitle[i]
tv.gravity = Gravity.CENTER
tableRow.addView(tv)
}
tableHeader!!.addView(tableRow)
}
테이블의 헤더는 createTableHeader() 라는 메소드에서 생성되도록 되어있었다. 구조를 보니 TableRow에다가 TextView를 삽입하는 방식이었다.
즉, TextView의 높이에 따라 테이블 헤더의 높이가 결정되는 것
기존엔 cellHeight로 제목이 아닌 다른 칸들의 높이와 동일하게 생성하도록 되어 있었다. 이를 WRAP_CONTENT로 바꿔서 테이블 헤더의 높이만 TextView의 높이에 맞추도록 변경
2. 폰트 및 글자 크기 조절
@SuppressLint("ResourceAsColor")
private fun add(schedules: ArrayList<Schedule>, specIdx: Int) {
val count = if (specIdx < 0) ++stickerCount else specIdx
val sticker = Sticker()
for (schedule in schedules) {
val tv = TextView(context)
val param = createStickerParam(schedule)
tv.layoutParams = param
tv.setPadding(10, 0, 10, 0)
/**
* TextView의 BufferType를 SPANNABLE로 설정
* 미리 text를 지정해놓고 그 후에 SpannableStringBUilder로 바꿔줘야 스타일이 바뀜
* */
val str = """
${schedule.classTitle}
${schedule.classPlace}
""".trimIndent()
tv.setText(str, TextView.BufferType.SPANNABLE) // 중요 !!
val builder = SpannableStringBuilder(str)
builder.setSpan(StyleSpan(Typeface.BOLD), 0, schedule.classTitle.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
builder.setSpan(AbsoluteSizeSpan(dp2Px(10)), schedule.classTitle.length+1, str.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
tv.text = builder
tv.setTextColor(com.example.lab.R.color.black_gray)
tv.setTextSize(
TypedValue.COMPLEX_UNIT_DIP,
DEFAULT_STICKER_FONT_SIZE_DP.toFloat()
)
tv.setOnClickListener {
if (stickerSelectedListener != null) stickerSelectedListener!!.OnStickerSelected(
count,
schedules
)
}
sticker.addTextView(tv)
sticker.addSchedule(schedule)
stickers[count] = sticker
stickerBox!!.addView(tv)
}
setStickerColor()
}
위의 메소드는 시간표에 수업(스티커)를 추가하는 메소드다. 수업의 제목과 장소가 TextView 하나에 들어가는 구조여서 폰트나 크기를 따로 변경할 수가 없었다.
TextView의 일부분만 변경할 땐 SpannableStringBuilder를 많이 사용한다.
SpannableStringBuilder로 TextView의 텍스트를 변경할 땐 TextView의 buffertype 속성이 spannable로 되어있어야하는데, 동적으로 생성하다보니 xml 상에서 지정할 수 없는 상황 TextView의 속성 메소드로 buffertype을 지정할 수 있을 줄 알고 찾아봤는데 없었다.
따로 지정 메소드가 있는게 아니라 setText에서 파라미터로 bufferType을 전달받는 형태로 되어있었다.
임의의 텍스트를 할당해주고, bufferType을 지정해준다.
val builder = SpannableStringBuilder(str)
builder.setSpan(StyleSpan(Typeface.BOLD), 0, schedule.classTitle.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
builder.setSpan(AbsoluteSizeSpan(dp2Px(10)), schedule.classTitle.length+1, str.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
tv.text = builder
❗위와 같이 bufferType을 먼저 지정하고 그 후 SpannableStringBuilder로 변경해줘야한다 ❗
'안드로이드 > 이론' 카테고리의 다른 글
[ 안드로이드 ] 해상도 대응, 다양한 화면 크기 지원 (0) | 2023.01.31 |
---|---|
[ 안드로이드 ] local.properties를 이용하여 API Key 안전하게 보관하기 (0) | 2023.01.25 |
[ 안드로이드 ] Fragment Add시 밑의 Fragment 클릭되는 문제 (0) | 2022.11.16 |
[ 안드로이드 ] Livedata Observer 등록하자 마자 호출되는 경우 or 중복 호출 (0) | 2022.11.14 |
[ 안드로이드 ] BottomSheetDialog에서 Fragment로 값 전달 (0) | 2022.10.03 |