diff options
author | cretin45 <cretin45@gmail.com> | 2015-11-13 16:51:43 -0800 |
---|---|---|
committer | cretin45 <cretin45@gmail.com> | 2015-11-23 12:10:32 -0800 |
commit | acab44fc939b4083ab7ec889b0c6d4fe0db00cca (patch) | |
tree | 6d7dd6d411404b804814ec4091e007f05dfd4ae5 /src/com/android/launcher3/AutoExpandTextView.java | |
parent | 35614fdc7d13179ba9cbc80f15eca6d63cf3229d (diff) | |
download | android_packages_apps_Trebuchet-acab44fc939b4083ab7ec889b0c6d4fe0db00cca.tar.gz android_packages_apps_Trebuchet-acab44fc939b4083ab7ec889b0c6d4fe0db00cca.tar.bz2 android_packages_apps_Trebuchet-acab44fc939b4083ab7ec889b0c6d4fe0db00cca.zip |
Reimplement the CM scrubber against the new Launcher
PS4: Implement RTL support
Change-Id: I4456d54b5924913d1b36e1cfa9a2269150f6fb3e
Diffstat (limited to 'src/com/android/launcher3/AutoExpandTextView.java')
-rw-r--r-- | src/com/android/launcher3/AutoExpandTextView.java | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/src/com/android/launcher3/AutoExpandTextView.java b/src/com/android/launcher3/AutoExpandTextView.java new file mode 100644 index 000000000..ea7ac896e --- /dev/null +++ b/src/com/android/launcher3/AutoExpandTextView.java @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2014 Grantland Chew + * Copyright (C) 2015 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3; + +import android.content.Context; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.Color; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.TextPaint; +import android.text.TextUtils; +import android.text.method.TransformationMethod; +import android.text.style.ForegroundColorSpan; +import android.util.AttributeSet; +import android.widget.TextView; + +import java.util.ArrayList; + +/** + * A single-line TextView that resizes it's letter spacing to fit the width of the view + * + * @author Grantland Chew <grantlandchew@gmail.com> + * @author Linus Lee <llee@cyngn.com> + */ +public class AutoExpandTextView extends TextView { + // How precise we want to be when reaching the target textWidth size + private static final float PRECISION = 0.01f; + + // Attributes + private float mPrecision; + private TextPaint mPaint; + private float[] mPositions; + + public static class HighlightedText { + public String mText; + public boolean mHighlight; + + public HighlightedText(String text, boolean highlight) { + mText = text; + mHighlight = highlight; + } + } + + public AutoExpandTextView(Context context) { + super(context); + init(context, null, 0); + } + + public AutoExpandTextView(Context context, AttributeSet attrs) { + super(context, attrs); + init(context, attrs, 0); + } + + public AutoExpandTextView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(context, attrs, defStyle); + } + + private void init(Context context, AttributeSet attrs, int defStyle) { + float precision = PRECISION; + + if (attrs != null) { + TypedArray ta = context.obtainStyledAttributes( + attrs, + R.styleable.AutofitTextView, + defStyle, + 0); + precision = ta.getFloat(R.styleable.AutofitTextView_precision, precision); + } + + mPaint = new TextPaint(); + setPrecision(precision); + } + + /** + * @return the amount of precision used to calculate the correct text size to fit within it's + * bounds. + */ + public float getPrecision() { + return mPrecision; + } + + /** + * Set the amount of precision used to calculate the correct text size to fit within it's + * bounds. Lower precision is more precise and takes more time. + * + * @param precision The amount of precision. + */ + public void setPrecision(float precision) { + if (precision != mPrecision) { + mPrecision = precision; + refitText(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void setLines(int lines) { + super.setLines(1); + refitText(); + } + + /** + * Only allow max lines of 1 + */ + @Override + public void setMaxLines(int maxLines) { + super.setMaxLines(1); + refitText(); + } + + /** + * Re size the font so the specified text fits in the text box assuming the text box is the + * specified width. + */ + private void refitText() { + CharSequence text = getText(); + + if (TextUtils.isEmpty(text)) { + return; + } + + TransformationMethod method = getTransformationMethod(); + if (method != null) { + text = method.getTransformation(text, this); + } + int targetWidth = getWidth() - getPaddingLeft() - getPaddingRight(); + if (targetWidth > 0) { + float high = 100; + float low = 0; + + mPaint.set(getPaint()); + mPaint.setTextSize(getTextSize()); + float letterSpacing = getLetterSpacing(text, mPaint, targetWidth, low, high, + mPrecision); + mPaint.setLetterSpacing(letterSpacing); + calculateSections(text); + + super.setLetterSpacing(letterSpacing); + } + } + + public float getPositionOfSection(int position) { + if (mPositions == null || position >= mPositions.length) { + return 0; + } + return mPositions[position]; + } + + /** + * This calculates the different horizontal positions of each character + */ + private void calculateSections(CharSequence text) { + mPositions = new float[text.length()]; + for (int i = 0; i < text.length(); i++) { + if (i == 0) { + mPositions[0] = mPaint.measureText(text, 0, 1) / 2; + } else { + // try to be lazy and just add the width of the newly added char + mPositions[i] = mPaint.measureText(text, i, i + 1) + mPositions[i - 1]; + } + } + } + + /** + * Sets the list of sections in the text view. This will take the first character of each + * and space it out in the text view using letter spacing + */ + public void setSections(ArrayList<HighlightedText> sections) { + mPositions = null; + if (sections == null || sections.size() == 0) { + setText(""); + return; + } + + Resources r = getContext().getResources(); + int highlightColor = r.getColor(R.color.app_scrubber_highlight_color); + int grayColor = r.getColor(R.color.app_scrubber_gray_color); + + SpannableStringBuilder builder = new SpannableStringBuilder(); + for (HighlightedText highlightText : sections) { + SpannableString spannable = new SpannableString(highlightText.mText.substring(0, 1)); + spannable.setSpan( + new ForegroundColorSpan(highlightText.mHighlight ? highlightColor : grayColor), + 0, spannable.length(), 0); + builder.append(spannable); + } + + setText(builder); + } + + private static float getLetterSpacing(CharSequence text, TextPaint paint, float targetWidth, + float low, float high, float precision) { + float mid = (low + high) / 2.0f; + paint.setLetterSpacing(mid); + + float measuredWidth = paint.measureText(text, 0, text.length()); + + if (high - low < precision) { + if (measuredWidth < targetWidth) { + return mid; + } else { + return low; + } + } else if (measuredWidth > targetWidth) { + return getLetterSpacing(text, paint, targetWidth, low, mid, precision); + } else if (measuredWidth < targetWidth) { + return getLetterSpacing(text, paint, targetWidth, mid, high, precision); + } else { + return mid; + } + } + + @Override + protected void onTextChanged(final CharSequence text, final int start, + final int lengthBefore, final int lengthAfter) { + super.onTextChanged(text, start, lengthBefore, lengthAfter); + refitText(); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + if (w != oldw) { + refitText(); + } + } +}
\ No newline at end of file |