项目做完了,写写博客,在项目中遇到的一些问题,或者是自己觉得很不错的东西。这一篇主要是想和大家分享一下我在项目中封装的一个东西,就是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. js,java,浮点数运算错误及应对方法

    js,java浮点数运算错误及应对方法 一,浮点数为什么会有运算错误 IEEE 754 标准规定了计算机程序设计环境中的二进制和十进制的浮点数自述的交换.算术格式以及方法. 现有存储介质都是2进制.2 ...

  2. 编程结构:Promise和Future

    非阻塞模型中Promise,Future 和 Callback一些比较常用的模型: Future表示一个可能还没有实际完成的异步任务结果:实际在编程中,应用future数据结构的时候,你得到并不是一个 ...

  3. Codeforces Round #342 (Div. 2) A. Guest From the Past(贪心)

    传送门 Description Kolya Gerasimov loves kefir very much. He lives in year 1984 and knows all the detai ...

  4. eclipse项目部署路径

    1.项目名点击右键 2.选择Build Path   ------>Configure Build Path... 3.选择Source  ----->Default output fol ...

  5. 使用VS2010创建WebService 发布、测试

    http://blog.sina.com.cn/s/blog_45eaa01a0102vopl.html 1 打开VS2010,菜单    文件->新建->项目 2 选择[ASP.net ...

  6. 原生JS常用代码汇总

    数组相关 var codes = new Array( ); //创建数组codes.length //数组长度 动态插入数组 codes.push(value);

  7. filterHTML

    function filterHTML(source) { return !source ? "" : source.replace(/]*>/g, "" ...

  8. 1.0、Struts2的简单搭建方法

    一.Struts2:是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet:用于jsp页面与Java代码之间的交互. 1.核心:Filter拦截器,对所有的请求进行拦截. 2.工作 ...

  9. MySQL字段自增长AUTO_INCREMENT的学习笔记

    1.创建表时指定AUTO_INCREMENT自增值的初始值(即起始值): CREATE TABLE XXX (ID INT(5) PRIMARY KEY AUTO_INCREMENT) AUTO_IN ...

  10. PHP函数 addslashes() 和 mysql_real_escape_string() 的区别 && SQL宽字节,绕过单引号注入攻击

    首先:不要使用 mysql_escape_string(),它已被弃用,请使用 mysql_real_escape_string() 代替它. mysql_real_escape_string() 和 ...