项目做完了,写写博客,在项目中遇到的一些问题,或者是自己觉得很不错的东西。这一篇主要是想和大家分享一下我在项目中封装的一个东西,就是tab选项卡。先看看效果图:

我在网上看了很多有关选项卡的demo,可是发现都不太符合我的需求,万恶的产品经理想做的效果是选项卡中的文字有多长,文字下方的线就显示多长,无奈之下,自己写了。由于项目中很多地方都有用这个东东,所以我就封装了这一个,先看看代码。

这是封装的代码:

public class ViewPagerIndicator extends HorizontalScrollView implements
OnPageChangeListener, OnClickListener { private RelativeLayout[] tabArr;// tab数组
private String[] tabTexts;// tab标题数组
private int[] tabTextWidthArr;// tab标题宽度数组 private int currTabPosition;// 当前选中的tab
private float fromTransX;// 游标在启动动画之前的X轴坐标
private int tabSpacing;// tab之间的间距
private int cursorPadding;// tab默认和cursor长度一样
private int mTextColor = getResources().getColor(R.color.gray_666666);
private float mTextSize = 13;
private int tabLength;// tab个数
private int diviceWidth;// 设备宽度px
private float fromScaleX = 1.0f;
private int baseCursorWidth;// 初始化的游标宽度, 缩放动画每次以此为标准
private Boolean autoArrange = true;
private Boolean isPageFirstScrolled = true;
private int unSelectTextColor = getResources().getColor(R.color.gray_999999); //设置选中字体的颜色
private int selectTextColor = getResources().getColor(R.color.blue_45a7ff); //设置未选中字体的颜色 private Context mContext;
private ViewPager mViewPager;
private LinearLayout tabLy;// tab的横向线性布局
private ImageView cursor;// 游标
private Handler handler = new Handler();
View line; public ViewPagerIndicator(Context context) {
super(context);
// TODO Auto-generated constructor stub
init();
} public ViewPagerIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init();
} public ViewPagerIndicator(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
init();
} /**
* 初始化基本布局
*/
private void init() {
// TODO Auto-generated method stub
mContext = getContext();
diviceWidth = DensityUtil.getDisplayWidth((Activity) mContext);
// 设置属性
this.setBackgroundColor(getResources().getColor(R.color.white));
this.setHorizontalScrollBarEnabled(false);// 去掉滚动条
this.setVisibility(View.GONE);
// 加载ScrollView的内容布局
View v = View.inflate(mContext, R.layout.viewpager_indicator_layout, null);
tabLy = (LinearLayout) v.findViewById(R.id.main_tab);// Tab布局
cursor = (ImageView) v.findViewById(R.id.main_cursor);// 游标 line = v.findViewById(R.id.line); //获得中间那条线
this.addView(v);
} public void setLinevisibility(boolean isShow) {
line.setVisibility(isShow ? View.VISIBLE : View.GONE);
} /**
* 设置参数.
*
* @param tabSpacing tab间距
* @param cursorPadding 游标向左右延伸的距离, 默认为0, 也即和tab文本一样长
* @param viewPager 设置ViewPager
* @param tabTexts tab内容数组
* @param autoArrange 当tab长度不足屏幕宽度时, 是否自动进行摆列, 默认为true
*/
public void setParams(int tabSpacing, int cursorPadding, String[] tabTexts,
ViewPager viewPager, Boolean autoArrange) {
if (tabTexts == null || tabTexts.length < 1) {
return;
}
this.tabSpacing = tabSpacing;
this.cursorPadding = cursorPadding;
this.tabTexts = tabTexts;
this.mViewPager = viewPager;
this.autoArrange = autoArrange; this.setVisibility(View.VISIBLE);
initTabSpacing();
initTabs();
initCursor();
onPageSelected(currTabPosition);// 初始化tab样式和动画
if (mViewPager != null) {
mViewPager.setOnPageChangeListener(this);
}
} /**
* 确定tab间隙长度
*/
private void initTabSpacing() {
// TODO Auto-generated method stub
tabLength = tabTexts.length;
int tabTextsWidth = 0;// tab文本总长度
TextView tv = new TextView(mContext);
tabTextWidthArr = new int[tabLength];
for (int i = 0; i < tabLength; i++) {
tv.setTextSize(mTextSize);
tabTextWidthArr[i] = (int) tv.getPaint().measureText(tabTexts[i]);
tabTextsWidth += tabTextWidthArr[i];
}
int scrollViewWidth = tabTextsWidth + tabLength * tabSpacing;
// 默认, tab(包括间隙)总长度小于屏幕宽度时, 重新计算间距, 让各个tab均匀填满scrollview
if (autoArrange && scrollViewWidth < diviceWidth) {
tabSpacing = (diviceWidth - tabTextsWidth) / tabLength;
}
} /**
* 初始化Tab
*/
private void initTabs() {
tabLy.removeAllViews();
tabArr = new RelativeLayout[tabLength];
TextView tabTextView = null;
for (int i = 0; i < tabLength; i++) {
// 初始化tabArr
LinearLayout.LayoutParams tabParam = new LinearLayout.LayoutParams(
tabTextWidthArr[i] + tabSpacing, LayoutParams.MATCH_PARENT);
tabArr[i] = (RelativeLayout) View.inflate(mContext,
R.layout.viewpager_indicator_tab, null);
tabArr[i].setLayoutParams(tabParam);
tabArr[i].setTag(i);
tabArr[i].setOnClickListener(this);
// 初始化tabTextViewArr
tabTextView = (TextView) tabArr[i].findViewById(R.id.tab_tv);
tabTextView.setTextSize(mTextSize);
tabTextView.setTextColor(mTextColor);
tabTextView.setText(tabTexts[i]);
// 添加子tab
tabLy.addView(tabArr[i], i);
}
} @Override
public void onClick(View v) {
int i = (Integer) v.getTag();
setTabClick(i);
} /**
* 设置当前Tab点击时事件
*
* @param position
*/
private void setTabClick(int position) {
// 如果点击的为当前的Tab,则滚回到顶部, 否则切换
if (position == currTabPosition) { } else {
mViewPager.setCurrentItem(position);
}
} /**
* 初始化cursor长度
*/
private void initCursor() {
// TODO Auto-generated method stub
baseCursorWidth = tabTextWidthArr[currTabPosition] + cursorPadding;
RelativeLayout.LayoutParams cursorLp = (RelativeLayout.LayoutParams) cursor
.getLayoutParams();
cursorLp.width = baseCursorWidth;
cursor.setLayoutParams(cursorLp);
} @Override
public void onPageScrollStateChanged(int arg0) {
} @Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
} @Override
public void onPageSelected(final int position) {
// TODO Auto-generated method stub
currTabPosition = position;
setTabStyle(position);// 改变tab字体颜色
handler.post(new Runnable() { @Override
public void run() {
setTabAnimation(position);
}
});
} /**
* 设置未选中tab字体的颜色
*/
public void setUnSelectTextColor(int UnSelectTextColor) {
this.unSelectTextColor = UnSelectTextColor;
} /**
* 设置选中tab字体的颜色
*/
public void setSelectTextColor(int selectTextColor) {
this.selectTextColor = selectTextColor;
} /**
* 设置tab字体的大小
*/
public void setTextSize(int textSize){
this.mTextSize = textSize;
} /**
* 设置选中项背景和字体颜色
*
* @param position
*/
private void setTabStyle(int position) {
// 还原Tab的背景和字体颜色
for (int i = 0; i < tabLength; i++) {
((TextView) tabArr[i].getChildAt(0)).setTextColor(unSelectTextColor);
}
// 改变 选中文本的颜色, 同时红点消失
((TextView) tabArr[position].getChildAt(0)).setTextColor(selectTextColor);
} /**
* 设置tab的动画
*
* @param position
*/
private void setTabAnimation(final int position) {
// 选中的tab中心位置到scrollview最左边位置的距离
int offset = 0;
for (int i = 0; i < position; i++) {
offset += tabTextWidthArr[i] + tabSpacing;
}
offset += (tabTextWidthArr[position] + tabSpacing) / 2;
// tab滚动到居中位置
int scrollOffset = offset - diviceWidth / 2 <= 0 ? 0 : offset
- diviceWidth / 2;
smoothScrollTo(scrollOffset, 0); // 移动动画
offset -= (tabTextWidthArr[0] / 2 + cursorPadding / 2); Animation translateAnim = new TranslateAnimation(isPageFirstScrolled ? offset : fromTransX, offset, 0,
0);
fromTransX = offset;
isPageFirstScrolled = false; // 缩放动画, 以初始化的cursor为缩放参考
offset = tabTextWidthArr[currTabPosition] + cursorPadding;
float toScaleX = (float) offset / (float) baseCursorWidth;
Animation scaleAnim = new ScaleAnimation(fromScaleX, toScaleX, 1.0f,
1.0f, Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);// 中间为缩放中心
fromScaleX = toScaleX; // 将两个动画添加进集合, 同时执行
AnimationSet anim = new AnimationSet(true);
anim.addAnimation(scaleAnim); // 注意: 先添加缩放动画, 否则会出问题, 原因不知
anim.addAnimation(translateAnim);
anim.setDuration(300);
anim.setFillAfter(true);
cursor.startAnimation(anim); // 开始动画
} }
viewpager_indicator_layout文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"> <View
android:id="@+id/line"
android:layout_width="1px"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:background="@color/gray_cccccc"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:visibility="gone"
/> <LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> <LinearLayout
android:id="@+id/main_tab"
android:layout_width="wrap_content"
android:layout_height="0dip"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="horizontal" /> <View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/gray_cccccc" />
</LinearLayout> <ImageView
android:id="@+id/main_cursor"
android:layout_width="wrap_content"
android:layout_height="2dip"
android:layout_alignParentBottom="true"
android:scaleType="matrix"
android:src="@drawable/youdan_cursor_bg" /> </RelativeLayout>

然后在布局文件中用:
<com.manqian.mqlibrary.view.ViewPagerIndicator
android:id="@+id/horizontal_scrollview"
android:layout_width="match_parent"
android:layout_height="47dp" /> <android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"/> 这里我的说一下,
com.manqian.mqlibrary.view.ViewPagerIndicator  这个是你把这个封装的文件放在项目的路径,这个是我的路径,有的同学就会直接复制过去,发现报错,要会灵活一点。
好了,我先说说一下我的思路,大家可以看到,我封装的时候继承了什么吧,对的,就是这个horizontalscrollview,这个是水平的scrollview,也就是说是它可以使得tab可以水平滑动,还有我实现了几个监听器,通过监听器中的几个方法,从中配合来实现这个功能,具体的,我在代码上注释的比较清楚了。希望对大家有用。

												

android tab选项卡的使用的更多相关文章

  1. <Android>tab选项卡

    1.继承TabActivity实现 a)         在布局文件中使用FrameLayout列出Tab组件及Tab中的内容组件 b)        Activity要继承TabActivity c ...

  2. Android Tab -- 使用ViewPager、Fragment、FragmentPagerAdapter来实现

    原文地址:http://blog.csdn.net/crazy1235/article/details/42678877 效果:滑动切换:点击标签切换. 代码:https://github.com/l ...

  3. Android Tab -- 使用Fragment、FragmentManager来实现

    原文地址:http://blog.csdn.net/crazy1235/article/details/42678877 效果: 代码:https://github.com/ldb-github/La ...

  4. Ionic入门七:ionic tab(选项卡)

    ionic tab(选项卡) 是水平排列的按钮或者链接,用以页面间导航的切换.它可以包含文字和图标的组合,是一种移动设备上流行的导航方法. 1.基本用法 以下选项卡容器使用了 tabs 类,每个选项卡 ...

  5. iOS开发-iPad侧边栏Tab选项卡切换

    Android中习惯了叫侧边栏,iOS中如果不习惯侧边栏称呼的话可以叫dock,侧边栏的切换,类似于Android中的底部导航栏的切换,iPad尺寸大了一些,导航的栏目放在侧边会显示的更好耐看一些.选 ...

  6. Android中选项卡功能的实现

    Android中选项卡功能的实现 Android中使用TabHost和TabWidget来实现选项卡功能.TabHost必须是布局的根节点,它包含两个子节点: TabWidget,显示选项卡: Fra ...

  7. ionic-CSS:ionic tab(选项卡)

    ylbtech-ionic-CSS:ionic tab(选项卡) 1.返回顶部 1. ionic tab(选项卡) ionic tab(选项卡) 是水平排列的按钮或者链接,用以页面间导航的切换.它可以 ...

  8. 基于CkEditor实现.net在线开发之路(4)快速布局,工具箱,模板载入,tab选项卡简单说明与使用

    上一章给常用的from表单控件属性页面,进行了简单说明和介绍,但是由于是在网页中做界面设计,操作肯定没有桌面应用程序方便,便捷,为了更方便的布局与设计,今天我主要说一下快速布局,工具箱,tab选项卡, ...

  9. 可轮播滚动的Tab选项卡

    前段时间有试着搭建个后台主题ui框架,有用到可支持滚动的Tab选项卡,模仿着H+后台主题ui框架中的代码造轮子改造了下,可惜代码在公司,不能把代码外发出来(感觉这样被限制了很多,对于这样的公司没办法, ...

随机推荐

  1. BZOJ3505 [Cqoi2014]数三角形

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  2. <<< php程序在运行后报“internal server error”错误

    上传的php程序在运行后报“internal server error”错误,检查以下两方面: 1.请您检查php程序的属性是否设置为755,如果php程序的属性不是755,那么运行的时候会报“int ...

  3. <<< chm格式文件打不开及一些问题

    CHM 意为 Compiled HTML.以CHM为扩展名的文件图标通常为一个带问号的文档图标,表示帮助文档,是 Microsoft 自 Windows 98 以来提供的一种帮助文档格式的文件,用于替 ...

  4. red hat关于桥接模式连不上外网或者没有IP

    很多人·在启动虚拟机后连接不上外网,即ifconfig没有ip地址,我总结了一下需要注意的地方: 以下全是在桥接模式. 1.在windows中打开任务管理器-->服务中找到一下几个服务,确保它们 ...

  5. web前端基础知识-(三)JavaScript基本操作

    JavaScript 是一种轻量级的编程语言. JavaScript 是可插入 HTML 页面的编程代码. JavaScript 插入 HTML 页面后,可由所有的现代浏览器执行. JavaScrip ...

  6. Windows操作系统

    Microsoft Windows,是美国微软公司研发的一套操作系统,它问世于1985年,起初仅仅是Microsoft-DOS模拟环境,后续的系统版本由于微软不断的更新升级,不但易用,也慢慢的成为家家 ...

  7. linux中ldconfig的使用介绍

    linux中ldconfig的使用介绍 ldconfig是一个动态链接库管理命令,其目的为了让动态链接库为系统所共享. ldconfig的主要用途: 默认搜寻/lilb和/usr/lib,以及配置文件 ...

  8. 电商总结(五)移动M站建设

    最近在一直在搞M站,也就是移动web站点.由于是第一次,也遇到了很多问题,所以把最近了解到的东西总结总结.聊一聊什么是移动M站,它有啥作用和优势. 也有人会问,M站和APP有什么不同? 1. APP ...

  9. [NHibernate]存储过程的使用(一)

    目录 写在前面 文档与系列文章 Nhibernate中使用存储过程 一个例子 总结 写在前面 上篇文章一个小插曲,分析了延迟加载是如何解决N+1 select查询问题的.这篇开始介绍在nhiberna ...

  10. Spring实战 (第3版)——AOP

    在软件开发中,分布于应用中多处的功能被称为横切关注点.通常,这些横切关注点从概念上是与应用的 业务逻辑相分离的(但是往往直接嵌入到应用的业务逻辑之中).将这些横切关注点与业务逻辑相分离正是 面向切面编 ...