这是一个可滑动的标签栏的自定义控件,参考此文章http://blog.csdn.net/fx_sky/article/details/8990573,我将主要的功能整合成一个类,配上2个特定的布局即可使用。 
效果图:

主要布局文件:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="vertical" >
  6. <RelativeLayout
  7. android:id="@+id/rl_nav"
  8. android:layout_width="fill_parent"
  9. android:layout_height="wrap_content"
  10. android:layout_gravity="top" >
  11.  
  12. <RadioGroup
  13. android:id="@+id/rg_nav_content"
  14. android:layout_width="fill_parent"
  15. android:layout_height="38dip"
  16. android:layout_alignParentTop="true"
  17. android:background="#F2F2F2"
  18. android:orientation="horizontal" >
  19. </RadioGroup>
  20.  
  21. <ImageView
  22. android:id="@+id/iv_nav_indicator"
  23. android:layout_width="1dip"
  24. android:layout_height="5dip"
  25. android:layout_alignParentBottom="true"
  26. android:background="#FF0000"
  27. android:contentDescription="@string/mygo_share"
  28. android:scaleType="matrix" />
  29. </RelativeLayout>
  30. </LinearLayout>

标签的布局: 
sync_nav_radiogroup_item.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RadioButton xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="0dip"
  4. android:layout_height="fill_parent"
  5. android:background="#F2F2F2"
  6. android:button="@null"
  7. android:checked="true"
  8. android:gravity="center"
  9. android:textSize="15sp" />

以下是工具类代码:

  1. import android.app.Activity;
  2. import android.content.Context;
  3. import android.support.v4.view.ViewPager;
  4. import android.util.AttributeSet;
  5. import android.util.DisplayMetrics;
  6. import android.view.LayoutInflater;
  7. import android.view.View;
  8. import android.view.ViewGroup;
  9. import android.view.animation.LinearInterpolator;
  10. import android.view.animation.TranslateAnimation;
  11. import android.widget.HorizontalScrollView;
  12. import android.widget.ImageView;
  13. import android.widget.RadioButton;
  14. import android.widget.RadioGroup;
  15. import android.widget.RadioGroup.OnCheckedChangeListener;
  16.  
  17. public class SyncHorizontalScrollView extends HorizontalScrollView {
  18.  
  19. private View view;
  20. private ImageView leftImage;
  21. private ImageView rightImage;
  22. private int windowWitdh = ;
  23. private Activity mContext;
  24. private RadioGroup rg_nav_content;
  25. private ImageView iv_nav_indicator;
  26. private LayoutInflater mInflater;
  27. private int count;// 屏幕显示的标签个数
  28. private int indicatorWidth;// 每个标签所占的宽度
  29. private int currentIndicatorLeft = ;// 当前所在标签页面的位移
  30. private ViewPager mViewPager;
  31. private int scrollX;
  32.  
  33. public SyncHorizontalScrollView(Context context) {
  34. super(context);
  35. // TODO Auto-generated constructor stub
  36. }
  37.  
  38. public SyncHorizontalScrollView(Context context, AttributeSet attrs) {
  39. super(context, attrs);
  40. // TODO Auto-generated constructor stub
  41. }
  42.  
  43. /**
  44. *
  45. * 方法描述:
  46. * @param mViewPager
  47. * @param leftImage 左箭頭
  48. * @param rightImage 右箭頭
  49. * @param tabTitle 標籤欄的名稱
  50. * @param count 一頁顯示的標籤個數
  51. * @param context
  52. * <pre>
  53. * 修改日期 修改人 修改说明
  54. * 2014-2-17 chen 新建
  55. * </pre>
  56. */
  57. public void setSomeParam(ViewPager mViewPager, ImageView leftImage,
  58. ImageView rightImage, String[] tabTitle, int count, Activity context) {
  59. this.mContext = context;
  60. this.mViewPager = mViewPager;
  61. // this.view = view;
  62. mInflater = LayoutInflater.from(context);
  63. this.view = mInflater.inflate(R.layout.sync_hsv_item, null);
  64. this.addView(view);
  65. this.leftImage = leftImage;
  66. this.rightImage = rightImage;
  67. DisplayMetrics dm = new DisplayMetrics();
  68. context.getWindowManager().getDefaultDisplay().getMetrics(dm);
  69. windowWitdh = dm.widthPixels;
  70. this.count = count;
  71. indicatorWidth = windowWitdh / count;
  72. init(tabTitle);
  73. }
  74.  
  75. private void init(String[] tabTitle) {
  76. rg_nav_content = (RadioGroup) view.findViewById(R.id.rg_nav_content);
  77. iv_nav_indicator = (ImageView) view.findViewById(R.id.iv_nav_indicator);
  78. initIndicatorWidth();
  79. initNavigationHSV(tabTitle);
  80. setListener();
  81. }
  82.  
  83. // 初始化滑动下标的宽
  84. private void initIndicatorWidth() {
  85. ViewGroup.LayoutParams cursor_Params = iv_nav_indicator
  86. .getLayoutParams();
  87. cursor_Params.width = indicatorWidth;
  88. iv_nav_indicator.setLayoutParams(cursor_Params);
  89. }
  90.  
  91. // 添加顶部标签
  92. private void initNavigationHSV(String[] tabTitle) {
  93. rg_nav_content.removeAllViews();
  94. for (int i = ; i < tabTitle.length; i++) {
  95. RadioButton rb = (RadioButton) mInflater.inflate(
  96. R.layout.sync_nav_radiogroup_item, null);
  97. rb.setId(i);
  98. rb.setText(tabTitle[i]);
  99. rb.setLayoutParams(new LayoutParams(indicatorWidth,
  100. LayoutParams.MATCH_PARENT));
  101. rg_nav_content.addView(rb);
  102. }
  103. RadioButton rb = (RadioButton) mInflater.inflate(
  104. R.layout.sync_nav_radiogroup_item, null);
  105. rg_nav_content.addView(rb);
  106.  
  107. }
  108.  
  109. private void setListener() {
  110. rg_nav_content
  111. .setOnCheckedChangeListener(new OnCheckedChangeListener() {
  112. @Override
  113. public void onCheckedChanged(RadioGroup group, int checkedId) {
  114. if (rg_nav_content.getChildAt(checkedId) != null) {
  115. moveAnimation(checkedId);
  116. mViewPager.setCurrentItem(checkedId); // ViewPager
  117. // 跟随一起 切换
  118. }
  119. }
  120. });
  121. }
  122. //动画移动效果
  123. private void moveAnimation(int checkedId){
  124. TranslateAnimation animation = new TranslateAnimation(currentIndicatorLeft,
  125. indicatorWidth * checkedId,0f, 0f);
  126. animation.setInterpolator(new LinearInterpolator());
  127. animation.setDuration();
  128. animation.setFillAfter(true);
  129.  
  130. // 执行位移动画
  131. iv_nav_indicator.startAnimation(animation);
  132.  
  133. // 记录当前 下标的距最左侧的 距离
  134. currentIndicatorLeft = indicatorWidth * checkedId;
  135. scrollX = (checkedId > ? currentIndicatorLeft: )- indicatorWidth * ;
  136. this.post(runnable);
  137. }
  138.  
  139. // 模拟点击事件
  140. public void performLabelClick(int position) {
  141. if (rg_nav_content != null && rg_nav_content.getChildCount() > position) {
  142. ((RadioButton) rg_nav_content.getChildAt(position)).performClick();
  143. }
  144. }
  145.  
  146. private Runnable runnable = new Runnable() {
  147.  
  148. @Override
  149. public void run() {
  150. // TODO Auto-generated method stub
  151. smoothScrollTo(scrollX, );
  152. }
  153. };
  154.  
  155. // 显示和隐藏左右两边的箭头
  156. protected void onScrollChanged(int l, int t, int oldl, int oldt) {
  157. super.onScrollChanged(l, t, oldl, oldt);
  158. if (!mContext.isFinishing() && view != null && rightImage != null
  159. && leftImage != null) {
  160. if (view.getWidth() <= windowWitdh) {
  161. leftImage.setVisibility(View.GONE);
  162. rightImage.setVisibility(View.GONE);
  163. } else {
  164. if (l == ) {
  165. leftImage.setVisibility(View.GONE);
  166. rightImage.setVisibility(View.VISIBLE);
  167. } else if (view.getWidth() - l == windowWitdh) {
  168. leftImage.setVisibility(View.VISIBLE);
  169. rightImage.setVisibility(View.GONE);
  170. } else {
  171. leftImage.setVisibility(View.VISIBLE);
  172. rightImage.setVisibility(View.VISIBLE);
  173. }
  174. }
  175. }
  176. }
  177. public int getIndicatorWidth(){
  178. return indicatorWidth;
  179. }
  180. }

在调用时,先调用setSomeParam方法将需要用的的控件与数据传入,然后控件内部开始初始化。 
由于项目有需求,要在进入此控件使用到的页面时,自动定位到某一个标签,在此需使用View.post方法执行HorizontalScrollView 控件的smoothScrollTo方法,才能确保进入页面后标签已定位。原因是scrollTo方法要等到界面显示完毕才能有效,而view.post方法也是在界面刷新完毕之后才执行。 
定义一个performLabelClick方法,让外部调用此类来实现相应的页面跳转即可。

不过此处使用时有一个问题,就是从上一级页面跳转至此页面时,无法固定在最后一个标签位,调试时发现虽然执行了performLabelClick方法模拟点击事件,但是监听事件并没有被响应。暂时没找出问题所在。不过用了一个方法来解决此问题,即在调用initNavigationHSV方法添加标签时,为其多加一个空标签,宽度为0即可,这样即可解决标签栏上无法定位到最后一位的问题,因为真正的最后一位实际上是宽度为0的空标签。 
如果大家有遇到此问题或是有解决方法,欢迎告知,谢谢。

附上代码下载地址: 
http://www.oschina.net/code/snippet_1409622_33243

  1.  

ViewPager + HorizontalScrollView 实现可滚动的标签栏的更多相关文章

  1. android Viewpager HorizontalScrollView 实现分页栏拖拽

    源码:http://files.cnblogs.com/android100/ViewPaperDemo.rar首先我们先看一个效果:  前两个是网易的,它做的title不能拖拽,.不过点击动画效果挺 ...

  2. Android ViewPager+HorizontalScrollView实现标题栏滑动(腾讯新闻)

    1) ViewPager提供了左右滑动切换页面的方法,但是它所提供的标题只是无语,估计没有真正的项目会照搬拿过来;并且它只能一页一页滑,我想直接查看最后一页要滑半天; 2) 看了腾讯新闻客户端感觉体验 ...

  3. 使用TabLayout快速实现一个导航栏

    在没有Material Design的年代,要实现一个类似微信主页面的效果,我们有以下几种解决方案: 1.Fragment + ViewPager  +  RadioGroup自定义固定导航条 2.F ...

  4. viewpager+fragment+HorizontalScrollView详细版

    XML布局 <HorizontalScrollView            android:id="@+id/hsv"            android:layout_ ...

  5. viewpager+fragment+HorizontalScrollView

    xml布局 <RelativeLayout        android:id="@+id/rl_column"        android:layout_width=&q ...

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

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

  7. Android重写HorizontalScrollView仿ViewPager效果

    Android提供的ViewPager类太复杂,有时候没有必要使用,所以重写一个HorizontalScrollView来实现类似的效果,也可以当做Gallery来用 思路很简单,就是重写onTouc ...

  8. 禁用滚动视图ListView、ViewPager、ScrollView、HorizontalScrollView、WebView边界颜色渐变

    禁用滚动视图ListView.ViewPager.ScrollView.HorizontalScrollView.WebView边界颜色渐变 ListView.ViewPager.ScrollView ...

  9. Android重写HorizontalScrollView模仿ViewPager效果

    Android提供的ViewPager类太复杂,有时候没有必要使用,所以重写一个HorizontalScrollView来实现类似的效果,也可以当做Gallery来用 思路很简单,就是重写onTouc ...

随机推荐

  1. div中嵌套div速度将会同样很慢

    ---恢复内容开始--- div中嵌套了div速度将会同样很慢   最近很多老板在我们公司做企业站的时候都会要求说:我要div+css的,不要表格建的那种,那样不利于优化.但我们发现就算给他们用div ...

  2. linux配置jdk环境详解

    环境:Redhat Server 5.1(虚拟机) 工具:Xftp4  jdk-7-linux-i586.rpm文件 步骤1:把jdk-7-linux-i586.rpm文件拷贝到/usr/local目 ...

  3. JDK Debug

    http://ishare.iask.sina.com.cn/f/23897007.html http://hi.baidu.com/bd_hare/item/7edd0415b60f0101e65c ...

  4. WIN ERROR:C:\Windows\System32\<LANG_NAME>\mstsc.exe.MUI

    Issue: When you upgrade Win7, you may found your remote desktop will not work. You may get following ...

  5. coroutine

    在脚本语言中,coroutine 不是个新鲜词汇,比如 lua 内建 coroutine,python中的greenlet,但在C程序中,并不是太常见. windows 下有 fiber,相关函数为 ...

  6. 普林斯顿大学算法课 Algorithm Part I Week 3 归并排序 Mergesort

    起源:冯·诺依曼最早在EDVAC上实现 基本思想: 将数组一分为(Divide array into two halves) 对每部分进行递归式地排序(Recursively sort each ha ...

  7. 关于ztree打开关闭所有节点,选中指定id节点

    var isOneByOneExpand=false;//是否递归展开 //展开节点 function expendNode(nodeId){ var node = treeObj.getNodeBy ...

  8. Struts 2.3.4.1完整示例

    [系统环境]Windows 7 Ultimate 64 Bit [开发环境]JDK1.6.21,Tomcat6.0.35,MyEclipse10 [其他环境]Struts2.3.4.1 [项目描述]S ...

  9. Apache的Access.log分析总结

    Apache的Access.log分析总结 #查看80端口的tcp连接  #netstat -tan | grep "ESTABLISHED" | grep ":80&q ...

  10. webpack入门笔记

    此为第一篇主要是webpack入门笔记: http://if-true.com/2015/10/16/webpack-tutorial-translate.html