1、自定义viewIndicator,使它继承LinearLayout
2、画三角形,计算三角形所在的位置
3、viewpage与tab之间产生联动。
分开一步步来说:
一、tab栏中自定义viewIndicator,主要代码为:
public class ViewIndicator extends LinearLayout {
private TypedArray array;
//画笔
private Paint mPaint;
//三角形
private Path mPath;
//三角形的宽和高
private int mTrianleWidth;
private int mTrianleHeight;
private static final float RADIO_TRIANGLE_WIDTH=1/6F;
//设置初始化的位置
private int mInitTranslationX;
//设置偏移量
private int mTranslationX;
private int mTabvisibleCount;
//默认显示的数量为4
private static final int COUNT_DEFAULT_TAB = 4;
private List mTitles;
//正常状态下的字体颜色
private static final int COLOR_TEXT_NORMAL=0x77FFFFFF;
//正常状态下的字体颜色
private static final int COLOR_TEXT_HIGH=0xFFFFFFFF;
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mTrianleWidth= (int) (w/mTabvisibleCount*RADIO_TRIANGLE_WIDTH);
mInitTranslationX=w/mTabvisibleCount/2-mTrianleWidth/2;
initTriangle();
}
//初始化三角形
private void initTriangle() {
mTrianleHeight=mTrianleWidth/2;
mPath=new Path();
//首先是在原点的位置
mPath.moveTo(0,0);
//三角形的底边首先移动,x轴是x的宽度,y轴为0;(0,0)△(三角形宽度mTrianleWidth,0)
mPath.lineTo(mTrianleWidth,0);
//再向左上方移动,如果为等腰三角形,Y轴方向的高度与mTrianleWidth/2相等,y轴向下是正数
mPath.lineTo(mTrianleWidth/2,-mTrianleHeight);
//闭合,形成三角形。
mPath.close();
}
public ViewIndicator(Context context) {
this(context,null);
}
@Override
protected void dispatchDraw(Canvas canvas) {
canvas.save();
canvas.translate(mInitTranslationX+mTranslationX,getHeight() +2);
canvas.drawPath(mPath,mPaint);
canvas.restore();
super.dispatchDraw(canvas);
}
public ViewIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
//获取自定义属性,可见Tab的数量
array=context.obtainStyledAttributes(attrs,R.styleable.ViewIndicator);
mTabvisibleCount=array.getInt(R.styleable.ViewIndicator_visible_tab_count,COUNT_DEFAULT_TAB);
if (mTabvisibleCount<0){
mTabvisibleCount=COUNT_DEFAULT_TAB;
}
array.recycle();
//初始化画笔
mPaint=new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.WHITE);
mPaint.setStyle(Paint.Style.FILL);
//设置圆角效果,不至于太尖锐
mPaint.setPathEffect(new CornerPathEffect(3));
}
//当xml加载完后运行该方法
@Override
protected void onFinishInflate() {
super.onFinishInflate();
//拿到子元素的个数
int cCount=getChildCount();
if (cCount==0){
return;
}
for (int i = 0; i //获取参数,重新动态布局
LinearLayout.LayoutParams lp= (LayoutParams) view.getLayoutParams();
//如果设置了权重,此时将权重设置为0
lp.weight=0;
//将宽度设置为平分。屏幕宽度除以可见数量
lp.width=getScreenWidth()/mTabvisibleCount;
//设置参数
view.setLayoutParams(lp);
}
}
//获取屏幕宽度
private int getScreenWidth() {
WindowManager wm= (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics=new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.widthPixels;
};
/**
* 指示器跟随着viewpager一起移动。
* @param position
* @param offset
*/
public void scoll(int position,float offset) {
int tabwidth=getWidth()/mTabvisibleCount;
mTranslationX= (int) (tabwidth*(offset+position));
//容器移动,当tab处于移动的最后一个时,当可见tab不为1
if (mTabvisibleCount!=1) {
if (position >= (mTabvisibleCount - 2) && offset > 0 && getChildCount() > mTabvisibleCount) {
this.scrollTo((position - (mTabvisibleCount - 2)) * tabwidth + (int) (tabwidth * offset), 0);
}
}else {
this.scrollTo((int)(tabwidth*(position+offset)),0);
}
//三角形发生改变,需要重新绘制
invalidate();
}
public void setTabItemTitles(List titles){
if (titles!=null&&titles.size()>0){
this.removeAllViews();
mTitles=titles;
for (String title : titles) {
addView(generateTexeView(title));
}
}
setItemOnclick();
}
//根据title创建Tab
private View generateTexeView(String title) {
TextView tv=new TextView(getContext());
LinearLayout.LayoutParams lp=new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
lp.width=getScreenWidth()/mTabvisibleCount;
tv.setText(title);
tv.setGravity(Gravity.CENTER);
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP,16);
tv.setTextColor(Color.WHITE);
tv.setLayoutParams(lp);
return tv;
}
private ViewPager viewPager;
//设置可显示的tab数目。
public void setVisibleTabCount(int count){
mTabvisibleCount=count;
}
//简化activity中的代码
public void setPageOnchangListen(ViewPager vp, int pos){
viewPager=vp;
//为viewpage设置监听器
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//当页面发生滚动的时候,偏移量为tabwidth*positionOffset(这是0-1的页面)+position*tabwidth(第二个页面到第三个页面)
scoll(position,positionOffset);
//为OnpagerChangeListener中的方法设置
if(listener!=null) {
listener.onPageScrolled(position, positionOffset, positionOffsetPixels);
}
}
@Override
public void onPageSelected(int position) {
if(listener!=null)
listener.onPageSelected(position);
highLightTextView(position);
}
@Override
public void onPageScrollStateChanged(int state) {
if(listener!=null)
listener.onPageScrollStateChanged(state);
}
});
viewPager.setCurrentItem(pos);
highLightTextView(pos);
}
private OnPageChangeListener listener;
//设置viewpager的回调供选择者使用
public interface OnPageChangeListener{
void onPageScrolled(int position, float positionOffset, int positionOffsetPixels);
void onPageSelected(int position);
void onPageScrollStateChanged(int state);
}
//设置一个方法供调用者使用
public void setOnpageChangeListener(OnPageChangeListener mlistener){
this.listener=mlistener;
}
//重置颜色
public void resetTextViewColor(){
for(int i=0;iif (view instanceof TextView){
((TextView) view).setTextColor(COLOR_TEXT_NORMAL);
}
}
}
//设置颜色字体;
public void highLightTextView(int pos){
//重置颜色
resetTextViewColor();
View view=getChildAt(pos);
if (view instanceof TextView){
((TextView) view).setTextColor(COLOR_TEXT_HIGH);
}
}
//设置监听器
public void setItemOnclick(){
for (int i = 0; i final int j =i;
View view =getChildAt(i);
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
viewPager.setCurrentItem(j);
}
});
}
}
}
代码中都有注释,这里主要是想讲解下有关于画三角形:
图片比较粗糙,各位将就看下~毕竟不是专业美工出身。首先是设置三角形的起点,调用mpath.lineto()函数,移动坐标。需要注意的是Y轴向上是负,向下为正。最后闭合三角形。
//起点
mPath.moveTo(0,0);
//三角形的底边首先移动,x轴是x的宽度,y轴为0;(0,0)△(三角形宽度mTrianleWidth,0)
mPath.lineTo(mTrianleWidth,0);
//再向左上方移动,如果为等腰三角形,Y轴方向的高度与mTrianleWidth/2相等,y轴向下是正数
mPath.lineTo(mTrianleWidth/2,-mTrianleHeight);
//闭合,形成三角形。
mPath.close();
在MainActivity中的调用:
public class MainActivity extends FragmentActivity {
ViewPager viewPager;
ViewIndicator viewIndicator;
private List mtitles= Arrays.asList("短信1","收藏2","推荐3","短信4","收藏5","推荐6","短信7","收藏8","推荐9");
private List fragments=new ArrayList();
//fragment的adapter
private FragmentPagerAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main2);
// ButterKnife.bind(this);
initView();
initDatas();
//先设置可显示的数量
viewIndicator.setVisibleTabCount(4);
viewIndicator.setTabItemTitles(mtitles);
viewPager.setAdapter(mAdapter);
//在viewIndicator中设置监听,避免在
viewIndicator.setPageOnchangListen(viewPager,0);
}
private void initView() {
viewPager= (ViewPager) findViewById(R.id.viewpager);
viewIndicator= (ViewIndicator) findViewById(R.id.id_indicator);
}
private void initDatas() {
for (String mtitle : mtitles) {
fragments.add(VpsimpleFragment.newInstance(mtitle));
}
mAdapter=new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
return fragments.get(position);
}
@Override
public int getCount() {
return fragments.size();
}
};
}
实现代码比较简单。就不一一阐述了。
关于VpsimpleFragment.java的代码如下:
private String mtitle;
public static final String BUNDLE_TITLE="title";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Bundle bundle=getArguments();
if (bundle!=null){
mtitle=bundle.getString(BUNDLE_TITLE);
}
TextView textView=new TextView(getActivity());
textView.setText(mtitle);
textView.setGravity(Gravity.CENTER);
return textView;
}
//获取实例
public static VpsimpleFragment newInstance(String title){
Bundle bundle=new Bundle();
bundle.putString(BUNDLE_TITLE,title);
VpsimpleFragment fragment=new VpsimpleFragment();
fragment.setArguments(bundle);
return fragment;
}