2016-04-02 9 views
0

私はいくつかの名前を表示したいスピナーを持っています。 名前はsqliteクエリに基づいて取得します。どのように私は最長の名前の長さに基づいてフォントサイズを減らすことができますか?私が使用してスピナーのフォントサイズをandroidの最も長い値に基づいて自動調整する方法

textView.getText().length() ? 
+0

スピナーにフルネームが必要ですか?スピナーの膨張したテキストビューで 'android:singleLine = true'を使用しない場合。 – Kathi

答えて

0

ナイーブでチェックしなければならない:

  1. は最長の文字列を検索します。
  2. TextViewの最大サイズを測定します。
  3. TextViewに収まるテキストを測定します。 (TextPaintを使用すると、テキストテキストのメジャーメソッドが提供されます)。

アルゴリズムを理解するだけで済みます。このようなものかもしれない。

size = TextView.getWidth(); 
paint = new TextPaint(); 
paint.setTextSize(SOME_BIG_NUMBER); 
while(true){ 
    if (paint.measureText(longest_text) < size){ 
     break; 
    } else { 
     paint.setTextSize(paint.getTextSize() -1f); 
    } 
} 
result size = paint.getTextSize(); 

もう1つのアプローチは、AutoResizeTextViewを使用することです。データを設定したら、すべてのAutoResizeTextViewsを通過し、最小値を見つけてすべてのTextViewsに設定します。しかし、それは非常に高価で、ユーザーは描画に気付くでしょう。

public class AutoResizeTextView extends TextView { 

private interface SizeTester { 
    /** 
    * @param suggestedSize Size of text to be tested 
    * @param availableSpace available space in which text must fit 
    * 
    * @return an integer < 0 if after applying {@code suggestedSize} to 
    * text, it takes less space than {@code availableSpace}, > 0 
    * otherwise 
    */ 
    public int onTestSize(int suggestedSize, RectF availableSpace); 
} 

private RectF mTextRect = new RectF(); 

private RectF mAvailableSpaceRect; 

private SparseIntArray mTextCachedSizes; 

private TextPaint mPaint; 

private float mMaxTextSize; 

private float mSpacingMult = 1.0f; 

private float mSpacingAdd = 0.0f; 

private float mMinTextSize = 20; 

private int mWidthLimit; 

private Typeface mTypeFace; 

private static final int NO_LINE_LIMIT = -1; 
private int mMaxLines; 

private boolean mEnableSizeCache = true; 
private boolean mInitiallized; 

public AutoResizeTextView(Context context) { 
    super(context); 
    initialize(); 
    ArrayList<String> list = new ArrayList<>(); 
    int index = -1; 
    for (String st : list) { 
     index = index < st.length() ? st.length() :index; 
    } 

    TextPaint paint = new TextPaint(); 
    paint.measureText(list.get(index)); 
} 

public AutoResizeTextView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    initialize(); 
} 

public AutoResizeTextView(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
    initialize(); 
} 

private void initialize() { 
    mPaint = new TextPaint(getPaint()); 
    if (mTypeFace != null) { 
     mPaint.setTypeface(mTypeFace); 
    } 
    mMaxTextSize = getTextSize(); 
    mAvailableSpaceRect = new RectF(); 
    mTextCachedSizes = new SparseIntArray(); 
    if (mMaxLines == 0) { 
     // no value was assigned during construction 
     mMaxLines = NO_LINE_LIMIT; 
    } 
    mInitiallized = true; 
} 

@Override 
public void setText(final CharSequence text, BufferType type) { 
    super.setText(text, type); 
    adjustTextSize(text.toString()); 
} 

@Override 
public void setTextSize(float size) { 
    mMaxTextSize = size; 
    mTextCachedSizes.clear(); 
    adjustTextSize(getText().toString()); 
} 

@Override 
public void setMaxLines(int maxlines) { 
    super.setMaxLines(maxlines); 
    mMaxLines = maxlines; 
    reAdjust(); 
} 

public int getMaxLines() { 
    return mMaxLines; 
} 

@Override 
public void setSingleLine() { 
    super.setSingleLine(); 
    mMaxLines = 1; 
    reAdjust(); 
} 

@Override 
public void setSingleLine(boolean singleLine) { 
    super.setSingleLine(singleLine); 
    if (singleLine) { 
     mMaxLines = 1; 
    } else { 
     mMaxLines = NO_LINE_LIMIT; 
    } 
    reAdjust(); 
} 

@Override 
public void setLines(int lines) { 
    super.setLines(lines); 
    mMaxLines = lines; 
    reAdjust(); 
} 

@Override 
public void setTextSize(int unit, float size) { 
    Context c = getContext(); 
    Resources r; 

    if (c == null) { 
     r = Resources.getSystem(); 
    } else { 
     r = c.getResources(); 
    } 
    mMaxTextSize = TypedValue.applyDimension(unit, size, 
     r.getDisplayMetrics()); 
    mTextCachedSizes.clear(); 
    adjustTextSize(getText().toString()); 
} 

@Override 
public void setLineSpacing(float add, float mult) { 
    super.setLineSpacing(add, mult); 
    mSpacingMult = mult; 
    mSpacingAdd = add; 
} 

/** 
* Set the lower text size limit and invalidate the view 
* 
* @param minTextSize 
*/ 
public void setMinTextSize(float minTextSize) { 
    mMinTextSize = minTextSize; 
    reAdjust(); 
} 

private void reAdjust() { 
    adjustTextSize(getText().toString()); 
} 

private void adjustTextSize(String string) { 
    if (!mInitiallized) { 
     return; 
    } 
    int startSize = (int) mMinTextSize; 
    int heightLimit = getMeasuredHeight() - getCompoundPaddingBottom() 
     - getCompoundPaddingTop(); 
    mWidthLimit = getMeasuredWidth() - getCompoundPaddingLeft() 
     - getCompoundPaddingRight(); 
    if (mWidthLimit < 0) { 
     mWidthLimit = 0; 
    } 
    mAvailableSpaceRect.right = mWidthLimit; 
    mAvailableSpaceRect.bottom = heightLimit; 
    super.setTextSize(
     TypedValue.COMPLEX_UNIT_PX, 
     efficientTextSizeSearch(startSize, (int) mMaxTextSize, 
      mSizeTester, mAvailableSpaceRect)); 
} 

private final SizeTester mSizeTester = new SizeTester() { 
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 
    @Override 
    public int onTestSize(int suggestedSize, RectF availableSPace) { 
     mPaint.setTextSize(suggestedSize); 
     String text = getText().toString(); 
     boolean singleline = getMaxLines() == 1; 
     if (singleline) { 
      mTextRect.bottom = mPaint.getFontSpacing(); 
      mTextRect.right = mPaint.measureText(text); 
     } else { 
      StaticLayout layout = new StaticLayout(text, mPaint, 
       mWidthLimit, Layout.Alignment.ALIGN_NORMAL, mSpacingMult, 
       mSpacingAdd, true); 
      // return early if we have more lines 
      if (getMaxLines() != NO_LINE_LIMIT 
       && layout.getLineCount() > getMaxLines()) { 
       return 1; 
      } 
      mTextRect.bottom = layout.getHeight(); 
      int maxWidth = -1; 
      for (int i = 0; i < layout.getLineCount(); i++) { 
       if (maxWidth < layout.getLineWidth(i)) { 
        maxWidth = (int) layout.getLineWidth(i); 
       } 
      } 
      mTextRect.right = maxWidth; 
     } 

     mTextRect.offsetTo(0, 0); 
     if (availableSPace 
      .contains(mTextRect)) { // may be too small, don't worry we will find the best match 
      return -1; 
     } else { 
      if (mTextRect.bottom < availableSPace.bottom 
       && mTextRect.right > availableSPace.right) { 
       // hack :O 
       return -1; 
      } 
      // too big 
      return 1; 
     } 
    } 
}; 

/** 
* Enables or disables size caching, enabling it will improve performance 
* where you are animating a value inside TextView. This stores the font 
* size against getText().length() Be careful though while enabling it as 0 
* takes more space than 1 on some fonts and so on. 
* 
* @param enable enable font size caching 
*/ 
public void enableSizeCache(boolean enable) { 
    mEnableSizeCache = enable; 
    mTextCachedSizes.clear(); 
    adjustTextSize(getText().toString()); 
} 

private int efficientTextSizeSearch(int start, int end, 
    SizeTester sizeTester, RectF availableSpace) { 
    if (!mEnableSizeCache) { 
     return binarySearch(start, end, sizeTester, availableSpace); 
    } 
    String text = getText().toString(); 
    int key = text == null ? 0 : text.length(); 
    int size = mTextCachedSizes.get(key); 
    if (size != 0) { 
     return size; 
    } 
    size = binarySearch(start, end, sizeTester, availableSpace); 
    mTextCachedSizes.put(key, size); 
    return size; 
} 

private static int binarySearch(int start, int end, SizeTester sizeTester, 
    RectF availableSpace) { 
    int lastBest = start; 
    int lo = start; 
    int hi = end - 1; 
    int mid = 0; 
    while (lo <= hi) { 
     mid = (lo + hi) >>> 1; 
     int midValCmp = sizeTester.onTestSize(mid, availableSpace); 
     if (midValCmp < 0) { 
      lastBest = lo; 
      lo = mid + 1; 
     } else if (midValCmp > 0) { 
      hi = mid - 1; 
      lastBest = hi; 
     } else { 
      return mid; 
     } 
    } 
    // make sure to return last best 
    // this is what should always be returned 
    return lastBest; 
} 

@Override 
protected void onTextChanged(final CharSequence text, final int start, 
    final int before, final int after) { 
    super.onTextChanged(text, start, before, after); 
    reAdjust(); 
} 

@Override 
protected void onSizeChanged(int width, int height, int oldwidth, 
    int oldheight) { 
    mTextCachedSizes.clear(); 
    super.onSizeChanged(width, height, oldwidth, oldheight); 
    if (width != oldwidth || height != oldheight) { 
     reAdjust(); 
    } 
} 

@Override 
public void setTypeface(Typeface tf) { 
    super.setTypeface(tf); 
    mTypeFace = tf; 
    if (mInitiallized) { 
     mPaint.setTypeface(tf); 
     mTextCachedSizes.clear(); 
     reAdjust(); 
    } 
} 

@Override 
public CharSequence getAccessibilityClassName() { 
    return TextView.class.getName(); 
} 
} 

ベストアプローチは、これらのアプローチを組み合わせることです。最長のテキストを検索する。 AutoResizeTextViewを単純化してtextSizeのみを計算します。このサイズをtextViewsに設定します。

関連する問題