Skip to content

Commit

Permalink
Switched line clip prevention to maxLines for better ellipsizing.
Browse files Browse the repository at this point in the history
  • Loading branch information
nickbutcher committed Jul 13, 2016
1 parent 12587b6 commit 88716e2
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 25 deletions.
52 changes: 29 additions & 23 deletions app/src/main/java/io/plaidapp/ui/widget/BaselineGridTextView.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Paint;
import android.graphics.Rect;
import android.text.Layout;
import android.util.AttributeSet;
import android.util.TypedValue;

Expand All @@ -44,7 +42,7 @@ public class BaselineGridTextView extends FontTextView {

private float lineHeightMultiplierHint = 1f;
private float lineHeightHint = 0f;
private boolean clipToFullLines = false;
private boolean maxLinesByHeight = false;
private int extraTopPadding = 0;
private int extraBottomPadding = 0;

Expand All @@ -71,7 +69,7 @@ public BaselineGridTextView(Context context, AttributeSet attrs,
a.getFloat(R.styleable.BaselineGridTextView_lineHeightMultiplierHint, 1f);
lineHeightHint =
a.getDimensionPixelSize(R.styleable.BaselineGridTextView_lineHeightHint, 0);
clipToFullLines = a.getBoolean(R.styleable.BaselineGridTextView_clipToFullLines, false);
maxLinesByHeight = a.getBoolean(R.styleable.BaselineGridTextView_maxLinesByHeight, false);
a.recycle();

FOUR_DIP = TypedValue.applyDimension(
Expand All @@ -97,6 +95,15 @@ public void setLineHeightHint(float lineHeightHint) {
computeLineHeight();
}

public boolean getMaxLinesByHeight() {
return maxLinesByHeight;
}

public void setMaxLinesByHeight(boolean maxLinesByHeight) {
this.maxLinesByHeight = maxLinesByHeight;
requestLayout();
}

@Override
public int getCompoundPaddingTop() {
// include extra padding to place the first line's baseline on the grid
Expand All @@ -118,11 +125,13 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
height += ensureBaselineOnGrid();
height += ensureHeightGridAligned(height);
setMeasuredDimension(getMeasuredWidth(), height);
checkLineClipping(height);
checkMaxLines(height, MeasureSpec.getMode(heightMeasureSpec));
}

/**
* Ensures line height is a multiple of 4dp.
*/
private void computeLineHeight() {
// ensures line height is a multiple of 4dp
final Paint.FontMetricsInt fm = getPaint().getFontMetricsInt();
final int fontHeight = Math.abs(fm.ascent - fm.descent) + fm.leading;
final float desiredLineHeight = (lineHeightHint > 0)
Expand All @@ -134,8 +143,10 @@ private void computeLineHeight() {
setLineSpacing(baselineAlignedLineHeight - fontHeight, 1f);
}

/**
* Ensure that the first line of text sits on the 4dp grid.
*/
private int ensureBaselineOnGrid() {
// ensure that the first line of text sits on the 4dp grid
float baseline = getBaseline();
float gridAlign = baseline % FOUR_DIP;
if (gridAlign != 0) {
Expand All @@ -144,8 +155,10 @@ private int ensureBaselineOnGrid() {
return extraTopPadding;
}

/**
* Ensure that height is a multiple of 4dp.
*/
private int ensureHeightGridAligned(int height) {
// ensure that height is a multiple of 4dp
float gridOverhang = height % FOUR_DIP;
if (gridOverhang != 0) {
extraBottomPadding = (int) (FOUR_DIP - Math.ceil(gridOverhang));
Expand All @@ -154,21 +167,14 @@ private int ensureHeightGridAligned(int height) {
}

/**
* If measuring with an exact height then text can be clipped mid-line. Prevent this by setting
* a smaller {@code clipBounds} so that any partial lines are not drawn.
* When measured with an exact height, text can be vertically clipped mid-line. Prevent
* this by setting the {@code maxLines} property based on the available space.
*/
private void checkLineClipping(int height) {
if (!clipToFullLines) return;

Layout layout = getLayout();
if (layout == null) return;
final int paddingLeft = getCompoundPaddingLeft();
final int paddingTop = getCompoundPaddingTop();
int textHeight = height - paddingTop - getCompoundPaddingBottom();
int fullLines = (int) Math.floor(textHeight / getLineHeight());
Rect clip = new Rect(paddingLeft, paddingTop,
paddingLeft + layout.getWidth(),
paddingTop + (fullLines * getLineHeight()));
setClipBounds(clip);
private void checkMaxLines(int height, int heightMode) {
if (!maxLinesByHeight || heightMode != MeasureSpec.EXACTLY) return;

int textHeight = height - getCompoundPaddingTop() - getCompoundPaddingBottom();
int completeLines = (int) Math.floor(textHeight / getLineHeight());
setMaxLines(completeLines);
}
}
3 changes: 2 additions & 1 deletion app/src/main/res/layout/designer_news_story_item.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
android:layout_marginEnd="@dimen/padding_normal"
android:layout_weight="1"
android:breakStrategy="simple"
app:clipToFullLines="true"
android:ellipsize="end"
app:maxLinesByHeight="true"
tools:text="Amazing designer news story"
style="@style/Widget.Plaid.TilePrimary" />

Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/values/attrs_baseline_grid_text_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<declare-styleable name="BaselineGridTextView">
<attr name="lineHeightMultiplierHint" format="float" />
<attr name="lineHeightHint" />
<attr name="clipToFullLines" format="boolean" />
<attr name="maxLinesByHeight" format="boolean" />
</declare-styleable>

</resources>

0 comments on commit 88716e2

Please sign in to comment.