ViewPageIndicator,说白了就是ViewPager的分页指示器。JakeWharton的开源控件ViewPageIndicator提供了标签指引效果:底部小圆点的、底部图标的、底部指示线的、顶部tab标签的(掉图标的tab标签等)、顶部title的等效果,都可以自己修改适合自己的style显示样式。
今天主要介绍的是利用ViewPageIndicator+ViewPager实现左右滑动带图标tab标签功能。
首先我们需要去去Github下载类库:https://github.com/JakeWharton/Android-ViewPagerIndicator。下载下来之后里边主要有两个文件:sample和library。sample里边主要是运行例子,以上所说的效果sample中都有;library是库工程,会作为我们的项目依赖库。
新建一个Android项目工程,将library引入。如果新建的项目libs目录下有android-support-v4.jar,你要将其删除,因为ViewPageIndicator里面有这个库,我们的项目中不允许存在两个android-support-v4.jar,不删除编译不能通过。
下面主要介绍代码,首先看布局文件,很简单,上边一个main_head主页的标题栏,下边tab标签指示器,最下边一个ViewPager。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@android:color/white"
android:orientation="vertical" >
<include layout="@layout/main_head" />
<com.viewpagerindicator.TabPageIndicator
android:id="@+id/indicator"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
MainActivity代码:
package com.chuan.viewpagerindicatortest;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import com.viewpagerindicator.IconPagerAdapter;
import com.viewpagerindicator.TabPageIndicator;
public class MainActivity extends FragmentActivity {
private static final String[] CONTENT = new String[] { "最新", "最热","穿越"};
private static final int[] ICONS = new int[] {
R.drawable.news,
R.drawable.hot,
R.drawable.random,
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentPagerAdapter adapter = new GoogleMusicAdapter(getSupportFragmentManager());
ViewPager pager = (ViewPager)findViewById(R.id.pager);
pager.setAdapter(adapter);
TabPageIndicator indicator = (TabPageIndicator)findViewById(R.id.indicator);
indicator.setViewPager(pager);
}
class GoogleMusicAdapter extends FragmentPagerAdapter implements IconPagerAdapter {
public GoogleMusicAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return TestFragment.newInstance(CONTENT[position % CONTENT.length]);
}
@Override
public CharSequence getPageTitle(int position) {
return CONTENT[position % CONTENT.length].toUpperCase();
}
@Override public int getIconResId(int index) {
return ICONS[index];
}
@Override
public int getCount() {
return CONTENT.length;
}
}
}
首先我们先定义title和图标的集合,然后
实例化ViewPager和TabPageIndicator,要显示图标就需要重写继承自FragmentPagerAdapter并实现IconPagerAdapter的Adapter类,本例GoogleMusicAdapter。然后设置设置TabPageIndicator和ViewPager关联,就是调用TabPageIndicator的setViewPager(ViewPager view)方法,这样子我们就实现了点击上面的Tab,下面的ViewPager切换,滑动ViewPager上面的Tab跟着切换,ViewPager的item,也就是Fragment,我这里只用了一个TextView来显示从MainActivity传递过来的Tab的标题,只是为了模拟平常我们实际使用中,从Activity传递参数给Fragment,下面是TestFragment代码,其中具体的穿值就是在GoogleMusicAdapter中的getItem中。
package com.chuan.viewpagerindicatortest;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
public final class TestFragment extends Fragment {
private static final String KEY_CONTENT = "TestFragment:Content";
public static TestFragment newInstance(String content) {
TestFragment fragment = new TestFragment();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < 20; i++) {
builder.append(content).append(" ");
}
builder.deleteCharAt(builder.length() - 1);
fragment.mContent = builder.toString();
return fragment;
}
private String mContent = "???";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if ((savedInstanceState != null) && savedInstanceState.containsKey(KEY_CONTENT)) {
mContent = savedInstanceState.getString(KEY_CONTENT);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
TextView text = new TextView(getActivity());
text.setGravity(Gravity.CENTER);
text.setText(mContent);
text.setTextSize(20 * getResources().getDisplayMetrics().density);
text.setPadding(20, 20, 20, 20);
LinearLayout layout = new LinearLayout(getActivity());
layout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
layout.setGravity(Gravity.CENTER);
layout.addView(text);
return layout;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(KEY_CONTENT, mContent);
}
}
当然我们还需要改变标签的显示样式,就需要修改style文件,在AndroidManifest.xml的activity中引用我们自定义style样式
<style name="StyledIndicators" parent="@android:style/Theme.Light">
<item name="android:windowNoTitle">true</item>
<item name="vpiCirclePageIndicatorStyle">@style/CustomCirclePageIndicator</item>
<item name="vpiLinePageIndicatorStyle">@style/CustomLinePageIndicator</item>
<item name="vpiTitlePageIndicatorStyle">@style/CustomTitlePageIndicator</item>
<item name="vpiTabPageIndicatorStyle">@style/CustomTabPageIndicator</item>
<item name="vpiUnderlinePageIndicatorStyle">@style/CustomUnderlinePageIndicator</item>
</style>
<style name="CustomTitlePageIndicator">
<item name="android:background">#18FF0000</item>
<item name="footerColor">#FFAA2222</item>
<item name="footerLineHeight">1dp</item>
<item name="footerIndicatorHeight">3dp</item>
<item name="footerIndicatorStyle">underline</item>
<item name="android:textColor">#AA000000</item>
<item name="selectedColor">#FF000000</item>
<item name="selectedBold">true</item>
</style>
<style name="CustomLinePageIndicator">
<item name="strokeWidth">4dp</item>
<item name="lineWidth">30dp</item>
<item name="unselectedColor">#FF888888</item>
<item name="selectedColor">#FF880000</item>
</style>
<style name="CustomCirclePageIndicator">
<item name="fillColor">#FF888888</item>
<item name="strokeColor">#FF000000</item>
<item name="strokeWidth">2dp</item>
<item name="radius">10dp</item>
<item name="centered">true</item>
</style>
<style name="CustomTabPageIndicator" parent="Widget.TabPageIndicator">
<item name="android:background">@drawable/custom_tab_indicator</item>
<item name="android:textAppearance">@style/CustomTabPageIndicator.Text</item>
<item name="android:textColor">#FF555555</item>
<item name="android:textSize">16sp</item>
<item name="android:divider">@drawable/custom_tab_indicator_divider</item>
<item name="android:dividerPadding">10dp</item>
<item name="android:showDividers">middle</item>
<item name="android:paddingLeft">8dp</item>
<item name="android:paddingRight">8dp</item>
<item name="android:fadingEdge">horizontal</item>
<item name="android:fadingEdgeLength">8dp</item>
</style>
<style name="CustomTabPageIndicator.Text" parent="android:TextAppearance.Medium">
<item name="android:typeface">monospace</item>
</style>
<style name="CustomUnderlinePageIndicator">
<item name="selectedColor">#FFCC0000</item>
<item name="android:background">#FFCCCCCC</item>
<item name="fadeLength">1000</item>
<item name="fadeDelay">1000</item>
</style>
为了实现滑动时标签图标的变化更加明显我们在定义图标集合时应该引用我们在drawable文件夹中的自定义图片文件hot.xml等
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/hot_select" />
<item android:drawable="@drawable/hot_default" />
</selector>
由于类库中的标签状态图片是蓝色的我们也可以通过修改style中CustomTabPageIndicator的android:background中的drawable来实现我们想要的效果
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Non focused states -->
<item android:state_focused="false" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/custom_tab_indicator_unselected" />
<item android:state_focused="false" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/custom_tab_indicator_selected" />
<!-- Focused states -->
<item android:state_focused="true" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/custom_tab_indicator_unselected_focused" />
<item android:state_focused="true" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/custom_tab_indicator_selected_focused" />
<!-- Pressed -->
<!-- Non focused states -->
<item android:state_focused="false" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/custom_tab_indicator_unselected_pressed" />
<item android:state_focused="false" android:state_selected="true" android:state_pressed="true" android:drawable="@drawable/custom_tab_indicator_selected_pressed" />
<!-- Focused states -->
<item android:state_focused="true" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/custom_tab_indicator_unselected_pressed" />
<item android:state_focused="true" android:state_selected="true" android:state_pressed="true" android:drawable="@drawable/custom_tab_indicator_selected_pressed" />
</selector>
使用ViewPageIndicator默认图标不能居中,所以我们需要修改一下类库library中TabPageIndicator.java文件。我们需要自定义TextView,在TabPageIndicator的继承自TextView中的TabView类中我们需要继承我们自定义的TextView类DrawableCenterTextView,DrawableCenterTextView的内容如下:
package com.viewpagerindicator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.TextView;
public class DrawableCenterTextView extends TextView {
public DrawableCenterTextView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
public DrawableCenterTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DrawableCenterTextView(Context context) {
super(context);
}
@Override
protected void onDraw(Canvas canvas) {
Drawable[] drawables = getCompoundDrawables();
if (drawables != null) {
Drawable drawableLeft = drawables[0];
Drawable drawableRight = drawables[2];
if (drawableLeft != null || drawableRight != null) {
float textWidth = getPaint().measureText(getText().toString());
int drawablePadding = getCompoundDrawablePadding();
int drawableWidth = 0;
if (drawableLeft != null)
drawableWidth = drawableLeft.getIntrinsicWidth();
else if (drawableRight != null) {
drawableWidth = drawableRight.getIntrinsicWidth();
}
float bodyWidth = textWidth + drawableWidth + drawablePadding;
canvas.translate((getWidth() - bodyWidth) / 2, 0);
}
}
super.onDraw(canvas);
}
}
图标居中感谢:http://www.cnblogs.com/
最后我们看运行效果
总结使用ViewPagerIndicator还是可以很方便的实现我们想要的效果。
源码下载地址:http://download.csdn.net/detail/xiaoxiaoma_yi/8119057