Skip to content

Commit

Permalink
TitleFlowIndicator supports custom typefaces
Browse files Browse the repository at this point in the history
Either using android:typeface and android:textStyle or app:customTypeface if one is provided with the app.
  • Loading branch information
pakerfeldt committed Nov 1, 2011
1 parent 270cdc4 commit 6befb6b
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 28 deletions.
Binary file added viewflow-example/assets/fonts/Antic.ttf
Binary file not shown.
1 change: 1 addition & 0 deletions viewflow-example/res/layout/title_layout.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
android:id="@+id/viewflowindic" android:layout_height="wrap_content"
android:layout_width="fill_parent"
app:footerLineHeight="2dp"
app:customTypeface="fonts/Antic.ttf"
app:footerTriangleHeight="10dp" app:textColor="#FFFFFFFF" app:selectedColor="#FFFFC445" app:footerColor="#FFFFC445" app:titlePadding="10dp" app:textSize="11dp" app:selectedSize="12dp" android:layout_marginTop="10dip" app:clipPadding="5dp"></org.taptwo.android.widget.TitleFlowIndicator>

</LinearLayout>
Expand Down
1 change: 1 addition & 0 deletions viewflow/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,6 @@
<attr name="footerLineHeight" format="dimension" />
<attr name="footerColor" format="color" />
<attr name="footerTriangleHeight" format="dimension" />
<attr name="customTypeface" format="string" />
</declare-styleable>
</resources>
90 changes: 62 additions & 28 deletions viewflow/src/org/taptwo/android/widget/TitleFlowIndicator.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;
Expand Down Expand Up @@ -64,6 +65,13 @@ public class TitleFlowIndicator extends TextView implements FlowIndicator {
private float clipPadding;
private float footerLineHeight;

/* These are hardcoded just like in TextView */
private static final int SANS = 1;
private static final int SERIF = 2;
private static final int MONOSPACE = 3;

private Typeface typeface;

/**
* Default constructor
*/
Expand All @@ -81,7 +89,12 @@ public TitleFlowIndicator(Context context) {
public TitleFlowIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
// Retrieve styles attributs

int typefaceIndex = attrs.getAttributeIntValue("http://schemas.android.com/apk/res/android", "typeface", 0);
int textStyleIndex = attrs.getAttributeIntValue("http://schemas.android.com/apk/res/android", "textStyle", 0);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TitleFlowIndicator);

String customTypeface = a.getString(R.styleable.TitleFlowIndicator_customTypeface);
// Retrieve the colors to be used for this view and apply them.
int footerColor = a.getColor(R.styleable.TitleFlowIndicator_footerColor, FOOTER_COLOR);
footerLineHeight = a.getDimension(R.styleable.TitleFlowIndicator_footerLineHeight, FOOTER_LINE_HEIGHT);
Expand All @@ -94,6 +107,13 @@ public TitleFlowIndicator(Context context, AttributeSet attrs) {
titlePadding = a.getDimension(R.styleable.TitleFlowIndicator_titlePadding, TITLE_PADDING);
clipPadding = a.getDimension(R.styleable.TitleFlowIndicator_clipPadding, CLIP_PADDING);
initDraw(textColor, textSize, selectedColor, selectedBold, selectedSize, footerLineHeight, footerColor);

if (customTypeface != null)
typeface = Typeface.createFromAsset(context.getAssets(), customTypeface);
else
typeface = getTypefaceByIndex(typefaceIndex);
typeface = Typeface.create(typeface, textStyleIndex);

}

/**
Expand Down Expand Up @@ -129,10 +149,10 @@ protected void onDraw(Canvas canvas) {

// Calculate views bounds
ArrayList<Rect> bounds = calculateAllBounds(paintText);

// If no value then add a fake one
int count = (viewFlow != null && viewFlow.getAdapter() != null) ? viewFlow.getAdapter().getCount() : 1;

// Verify if the current view must be clipped to the screen
Rect curViewBound = bounds.get(currentPosition);
int curViewWidth = curViewBound.right - curViewBound.left;
Expand All @@ -144,7 +164,7 @@ protected void onDraw(Canvas canvas) {
// Try to clip to the screen (right side)
clipViewOnTheRight(curViewBound, curViewWidth);
}

// Left views starting from the current position
if (currentPosition > 0) {
for (int iLoop = currentPosition - 1; iLoop >= 0; iLoop--) {
Expand All @@ -153,21 +173,21 @@ protected void onDraw(Canvas canvas) {
// Si left side is outside the screen
if (bound.left < 0) {
// Try to clip to the screen (left side)
clipViewOnTheLeft(bound, w);
clipViewOnTheLeft(bound, w);
// Except if there's an intersection with the right view
if (iLoop < count - 1 && currentPosition != iLoop) {
Rect rightBound = bounds.get(iLoop + 1);
// Intersection
if (bound.right + TITLE_PADDING > rightBound.left) {
bound.left = rightBound.left - (w + (int)titlePadding);
bound.left = rightBound.left - (w + (int) titlePadding);
}
}
}
}
}
// Right views starting from the current position
if (currentPosition < count - 1) {
for (int iLoop = currentPosition + 1 ; iLoop < count; iLoop++) {
for (int iLoop = currentPosition + 1; iLoop < count; iLoop++) {
Rect bound = bounds.get(iLoop);
int w = bound.right - bound.left;
// If right side is outside the screen
Expand All @@ -179,7 +199,7 @@ protected void onDraw(Canvas canvas) {
Rect leftBound = bounds.get(iLoop - 1);
// Intersection
if (bound.left - TITLE_PADDING < leftBound.right) {
bound.left = leftBound.right + (int)titlePadding;
bound.left = leftBound.right + (int) titlePadding;
}
}
}
Expand All @@ -199,25 +219,26 @@ protected void onDraw(Canvas canvas) {
if (Math.abs(middle - (getWidth() / 2)) < 20) {
paint = paintSelected;
}
canvas.drawText(title, bound.left, bound.bottom, paint);
paint.setTypeface(typeface);
canvas.drawText(title, bound.left, bound.bottom, paint);
}
}

// Draw the footer line
path = new Path();
int coordY = getHeight()-1;
coordY -= (footerLineHeight%2 == 1) ? footerLineHeight/2 : footerLineHeight/2-1;
int coordY = getHeight() - 1;
coordY -= (footerLineHeight % 2 == 1) ? footerLineHeight / 2 : footerLineHeight / 2 - 1;
path.moveTo(0, coordY);
path.lineTo(getWidth(), coordY);
path.close();
canvas.drawPath(path, paintFooterLine);
// Draw the footer triangle
path.close();
canvas.drawPath(path, paintFooterLine);
// Draw the footer triangle
path = new Path();
path.moveTo(getWidth() / 2, getHeight()-footerLineHeight-footerTriangleHeight);
path.lineTo(getWidth() / 2 + footerTriangleHeight, getHeight()-footerLineHeight);
path.lineTo(getWidth() / 2 - footerTriangleHeight, getHeight()-footerLineHeight);
path.close();
canvas.drawPath(path, paintFooterTriangle);
path.moveTo(getWidth() / 2, getHeight() - footerLineHeight - footerTriangleHeight);
path.lineTo(getWidth() / 2 + footerTriangleHeight, getHeight() - footerLineHeight);
path.lineTo(getWidth() / 2 - footerTriangleHeight, getHeight() - footerLineHeight);
path.close();
canvas.drawPath(path, paintFooterTriangle);

}

Expand All @@ -230,7 +251,7 @@ protected void onDraw(Canvas canvas) {
* width of the view.
*/
private void clipViewOnTheRight(Rect curViewBound, int curViewWidth) {
curViewBound.right = getLeft() + getWidth() - (int)clipPadding;
curViewBound.right = getLeft() + getWidth() - (int) clipPadding;
curViewBound.left = curViewBound.right - curViewWidth;
}

Expand All @@ -243,7 +264,7 @@ private void clipViewOnTheRight(Rect curViewBound, int curViewWidth) {
* width of the view.
*/
private void clipViewOnTheLeft(Rect curViewBound, int curViewWidth) {
curViewBound.left = 0 + (int)clipPadding;
curViewBound.left = 0 + (int) clipPadding;
curViewBound.right = curViewWidth;
}

Expand Down Expand Up @@ -285,7 +306,7 @@ private Rect calcBounds(int index, Paint paint) {
// Calculate the text bounds
Rect bounds = new Rect();
bounds.right = (int) paint.measureText(title);
bounds.bottom = (int) (paint.descent()-paint.ascent());
bounds.bottom = (int) (paint.descent() - paint.ascent());
return bounds;
}

Expand Down Expand Up @@ -351,16 +372,15 @@ public void setViewFlow(ViewFlow view) {
public void setTitleProvider(TitleProvider provider) {
titleProvider = provider;
}

/*
* (non-Javadoc)
*
* @see android.view.View#onMeasure(int, int)
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measureWidth(widthMeasureSpec),
measureHeight(heightMeasureSpec));
setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
}

/**
Expand All @@ -376,8 +396,7 @@ private int measureWidth(int measureSpec) {
int specSize = MeasureSpec.getSize(measureSpec);

if (specMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException(
"ViewFlow can only be used in EXACTLY mode.");
throw new IllegalStateException("ViewFlow can only be used in EXACTLY mode.");
}
result = specSize;
return result;
Expand All @@ -403,10 +422,25 @@ private int measureHeight(int measureSpec) {
else {
// Calculate the text bounds
Rect bounds = new Rect();
bounds.bottom = (int) (paintText.descent()-paintText.ascent());
result = bounds.bottom - bounds.top + (int)footerTriangleHeight + (int)footerLineHeight + 10;
bounds.bottom = (int) (paintText.descent() - paintText.ascent());
result = bounds.bottom - bounds.top + (int) footerTriangleHeight + (int) footerLineHeight + 10;
return result;
}
return result;
}

private Typeface getTypefaceByIndex(int typefaceIndex) {
switch (typefaceIndex) {
case SANS:
return Typeface.SANS_SERIF;

case SERIF:
return Typeface.SERIF;

case MONOSPACE:
return Typeface.MONOSPACE;
default:
return Typeface.DEFAULT;
}
}
}

0 comments on commit 6befb6b

Please sign in to comment.