TextView가 설치된 AutoSize
며칠 전 앱에서 TextView의 AutoSize를 사용할 기회가 생겼는데, 어떻게 설치하는지 신경 쓰여서 특별한 달력의 계절도 있어서 실제로 보기로 했어요!
(실제로 보니까 설치가 복잡하지 않아서 내용이 너무 짧아요.)
AutoSize 소개
먼저 TextView의 AutoSize를 간단히 확인하고 싶습니다.
TextView의 AutoSize는 TextView의 너비, 높이, 문자열 길이에 따라 자동으로 TextSize를 조정하는 기능입니다.
AutoSize에 필요한 설정은 다음 네 가지 요소입니다.
autoSizePreseSizes라는 것도 있는데 미리 정해진 사이즈로 TextSize를 조정하는 경우도 있지만, 이번에는 결정된 범위 내에서 지정된 절차에 따라 사이즈를 변경하는 다음과 같은 설정 방법을 주로 처리한다.
android:autoSizeMinTextSize
자동 조정 시 최소 TextSizeandroid:autoSizeMaxTextSize
자동 조정 시 최대 TextSizeandroid:autoSizeStepGranularity
여기에 설정된 TextSize를 사용하여 각각 확대 또는 축소android:autoSizeTextType
설정uniform
시 자동 조정, 설정none
시 자동 조정 안 함실제로 설정하면 ↓ 같은 동작이 됩니다.
GIF에 오를 수 있다면 올라가고 싶어요.
이 네 가지 요소만 설정하면 TextView의 AutoSize 자체는 간단하게 설정할 수 있습니다.
AutoSize 내부 설치
다음은 주제입니다. AutoSize의 내부 설치가 어떤지 보고 싶습니다.
TextView반부터 거슬러 올라가면
AppCompatTextViewAutoSizeHelper
반이 있습니다.이 분류에 대한 주석
Utility class which encapsulates the logic for the TextView auto-size text feature
이런 기록이 있다.
이 반에서 오토시즈 관련 처리가 이뤄졌기 때문에 이 반 내용을 보면 어떻게 시행됐는지 알 수 있다.
setupAutoSizeText()
AppCompatTextViewAutoSizeHelper
자세히 보니 setupAutoSizeText()
설치 방법이 있어 여기서부터 살펴보자. private boolean setupAutoSizeText() {
if (supportsAutoSizeText()
&& mAutoSizeTextType == TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM) {
// Calculate the sizes set based on minimum size, maximum size and step size if we do
// not have a predefined set of sizes or if the current sizes array is empty.
if (!mHasPresetAutoSizeValues || mAutoSizeTextSizesInPx.length == 0) {
// Calculate sizes to choose from based on the current auto-size configuration.
final int autoSizeValuesLength = ((int) Math.floor((mAutoSizeMaxTextSizeInPx
- mAutoSizeMinTextSizeInPx) / mAutoSizeStepGranularityInPx)) + 1;
final int[] autoSizeTextSizesInPx = new int[autoSizeValuesLength];
for (int i = 0; i < autoSizeValuesLength; i++) {
autoSizeTextSizesInPx[i] = Math.round(
mAutoSizeMinTextSizeInPx + (i * mAutoSizeStepGranularityInPx));
}
mAutoSizeTextSizesInPx = cleanupAutoSizePresetSizes(autoSizeTextSizesInPx);
}
mNeedsAutoSizeText = true;
} else {
mNeedsAutoSizeText = false;
}
return mNeedsAutoSizeText;
}
먼저 설정된
autoSizeMaxText
과autoSizeMinTextSize
사이의 차이autoSizeStepGranularity
를 나누고, 먼저 설정할 수 있는 TextSize의 개수를 계산한다.그리고
autoSizeMinTextSize
를 초기값으로 순서대로 autoSizeStepGranularity
를 더하면 범위를 설정할 수 있는 TextSize를 모두 그룹에 저장합니다.그런 다음 계산된 값을
cleanupAutoSizePresetSizes
에 전달하고 값이 Positive인지, 중복된 값이 있는지 확인합니다.그런 다음 계산된 값을
mAutoSizeTextSizesInPx
에 저장합니다.따라서 AutoSize 설치로 범위를 쉽게 설정할 수 있는 TextSize를 모두 계산한 후 저장하는 작업이 수행되었습니다.
autoSizeText()
다음은 본명
autoSizeText
방법을 보겠습니다. void autoSizeText() {
if (!isAutoSizeEnabled()) {
return;
}
if (mNeedsAutoSizeText) {
if (mTextView.getMeasuredHeight() <= 0 || mTextView.getMeasuredWidth() <= 0) {
return;
}
final boolean horizontallyScrolling = mImpl.isHorizontallyScrollable(mTextView);
final int availableWidth = horizontallyScrolling
? VERY_WIDE
: mTextView.getMeasuredWidth() - mTextView.getTotalPaddingLeft()
- mTextView.getTotalPaddingRight();
final int availableHeight = mTextView.getHeight() - mTextView.getCompoundPaddingBottom()
- mTextView.getCompoundPaddingTop();
if (availableWidth <= 0 || availableHeight <= 0) {
return;
}
synchronized (TEMP_RECTF) {
TEMP_RECTF.setEmpty();
TEMP_RECTF.right = availableWidth;
TEMP_RECTF.bottom = availableHeight;
final float optimalTextSize = findLargestTextSizeWhichFits(TEMP_RECTF);
if (optimalTextSize != mTextView.getTextSize()) {
setTextSizeInternal(TypedValue.COMPLEX_UNIT_PX, optimalTextSize);
}
}
}
// Always try to auto-size if enabled. Functions that do not want to trigger auto-sizing
// after the next layout pass should set this to false.
mNeedsAutoSizeText = true;
}
여기서 먼저 AutoSize가 설정한 TextView의 width와 Height를 획득했다.얻은 TextView의 크기는
findLargestTextSizeWhichFits
방법으로 전달됩니다. private int findLargestTextSizeWhichFits(RectF availableSpace) {
final int sizesCount = mAutoSizeTextSizesInPx.length;
if (sizesCount == 0) {
throw new IllegalStateException("No available text sizes to choose from.");
}
int bestSizeIndex = 0;
int lowIndex = bestSizeIndex + 1;
int highIndex = sizesCount - 1;
int sizeToTryIndex;
while (lowIndex <= highIndex) {
sizeToTryIndex = (lowIndex + highIndex) / 2;
if (suggestedSizeFitsInSpace(mAutoSizeTextSizesInPx[sizeToTryIndex], availableSpace)) {
bestSizeIndex = lowIndex;
lowIndex = sizeToTryIndex + 1;
} else {
highIndex = sizeToTryIndex - 1;
bestSizeIndex = highIndex;
}
}
return mAutoSizeTextSizesInPx[bestSizeIndex];
}
그리고
findLargestTextSizeWhichFits
에서는 TextView에 수용되는 가장 큰 TextSize를 계산합니다.내용으로 준비
lowIndex
와 highIndex
, lowIndexには
를 초기값으로 하고 1
대입highIndex
에서 계산한 setupAutoSizeText
의length-1(어쨌든 최대 TextSize의 Index)을 대체한다.그리고 플러스
mAutoSizeTextSizesInPx
와 lowIndex
를 2로 나눈 인덱스의 사이즈를 건네주고highIndex
크기가 큰지 작은지 판정한다.크기가 크면(TextView 초과) ->
suggestedSizeFitsInSpace
현재 테스트된 사이즈의 Index-1로 업데이트되며highIndex
이 값을 유지합니다.크기가 작으면(TextView에 수납) ->
bestSizeIndex
현재 크기bestSizeIndex
를 유지하고, lowIndex
를 현재 시도하는 사이즈의 Index+1으로 업데이트합니다.lowIndex
가 성립되었을 때 이 조작을 반복합니다.예.
mAutoSizeTextSizesInPx = [1, 2, 3, 4]
mAutoSizeTextSizesInPx.length = 4
の場合、
lowIndex = 1
highIndex = 3
でスタート。
(1 + 3) / 2 = 2
TextViewに収まる場合
lowIndex = 2 + 1 = 3
highIndex = 3
=> 収まる場合TextSizeは4(mAutoSizeTextSizesInPx[3])
=> 収まらない場合TextSizeは3(mAutoSizeTextSizesInPx[2])
TextViewに収まらない場合
highIndex = 2 - 1 = 1
lowIndex = 1
=> 収まる場合TextSizeは2(mAutoSizeTextSizesInPx[1])
=> 収まらない場合TextSizeは1(mAutoSizeTextSizesInPx[0])
TextSize를 이렇게 판정하여 AutoSize를 실현하였다.AutoSize 실행 시기
AutoSize가 TextSize를 어떻게 조정하는지 알았기 때문에 마지막으로 AutoSize가 어느 시기에 실행되었는지 확인하고 싶습니다.
lowIndex <= highIndex
에서 참고원을 거슬러 올라가 마침내autoSizeText()
에 도착했다.TextView에서 설정한 문자열이 변경될 때마다 AutoSize가 실행됩니다.
총결산
AppCompatTextView#onTextChanged()
에서 물론 이번에 본 것 외에도 많은 방법과 처리 방법이 있었지만 이번에는 기본적인 부분만 봤는데 의외로 간단하게 이루어져서 놀랐어요.그리고 AutoSize 실행 시기를 조사할 때 Buton도 autoSize를 사용할 수 있다는 것을 알아차렸다.(Buton에서 AutoSize를 사용하는 경우는 거의 없는 것 같습니다.)
설치 계기를 살펴보려고 했는데 그룹 린터Layout이 가로로 늘어선 TextView가 AutoSize를 할 수 있는지 없는지가 계기였지만, 이번 설치를 보니 맞춤 제작이 가능할 것 같았다.
가로로 늘어선 TextView가 AutoSize, 높이
AppCompatTextViewAutoSizeHelper
를 지정할 수 있도록 도전해 보고 싶습니다. 다음에 시도해 보세요!
Reference
이 문제에 관하여(TextView가 설치된 AutoSize), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/mkikuchi/articles/d2086901f13282텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)