Skip to content

Commit f8d595f

Browse files
committed
Allow drawing title underline on top. Closes JakeWharton#126.
1 parent 3392124 commit f8d595f

File tree

6 files changed

+131
-11
lines changed

6 files changed

+131
-11
lines changed

library/res/values/vpi__attrs.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,11 @@
9191
<attr name="footerIndicatorUnderlinePadding" format="dimension" />
9292
<!-- Padding between the bottom of the title and the footer. -->
9393
<attr name="footerPadding" format="dimension" />
94+
<!-- Position of the line. -->
95+
<attr name="linePosition">
96+
<enum name="bottom" value="0"/>
97+
<enum name="top" value="1"/>
98+
</attr>
9499
<!-- Color of the selected title. -->
95100
<attr name="selectedColor" />
96101
<!-- Whether or not the selected item is displayed as bold. -->

library/res/values/vpi__defaults.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
<dimen name="default_title_indicator_footer_indicator_height">4dp</dimen>
3939
<dimen name="default_title_indicator_footer_indicator_underline_padding">20dp</dimen>
4040
<dimen name="default_title_indicator_footer_padding">7dp</dimen>
41+
<integer name="default_title_indicator_line_position">0</integer>
4142
<color name="default_title_indicator_selected_color">#FFFFFFFF</color>
4243
<bool name="default_title_indicator_selected_bold">true</bool>
4344
<color name="default_title_indicator_text_color">#BBFFFFFF</color>

library/src/com/viewpagerindicator/TitlePageIndicator.java

Lines changed: 58 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,25 @@ public static IndicatorStyle fromValue(int value) {
9595
}
9696
}
9797

98+
public enum LinePosition {
99+
Bottom(0), Top(1);
100+
101+
public final int value;
102+
103+
private LinePosition(int value) {
104+
this.value = value;
105+
}
106+
107+
public static LinePosition fromValue(int value) {
108+
for (LinePosition position : LinePosition.values()) {
109+
if (position.value == value) {
110+
return position;
111+
}
112+
}
113+
return null;
114+
}
115+
}
116+
98117
private ViewPager mViewPager;
99118
private ViewPager.OnPageChangeListener mListener;
100119
private int mCurrentPage = -1;
@@ -108,6 +127,7 @@ public static IndicatorStyle fromValue(int value) {
108127
private final Rect mBounds = new Rect();
109128
private final Paint mPaintFooterLine = new Paint();
110129
private IndicatorStyle mFooterIndicatorStyle;
130+
private LinePosition mLinePosition;
111131
private final Paint mPaintFooterIndicator = new Paint();
112132
private float mFooterIndicatorHeight;
113133
private float mFooterIndicatorUnderlinePadding;
@@ -148,6 +168,7 @@ public TitlePageIndicator(Context context, AttributeSet attrs, int defStyle) {
148168
final float defaultFooterIndicatorHeight = res.getDimension(R.dimen.default_title_indicator_footer_indicator_height);
149169
final float defaultFooterIndicatorUnderlinePadding = res.getDimension(R.dimen.default_title_indicator_footer_indicator_underline_padding);
150170
final float defaultFooterPadding = res.getDimension(R.dimen.default_title_indicator_footer_padding);
171+
final int defaultLinePosition = res.getInteger(R.integer.default_title_indicator_line_position);
151172
final int defaultSelectedColor = res.getColor(R.color.default_title_indicator_selected_color);
152173
final boolean defaultSelectedBold = res.getBoolean(R.bool.default_title_indicator_selected_bold);
153174
final int defaultTextColor = res.getColor(R.color.default_title_indicator_text_color);
@@ -165,6 +186,7 @@ public TitlePageIndicator(Context context, AttributeSet attrs, int defStyle) {
165186
mFooterIndicatorHeight = a.getDimension(R.styleable.TitlePageIndicator_footerIndicatorHeight, defaultFooterIndicatorHeight);
166187
mFooterIndicatorUnderlinePadding = a.getDimension(R.styleable.TitlePageIndicator_footerIndicatorUnderlinePadding, defaultFooterIndicatorUnderlinePadding);
167188
mFooterPadding = a.getDimension(R.styleable.TitlePageIndicator_footerPadding, defaultFooterPadding);
189+
mLinePosition = LinePosition.fromValue(a.getInteger(R.styleable.TitlePageIndicator_linePosition, defaultLinePosition));
168190
mTopPadding = a.getDimension(R.styleable.TitlePageIndicator_topPadding, defaultTopPadding);
169191
mTitlePadding = a.getDimension(R.styleable.TitlePageIndicator_titlePadding, defaultTitlePadding);
170192
mClipPadding = a.getDimension(R.styleable.TitlePageIndicator_clipPadding, defaultClipPadding);
@@ -241,6 +263,15 @@ public void setFooterIndicatorStyle(IndicatorStyle indicatorStyle) {
241263
invalidate();
242264
}
243265

266+
public LinePosition getLinePosition() {
267+
return mLinePosition;
268+
}
269+
270+
public void setLinePosition(LinePosition linePosition) {
271+
mLinePosition = linePosition;
272+
invalidate();
273+
}
274+
244275
public int getSelectedColor() {
245276
return mColorSelected;
246277
}
@@ -332,7 +363,9 @@ protected void onDraw(Canvas canvas) {
332363
}
333364

334365
// mCurrentPage is -1 on first start and after orientation changed. If so, retrieve the correct index from viewpager.
335-
if(mCurrentPage == -1 && mViewPager != null) mCurrentPage = mViewPager.getCurrentItem();
366+
if (mCurrentPage == -1 && mViewPager != null) {
367+
mCurrentPage = mViewPager.getCurrentItem();
368+
}
336369

337370
//Calculate views bounds
338371
ArrayList<Rect> bounds = calculateAllBounds(mPaintText);
@@ -349,7 +382,7 @@ protected void onDraw(Canvas canvas) {
349382
final int left = getLeft();
350383
final float leftClip = left + mClipPadding;
351384
final int width = getWidth();
352-
final int height = getHeight();
385+
int height = getHeight();
353386
final int right = left + width;
354387
final float rightClip = right - mClipPadding;
355388

@@ -457,19 +490,29 @@ protected void onDraw(Canvas canvas) {
457490
}
458491
}
459492

493+
//If we want the line on the top change height to zero and invert the line height to trick the drawing code
494+
float footerLineHeight = mFooterLineHeight;
495+
float footerIndicatorLineHeight = mFooterIndicatorHeight;
496+
if (mLinePosition == LinePosition.Top) {
497+
height = 0;
498+
footerLineHeight = -footerLineHeight;
499+
footerIndicatorLineHeight = -footerIndicatorLineHeight;
500+
}
501+
460502
//Draw the footer line
461503
mPath.reset();
462-
mPath.moveTo(0, height - mFooterLineHeight / 2f);
463-
mPath.lineTo(width, height - mFooterLineHeight / 2f);
504+
mPath.moveTo(0, height - footerLineHeight / 2f);
505+
mPath.lineTo(width, height - footerLineHeight / 2f);
464506
mPath.close();
465507
canvas.drawPath(mPath, mPaintFooterLine);
466508

509+
float heightMinusLine = height - footerLineHeight;
467510
switch (mFooterIndicatorStyle) {
468511
case Triangle:
469512
mPath.reset();
470-
mPath.moveTo(halfWidth, height - mFooterLineHeight - mFooterIndicatorHeight);
471-
mPath.lineTo(halfWidth + mFooterIndicatorHeight, height - mFooterLineHeight);
472-
mPath.lineTo(halfWidth - mFooterIndicatorHeight, height - mFooterLineHeight);
513+
mPath.moveTo(halfWidth, heightMinusLine - footerIndicatorLineHeight);
514+
mPath.lineTo(halfWidth + footerIndicatorLineHeight, heightMinusLine);
515+
mPath.lineTo(halfWidth - footerIndicatorLineHeight, heightMinusLine);
473516
mPath.close();
474517
canvas.drawPath(mPath, mPaintFooterIndicator);
475518
break;
@@ -480,11 +523,15 @@ protected void onDraw(Canvas canvas) {
480523
}
481524

482525
Rect underlineBounds = bounds.get(page);
526+
final float rightPlusPadding = underlineBounds.right + mFooterIndicatorUnderlinePadding;
527+
final float leftMinusPadding = underlineBounds.left - mFooterIndicatorUnderlinePadding;
528+
final float heightMinusLineMinusIndicator = heightMinusLine - footerIndicatorLineHeight;
529+
483530
mPath.reset();
484-
mPath.moveTo(underlineBounds.left - mFooterIndicatorUnderlinePadding, height - mFooterLineHeight);
485-
mPath.lineTo(underlineBounds.right + mFooterIndicatorUnderlinePadding, height - mFooterLineHeight);
486-
mPath.lineTo(underlineBounds.right + mFooterIndicatorUnderlinePadding, height - mFooterLineHeight - mFooterIndicatorHeight);
487-
mPath.lineTo(underlineBounds.left - mFooterIndicatorUnderlinePadding, height - mFooterLineHeight - mFooterIndicatorHeight);
531+
mPath.moveTo(leftMinusPadding, heightMinusLine);
532+
mPath.lineTo(rightPlusPadding, heightMinusLine);
533+
mPath.lineTo(rightPlusPadding, heightMinusLineMinusIndicator);
534+
mPath.lineTo(leftMinusPadding, heightMinusLineMinusIndicator);
488535
mPath.close();
489536

490537
mPaintFooterIndicator.setAlpha((int)(0xFF * selectedPercent));

sample/AndroidManifest.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,14 @@
127127

128128

129129
<!-- TITLE INDICATOR -->
130+
<activity
131+
android:name=".SampleTitlesBottom"
132+
android:label="Titles/Default (Bottom)">
133+
<intent-filter>
134+
<action android:name="android.intent.action.MAIN" />
135+
<category android:name="com.jakewharton.android.viewpagerindicator.sample.SAMPLE" />
136+
</intent-filter>
137+
</activity>
130138
<activity
131139
android:name=".SampleTitlesCenterClickListener"
132140
android:label="Titles/Center Click Listener">
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- Copyright (C) 2011 Jake Wharton
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
17+
<LinearLayout
18+
xmlns:android="http://schemas.android.com/apk/res/android"
19+
xmlns:app="http://schemas.android.com/apk/res-auto"
20+
android:orientation="vertical"
21+
android:layout_width="fill_parent"
22+
android:layout_height="fill_parent">
23+
24+
<android.support.v4.view.ViewPager
25+
android:id="@+id/pager"
26+
android:layout_width="fill_parent"
27+
android:layout_height="0dp"
28+
android:layout_weight="1"
29+
/>
30+
<com.viewpagerindicator.TitlePageIndicator
31+
android:id="@+id/indicator"
32+
android:padding="10dip"
33+
android:layout_height="wrap_content"
34+
android:layout_width="fill_parent"
35+
app:linePosition="top"
36+
/>
37+
38+
</LinearLayout>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.viewpagerindicator.sample;
2+
3+
import android.os.Bundle;
4+
import android.support.v4.view.ViewPager;
5+
import com.viewpagerindicator.TitlePageIndicator;
6+
7+
public class SampleTitlesBottom extends BaseSampleActivity {
8+
@Override
9+
protected void onCreate(Bundle savedInstanceState) {
10+
super.onCreate(savedInstanceState);
11+
setContentView(R.layout.simple_titles_bottom);
12+
13+
mAdapter = new TestTitleFragmentAdapter(getSupportFragmentManager());
14+
15+
mPager = (ViewPager)findViewById(R.id.pager);
16+
mPager.setAdapter(mAdapter);
17+
18+
mIndicator = (TitlePageIndicator)findViewById(R.id.indicator);
19+
mIndicator.setViewPager(mPager);
20+
}
21+
}

0 commit comments

Comments
 (0)