主要实现的思路:

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;//默认显示的数量为4private static final int COUNT_DEFAULT_TAB = 4;private List<String> mTitles;//正常状态下的字体颜色private static final int COLOR_TEXT_NORMAL=0x77FFFFFF;//正常状态下的字体颜色private static final int COLOR_TEXT_HIGH=0xFFFFFFFF;@Overrideprotected 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);}@Overrideprotected 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加载完后运行该方法@Overrideprotected void onFinishInflate() {super.onFinishInflate();//拿到子元素的个数int cCount=getChildCount();if (cCount==0){return;}for (int i = 0; i <cCount ; i++) {View view=getChildAt(i);//获取参数,重新动态布局LinearLayout.LayoutParams lp= (LayoutParams) view.getLayoutParams();//如果设置了权重,此时将权重设置为0lp.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不为1if (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<String> titles){if (titles!=null&&titles.size()>0){this.removeAllViews();mTitles=titles;for (String title : titles) {addView(generateTexeView(title));}}setItemOnclick();}
//根据title创建Tabprivate 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() {@Overridepublic 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);}}@Overridepublic void onPageSelected(int position) {if(listener!=null)listener.onPageSelected(position);highLightTextView(position);}@Overridepublic 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;i<getChildCount();i++){View view =getChildAt(i);if (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 <getChildCount() ; i++) {final int j =i;View view =getChildAt(i);view.setOnClickListener(new OnClickListener() {@Overridepublic 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<String> mtitles= Arrays.asList("短信1","收藏2","推荐3","短信4","收藏5","推荐6","短信7","收藏8","推荐9");private List<VpsimpleFragment> fragments=new ArrayList<VpsimpleFragment>();//fragment的adapterprivate FragmentPagerAdapter mAdapter;@Overrideprotected 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()) {@Overridepublic Fragment getItem(int position) {return fragments.get(position);}@Overridepublic int getCount() {return fragments.size();}};}

实现代码比较简单。就不一一阐述了。
关于VpsimpleFragment.java的代码如下:

        private String mtitle;public static final String BUNDLE_TITLE="title";@Overridepublic 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;}

Android指示器。相关推荐

  1. Android指示器的使用总结

    一.Android指示器的基础知识 Android指示器实现的三种基础方法: 1.使用PagerTitleStrip 2.使用PagerTabStrip 3.使用自定义的View设计宽度 (一)Pag ...

  2. android 指示器平移动画,Android实现带指示器的自动轮播式ViewPager

    前言 最近在做项目的时候,有个需求就是实现自动轮播式的ViewPager,最直观的例子就是知乎日报顶部的ViewPager,它内部有着好几个子view,每个一段时间便自动滑动到下一个item view ...

  3. Android指示器的使用。

    MagicIndicator是一款比较灵活的指示器.做项目时由于特殊的需求,需要灵活的指示器.于是在GitHub上找到一个使用很方便的框架. github地址:https://github.com/h ...

  4. android 流程指示,Android实现带有指示器的进度条

    背景 当我们看到UI给我们设计的效果的时候,我们习惯性的思路就是看看google有没有为我们提供相应的控件或者是能否在网上找到一些合适的轮子拿过来直接用.但是,有时候很不巧的是没有这样的轮子供我们直接 ...

  5. android进度指示器_等待的痛苦—浏览进度指示器地狱的7个级别

    android进度指示器 by Mike Zetlow 由Mike Zetlow 等待的痛苦-浏览进度指示器地狱的7个级别 (The Pain of Waiting - Navigating the ...

  6. Android MagicIndicator系列之一 —— 使用MagicIndicator打造千变万化的ViewPager指示器...

    说到 ViewPager 指示器,想必大家都不陌生,绝大部分应用中都有这个.使用频率非常之高.但系统对它的支持并不好,自带的 PagerTabStrip 和 PagerTitleStrip 太弱,很难 ...

  7. android之tab分页标签的实现方法,Android应用中使用ViewPager和ViewPager指示器来制作Tab标签...

    一.ViewPageIndicator开源框架的基本用法我们先得去Github上面下载这个库,下载地址:https://github.com/JakeWharton/Android-ViewPager ...

  8. Android 自定义控件 ViewPager头部指示器控件 ViewPagerBelowIndicator

    效果 演示 说明 为了实现 ViewPager 切换 Fragment 时的标签效果(类似新闻客户端导航的效果) 代码 package com.demo.view;import android.con ...

  9. android 横向stepview,Android 流程指示器 StepView

    软件介绍 StepView 是Android平台下自定义的流程指示器. 效果图: 使用: android:id="@+id/step_view0" android:layout_w ...

最新文章

  1. js如何判断一个对象是不是Array?
  2. mysql海量数据存储
  3. 32 CO配置-控制-产品成本控制-成本对象控制-期末结算-定义差异码
  4. 企业实战|基于Cobbler实现多版本系统批量部署
  5. 开始我们的Snippets!
  6. 抖音-相关分析和理解
  7. et200s模块接线图讲解_西门子S7-1500使用ET200S 1SI模块实现自由口通信
  8. 问卷星如何设置调查人利用账号登录_端起你的小板凳,快来听我讲制作调查问卷啦!...
  9. 西餐菜单怎么翻译成英文
  10. 利用ode45求解含控制量并且控制量为离散点的动力学方程
  11. zyt-Linux云计算
  12. Java 七参数计算
  13. python练习-Python输出不重复的字符
  14. MATLAB读取网页内链接,Matlab使用urlread()读取网页乱码问题
  15. 使用SfntTool制作字体剪辑工具1 - 直接使用sfnttool.jar
  16. 信号与系统——初识到理解(第二章——信号与系统)
  17. 【 题集 】 寒假计划——最短路
  18. 力扣 731. 我的日程安排表 II
  19. 企业应用大数据的三重境界:数据·分析·成果
  20. 进化算法可以不再需要计算集群,开普敦大学的新方法用一块GPU也能刷新MNIST记录...

热门文章

  1. 【游戏建模干货】国外角色建模大师的这几步操作,堪称学习经典,赶紧脑补一下吧!
  2. 这可能是史上功能最全的 Java 权限认证框架!
  3. matlab在Linux 环境下的安装激活
  4. 今年六月 IBM 推出 SOA 认证 考试
  5. 开发微信小程序调用拼多多接口
  6. certutil程序生成MD5
  7. 找不到/storage/emulated/0文件
  8. 如何为智能投顾打造对话系统?这有一份指南可供参考
  9. 【在线研讨-现场文字】《敏捷开发用户故事分类与组织结构(一期-5)》2012-06-26
  10. Oracle EBS 提交子请求