ViewPagerIndicator.java

public class ViewPagerIndicator extends LinearLayout {

    private Paint mPaint;
private Path mPath;
private int mTriangleWidth;
private int mTriangleHeight;
private static final float RADIO_TRIANGLE_WIDTH = 1/6F;
//三角形的底边最大宽度
private final float DIMENTION_TRIANGLE_WIDTH_MAX = getScreenWidth() / 3 * RADIO_TRIANGLE_WIDTH;
private int mInitTranslationX;
private int mTranslationX;
private int mVisibleTabCount;
private static final int COUNT_DEFAULT_TAB = 4;
private static final int COLOR_TEXT_NORMAL = 0x77FFFFFF;
private static final int COLOR_TEXT_HIGHLIGHT = 0xFFFFFFFF;
private ViewPager mViewPager;
private HorizontalScrollView mScrollView;
private boolean isClicked = false; //判断是否是由点击产生的滑动
private int scrollLocation; //Tab滚动的位置 public ViewPagerIndicator(Context context) {
this(context, null);
} public ViewPagerIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
//获取可见的tab数量
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ViewPagerIndicator);
mVisibleTabCount = a.getInt(R.styleable.ViewPagerIndicator_visible_table_count, COUNT_DEFAULT_TAB); if (mVisibleTabCount < 0) {
mVisibleTabCount = COUNT_DEFAULT_TAB;
}
a.recycle(); int w = getScreenWidth(); //屏幕宽度
Log.i("屏幕宽度", w+""); mTriangleWidth = (int) (w / mVisibleTabCount * RADIO_TRIANGLE_WIDTH);
mTriangleWidth = (int) Math.min(mTriangleWidth, DIMENTION_TRIANGLE_WIDTH_MAX);
mInitTranslationX = w / mVisibleTabCount / 2 - mTriangleWidth / 2;
Log.i("InitTranslationX", ""+mInitTranslationX);
Log.i("mTrianglewidth", mTriangleWidth+"");
Log.i("TabWidth", ""+(int)(w/mVisibleTabCount));
initTriangle(); //初始化画笔
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.parseColor("#ffffff"));
mPaint.setStyle(Paint.Style.FILL);
mPaint.setPathEffect(new CornerPathEffect(3));
} public interface OnPageChangeListener {
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels); public void onPageSelected(int position); public void onPageScrollStateChanged(int state);
} public OnPageChangeListener mListener; public void setOnPageChangedListener(OnPageChangeListener listener) {
this.mListener = listener;
} @Override
protected void dispatchDraw(Canvas canvas) { canvas.save(); canvas.translate(mInitTranslationX + mTranslationX, getHeight()+2);
canvas.drawPath(mPath, mPaint); canvas.restore(); super.dispatchDraw(canvas);
} @Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
} /**
* 通过布局添加Tab
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate(); int cCount = getChildCount();
if (cCount == 0) {
return;
} for (int i = 0; i < cCount; i++) {
View view = getChildAt(i);
LayoutParams lp = (LayoutParams) view.getLayoutParams();
lp.weight = 0;
lp.width = getScreenWidth() / mVisibleTabCount;
} setItemClickEvent();
} /**
* 获得屏幕的宽度
* @return
*/
private int getScreenWidth() {
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.widthPixels;
} /**
* 初始化三角形
*/
private void initTriangle() {
mTriangleHeight = mTriangleWidth / 2;
mPath = new Path();
mPath.moveTo(0,0);
mPath.lineTo(mTriangleWidth, 0);
mPath.lineTo(mTriangleWidth/2, -mTriangleHeight);
mPath.close();
} /**
* 指示器跟随手指进行滚动
* @param position
* @param offset
*/
public void scroll(int position, float offset) {
int tabWidth = getScreenWidth() / mVisibleTabCount;
mTranslationX = (int) (tabWidth * (position + offset));
invalidate(); //三角形的位置
int triangleLocation = mTranslationX + mInitTranslationX;
int screenWidth = getScreenWidth();
//当三角形处于滑动至屏幕外时移动外层ScrollView
if ((triangleLocation - scrollLocation) > (screenWidth - mInitTranslationX)
&& offset > 0.5 && !isClicked) {
if (mVisibleTabCount == 1) {
mScrollView.scrollTo(mTranslationX, 0);
scrollLocation = mTranslationX;
} else {
mScrollView.scrollTo((position - 2) * tabWidth, 0);
scrollLocation = (position - 2) * tabWidth;
}
} else if((triangleLocation - scrollLocation) < mInitTranslationX && offset > 0
&& offset < 0.5 && !isClicked) {
if (mVisibleTabCount == 1) {
mScrollView.scrollTo(mTranslationX, 0);
scrollLocation = mTranslationX;
} else {
mScrollView.scrollTo(position * tabWidth, 0);
scrollLocation = position * tabWidth;
}
}
//滑动完成时,将标记位恢复
if (offset == 0) {
isClicked = false;
}
} public void setTabItemTitles(List<String> titles) {
if(titles != null && titles.size() > 0) {
this.removeAllViews();
for (String title : titles) {
addView(generateTextView(title));
}
} setItemClickEvent();
} /**
* 根据title创建tab
* @param title
* @return
*/
private View generateTextView(String title) {
TextView tv = new TextView(getContext());
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
lp.width = getScreenWidth() / mVisibleTabCount;
tv.setText(title);
tv.setGravity(Gravity.CENTER);
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
tv.setTextColor(COLOR_TEXT_NORMAL);
tv.setLayoutParams(lp);
return tv;
} /**
* 设置可见Tab数量
* @param count
*/
public void setVisibleTabCount(int count) {
mVisibleTabCount = count;
} /**
* 设置关联的ViewPager
* @param viewPager
* @param position
*/
public void setViewPager(ViewPager viewPager, int position) {
mViewPager = viewPager; viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
scroll(position, positionOffset);
if(mListener != null) {
mListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
}
} @Override
public void onPageSelected(int position) {
if(mListener != null) {
mListener.onPageSelected(position);
} highLightTextView(position);
} @Override
public void onPageScrollStateChanged(int state) {
if(mListener != null) {
mListener.onPageScrollStateChanged(state);
}
}
}); viewPager.setCurrentItem(position);
highLightTextView(position);
} /**
* 设置外层HorizontalScrollView
* @param scrollView
*/
@RequiresApi(api = Build.VERSION_CODES.M)
public void setScrollView(HorizontalScrollView scrollView) {
mScrollView = scrollView; mScrollView.setOnScrollChangeListener(new OnScrollChangeListener() {
@Override
public void onScrollChange(View view, int i, int i1, int i2, int i3) {
scrollLocation = i2;
}
});
} /**
* 高亮显示选中tab文本
* @param position
*/
public void highLightTextView(int position) {
View view;
for (int i = 0; i < getChildCount(); i++) {
view = getChildAt(i);
if(view instanceof TextView) {
((TextView) view).setTextColor(COLOR_TEXT_NORMAL);
}
}
view = getChildAt(position);
if(view instanceof TextView) {
((TextView) view).setTextColor(COLOR_TEXT_HIGHLIGHT);
}
} /**
* 设置Tab的点击事件
*/
public void setItemClickEvent() {
int cCount = getChildCount();
for (int i = 0; i < cCount; i++) {
final int j = i;
View view = getChildAt(i);
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
isClicked = true;
mViewPager.setCurrentItem(j);
}
});
}
} }

自定义ViewPagerIndicator-视图指示器的更多相关文章

  1. UICollectionView(集合视图)以及自定义集合视图

    一.UICollectionView集合视图           其继承自UIScrollView.         UICollectionView类是iOS6新引进的API,用于展示集合视图,布局 ...

  2. Android 自定义View修炼-自定义HorizontalScrollView视图实现仿ViewPager效果

    开发过程中,需要达到 HorizontalScrollView和ViewPager的效果,于是直接重写了HorizontalScrollView来达到实现ViewPager的效果. 实际效果图如下: ...

  3. 自定义View视图

    自定义View视图文件查找逻辑 之前MVC5和之前的版本中,我们要想对View文件的路径进行控制的话,则必须要对IViewEngine接口的FindPartialView或FindView方法进行重写 ...

  4. 自定义MVC视图引擎ViewEngine 创建Model的专属视图

    MVC内置的视图引擎有WebForm view engine和Razor view engine,当然也可以自定义视图引擎ViewEngine.本文想针对某个Model,自定义该Model的专属视图. ...

  5. Swift自定义头视图和尾视图

    var data: [[String]]! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup a ...

  6. ASP.NET MVC 自定义Razor视图WorkContext

    概述 1.在ASP.NET MVC项目开发的过程中,我们经常需要在cshtml的视图层输出一些公用信息 比如:页面Title.服务器日期时间.页面关键字.关键字描述.系统版本号.资源版本号等 2.普通 ...

  7. Office365学习笔记—Xslt自定义列表视图

    1,在Office365中需要添加自定义的视图!用Spd添加视图,这儿我添加一个testView! (1)打开testView.aspx将</ZoneTemplate>节点中的内容全部删除 ...

  8. 自定义ViewPagerIndicator

    1. 简介 学习Android,自定义View不可避免,之前一直忽视这块内容,现在开始学,应该不算太晚.从常见的ViewPagerIndicator开始,当然,万能的Github上包罗万象,好用的in ...

  9. 解读ASP.NET 5 & MVC6系列(16):自定义View视图文件查找逻辑

    之前MVC5和之前的版本中,我们要想对View文件的路径进行控制的话,则必须要对IViewEngine接口的FindPartialView或FindView方法进行重写,所有的视图引擎都继承于该IVi ...

  10. sap表维护工具来维护自定义表&视图簇的使用

    一.通过表维护工具维护自定义表 1.SE11创建表 2.se11界面的菜单:实用程序->Table Maintenance Generator其实这里就是调用SE54 3.sm30 调用维护好的 ...

随机推荐

  1. 动态页面技术之JSP

    1.什么是JSP技术 JSP全名为Java Server Pages,中文名叫java服务器页面,其根本是一个简化的Servlet设计,它是由Sun Microsystems公司倡导.许多公司参与一起 ...

  2. High Performance MySQL笔记:count

    在SQL中使用count()好像是非常自然的事情: SELECT COUNT(*) FROM TABLE_NAME; 有时候确实会想过,count(*)和单独的count(column_name)有什 ...

  3. BZOJ4568: [Scoi2016]幸运数字(线性基 倍增)

    题意 题目链接 Sol 线性基是可以合并的 倍增维护一下 然后就做完了?? 喵喵喵? // luogu-judger-enable-o2 #include<bits/stdc++.h> # ...

  4. JSTL总结摘要

    一 概述 1.什么是JSTL? JSP Standard Taglib,一个定义了一系列标签的标签库,以取代在JSP页面中嵌套的java代码,经常与EL结合使用,使页面风格统一,维护方便. JSTL标 ...

  5. JavaScript的进阶之路(六)理解函数

    函数:定义一次,多次调用:用于对象的属性则称为对象的方法:在JavaScript中,函数即对象:嵌套的函数形成闭包: 定义函数和简单调用函数: //函数定义 function f1(){ //没有参数 ...

  6. 【js常用DOM方法】

    介绍几个js DOM的常用方法 获取元素节点 getElementById  getElementsByTagName  getElementsByClassName 先写一个简单的网页做测试: /* ...

  7. 几个 h5页面效果和 自动 app 生成网站 微页

    用MAKA.易企秀.兔展就够了,MAKA和兔展用户体验好些,易企秀广告有点丑,不过模板多一些. 至于交互类工具,iH5.Mugeda.Epub360这三个里面选一个就行. -------------- ...

  8. CentOS6.5(3)----设置自己安装的程序开机自动启动

    CentOS6.5系统下设置自己安装的程序开机自动启动 方法1. 把启动程序的命令添加到 /etc/rc.d/rc.local 文件中,比如设置开机启动 mysqld: #!/bin/sh # # T ...

  9. Python - Exceptions

    官方文档:https://docs.python.org/3/library/exceptions.html 1. 使用try...except... 2. 输出错误信息的方式为: try: curs ...

  10. 线性表接口的实现_Java

    线性表是其组成元素间具有线性关系的一种线性结构,对线性表的基本操作主要有插入.删除.查找.替换等,这些操作可以在线性表的任何位置进行.线性表可以采用顺序存储结构和链式存储结构表示. 本接口的类属于da ...