font-size 안드로이드 타이틀 - Android 용 TextView 자동 맞춤 설정





7 Answers

나는 M-WaJeEh의 답을 수정하여 양면에 복합 드로어 블을 고려했습니다.

getCompoundPaddingXXXX() 메소드 padding of the view + drawable space 반환 padding of the view + drawable space . 다음을 참조하십시오. TextView.getCompoundPaddingLeft()

문제 : 텍스트에 사용할 수있는 TextView 공간의 너비와 높이를 측정합니다. 드로어 블 크기를 고려하지 않으면 무시되며 텍스트는 드로어 블과 겹치게됩니다.

업데이트 된 세그먼트 adjustTextSize(String) :

private void adjustTextSize(final String text) {
  if (!mInitialized) {
    return;
  }
  int heightLimit = getMeasuredHeight() - getCompoundPaddingBottom() - getCompoundPaddingTop();
  mWidthLimit = getMeasuredWidth() - getCompoundPaddingLeft() - getCompoundPaddingRight();

  mAvailableSpaceRect.right = mWidthLimit;
  mAvailableSpaceRect.bottom = heightLimit;

  int maxTextSplits = text.split(" ").length;
  AutoResizeTextView.super.setMaxLines(Math.min(maxTextSplits, mMaxLines));

  super.setTextSize(
      TypedValue.COMPLEX_UNIT_PX,
      binarySearch((int) mMinTextSize, (int) mMaxTextSize,
                   mSizeTester, mAvailableSpaceRect));
}
글자 위치 toolbar

배경

많은 경우 TextView의 글꼴을 주어진 경계에 자동으로 맞추어야합니다.

문제

슬프게도이 문제 ( here , here , here )에 대해 많은 스레드와 게시물 (및 제안 된 솔루션)이 있지만 실제로는 아무 문제가 없습니다.

그게 바로 내가 실제 거래를 찾을 때까지 각자를 테스트하기로 결정한 이유입니다.

그런 textView의 요구 사항은 다음과 같아야한다고 생각합니다.

  1. 글꼴, 활자체, 스타일 및 문자 세트 사용을 허용해야합니다.

  2. 너비와 높이를 모두 처리해야합니다.

  3. 한계로 인해 텍스트가 적합하지 않으면 절단하지 않습니다. 예를 들어 텍스트가 너무 깁니다. 사용 가능한 크기가 너무 작습니다. 그러나 원하는 경우 수평 / 수직 스크롤 바를 요청할 수 있습니다.

  4. 여러 줄 또는 한 줄을 허용해야합니다. 멀티 라인의 경우, 최대 및 최소 라인을 허용하십시오.

  5. 계산 속도가 느려서는 안됩니다. 최상의 크기를 찾는 데 루프를 사용합니까? 적어도 최적화하고 매번 샘플링을 1 씩 증가시키지 마십시오.

  6. 멀티 라인의 경우, 크기를 조정하거나 더 많은 라인을 사용하거나, "\ n"문자를 사용하여 라인을 직접 선택할 수 있어야합니다.

내가 시도한 것

나는 많은 샘플 (링크에 대한 것들을 포함하여, 나는 썼다.)을 시도해 보았고, 나는 또한 그것들을 수정하기 위해 시도했다.

TextView가 자동으로 올바르게 표시되는지 시각적으로 확인할 수있는 샘플 프로젝트를 만들었습니다.

현재 샘플 프로젝트는 텍스트 (영어 알파벳 + 숫자)와 textView의 크기를 무작위로 추출하여 한 줄로 남겨 둡니다. 그러나이 방법도 제가 시도한 샘플에서는 잘 작동하지 않습니다.

코드는 다음과 같습니다 ( here 에서도 사용 가능).

파일 res/layout/activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
  android:layout_height="match_parent" tools:context=".MainActivity">
  <Button android:id="@+id/button1" android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true" android:text="Button" />
  <FrameLayout android:layout_width="match_parent"
    android:layout_height="wrap_content" android:layout_above="@+id/button1"
    android:layout_alignParentLeft="true" android:background="#ffff0000"
    android:layout_alignParentRight="true" android:id="@+id/container"
    android:layout_alignParentTop="true" />

</RelativeLayout>

src/.../MainActivity.java 파일

public class MainActivity extends Activity
  {
  private final Random        _random            =new Random();
  private static final String ALLOWED_CHARACTERS ="qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890";

  @Override
  protected void onCreate(final Bundle savedInstanceState)
    {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    final ViewGroup container=(ViewGroup)findViewById(R.id.container);
    findViewById(R.id.button1).setOnClickListener(new OnClickListener()
      {
        @Override
        public void onClick(final View v)
          {
          container.removeAllViews();
          final int maxWidth=container.getWidth();
          final int maxHeight=container.getHeight();
          final FontFitTextView fontFitTextView=new FontFitTextView(MainActivity.this);
          final int width=_random.nextInt(maxWidth)+1;
          final int height=_random.nextInt(maxHeight)+1;
          fontFitTextView.setLayoutParams(new LayoutParams(width,height));
          fontFitTextView.setSingleLine();
          fontFitTextView.setBackgroundColor(0xff00ff00);
          final String text=getRandomText();
          fontFitTextView.setText(text);
          container.addView(fontFitTextView);
          Log.d("DEBUG","width:"+width+" height:"+height+" text:"+text);
          }
      });
    }

  private String getRandomText()
    {
    final int textLength=_random.nextInt(20)+1;
    final StringBuilder builder=new StringBuilder();
    for(int i=0;i<textLength;++i)
      builder.append(ALLOWED_CHARACTERS.charAt(_random.nextInt(ALLOWED_CHARACTERS.length())));
    return builder.toString();
    }
  }

질문

아무도 실제로 작동하는 일반적인 문제에 대한 해결책을 알고 있습니까?

심지어 필자가 썼던 것보다 훨씬 적은 기능을 가진 솔루션조차도, 예를 들어 일정한 수의 텍스트 행을 가지며 그 크기에 따라 글꼴을 조정하지만, 이상한 결함을 가지지 않고 텍스트도 갖지 않는 솔루션 사용 가능한 공간보다 크거나 작습니다.

GitHub 프로젝트

이것이 중요한 TextView이기 때문에 모든 사람들이 쉽게 사용할 수 있고 here 기여할 수 있도록 라이브러리를 게시하기로 결정했습니다.




내 요구 사항은 다음과 같습니다.

  • ScalableTextView를 클릭하십시오.
  • listActivity를 열고 다양한 길이의 문자열 항목을 표시합니다.
  • 목록에서 텍스트를 선택하십시오.
  • 텍스트를 다시 다른 활동의 ScalableTextView로 설정합니다.

필자는 링크를 참조했습니다 : TextView Text를 Bound (주석 포함) 내에서 자동으로 조정 하고 DialogTitle.java

제공된 솔루션이 좋고 간단하지만 텍스트 상자의 크기를 동적으로 변경하지는 않습니다. 목록보기에서 선택한 텍스트 길이가 ScalableTextView 의 기존 텍스트 길이보다 큰 경우 효과적 입니다. ScalableTextView 의 기존 텍스트보다 길이가 짧은 텍스트를 선택하면 더 작은 크기의 텍스트를 표시하는 텍스트 크기가 증가하지 않습니다.

ScalableTextView.java를 수정하여 텍스트 길이를 기준으로 텍스트 크기를 재조정했습니다. 여기 내 ScalableTextView.java

public class ScalableTextView extends TextView
{
float defaultTextSize = 0.0f;

public ScalableTextView(Context context, AttributeSet attrs, int defStyle)
{
    super(context, attrs, defStyle);
    setSingleLine();
    setEllipsize(TruncateAt.END);
    defaultTextSize = getTextSize();
}

public ScalableTextView(Context context, AttributeSet attrs)
{
    super(context, attrs);
    setSingleLine();
    setEllipsize(TruncateAt.END);
    defaultTextSize = getTextSize();
}

public ScalableTextView(Context context)
{
    super(context);
    setSingleLine();
    setEllipsize(TruncateAt.END);
    defaultTextSize = getTextSize();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
    setTextSize(TypedValue.COMPLEX_UNIT_PX, defaultTextSize);
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    final Layout layout = getLayout();
    if (layout != null)
    {
        final int lineCount = layout.getLineCount();
        if (lineCount > 0)
        {
            int ellipsisCount = layout.getEllipsisCount(lineCount - 1);
            while (ellipsisCount > 0)
            {
                final float textSize = getTextSize();

                // textSize is already expressed in pixels
                setTextSize(TypedValue.COMPLEX_UNIT_PX, (textSize - 1));

                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
                ellipsisCount = layout.getEllipsisCount(lineCount - 1);
            }
        }
    }
}
}

해피 코딩 ....




이 문제에 대한 공식적인 해결책이 있습니다. Android O에서 소개 된 TextViews 자동 크기 조정은 Support Library 26에서 사용할 수 있으며 Android 4.0까지 역 호환됩니다.

https://developer.android.com/preview/features/autosizing-textview.html

https://.com/a/42940171/47680 에이 정보가 포함 된 이유가 관리자에 의해 삭제되었는지 잘 모르겠습니다.







이 시도

TextWatcher changeText = new TextWatcher() {
     @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                tv3.setText(et.getText().toString());
                tv3.post(new Runnable() {           
                    @Override
                    public void run() {
                    while(tv3.getLineCount() >= 3){                     
                            tv3.setTextSize((tv3.getTextSize())-1);                     
                        }
                    }
                });
            }

            @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

            @Override public void afterTextChanged(Editable s) { }
        };



@Malachiasz에 의해 설명 된 문제에 대한 빠른 수정

자동 크기 조정 클래스에서이 문제에 대한 맞춤 지원을 추가하여 문제를 해결했습니다.

public void setTextCompat(final CharSequence text) {
    setTextCompat(text, BufferType.NORMAL);
}

public void setTextCompat(final CharSequence text, BufferType type) {
    // Quick fix for Android Honeycomb and Ice Cream Sandwich which sets the text only on the first call
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1 &&
        Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
        super.setText(DOUBLE_BYTE_WORDJOINER + text + DOUBLE_BYTE_WORDJOINER, type);
    } else {
        super.setText(text, type);
    }
}

@Override
public CharSequence getText() {
    String originalText = super.getText().toString();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1 &&
        Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
        // We try to remove the word joiners we added using compat method - if none found - this will do nothing.
        return originalText.replaceAll(DOUBLE_BYTE_WORDJOINER, "");
    } else {
        return originalText;
    }
}

yourView.setTextCompat(newTextValue)대신 전화 하세요.yourView.setText(newTextValue)




Android O 이후로 xml의 텍스트 크기를 자동으로 조정할 수 있습니다.

https://developer.android.com/preview/features/autosizing-textview.html

  <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:autoSizeTextType="uniform"
    app:autoSizeMinTextSize="12sp"
    app:autoSizeMaxTextSize="100sp"
    app:autoSizeStepGranularity="2sp"
  />

Android O를 사용하면 TextView의 특성과 경계를 기반으로 레이아웃을 채우기 위해 텍스트 크기가 자동으로 확장되거나 축소되도록 TextView에 지시 할 수 있습니다. 이 설정을 사용하면 동적 콘텐츠로 여러 화면에서 텍스트 크기를보다 쉽게 ​​최적화 할 수 있습니다.

Support Library 26.0 Beta는 Android O 이전의 Android 버전을 실행하는 기기의 TextView 자동 크기 조정 기능을 완벽하게 지원합니다.이 라이브러리는 Android 4.0 (API 레벨 14) 이상에 대한 지원을 제공합니다. android.support.v4.widget 패키지에는 이전 버전과 호환되는 기능에 액세스하기위한 TextViewCompat 클래스가 포함되어 있습니다.




Related