HorizontalScrollView 仿真 tabLayout

HorizontalScrollView 仿真 tabLayout别人微博的网址http://blog.csdn.net/u013835855/article/details/71159888目前滑动指示器最著名的是JakeWarton的ViewpagerIndicator,用别人的东西固然方便,但是也带来很多使用上的疑惑,这篇博客,我们使用HorizontalScrollView自己写一个viewPager指示器。这里首先说一下很多自己写的indi

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

别人微博的 网址 http://blog.csdn.net/u013835855/article/details/71159888

目前滑动指示器最著名的是JakeWarton的ViewpagerIndicator,用别人的东西固然方便,但是也带来很多使用上的疑惑,这篇博客,我们使用HorizontalScrollView自己写一个viewPager指示器。

这里首先说一下很多自己写的indicator只限于可视范围内不能移动的指示器,所以tab的数量有限,一般最多五个就已经很拥挤了,可是我们发现开源的ViewpagerIndicator有一个很棒的效果就是不用限定tab的个数,并且当前选中的tab将处于中间位置(两边不可滑动范围除外),这一点我便想到了利用HorizontalScrollView来实现这个效果。而tab的显示我使用TextView就行动态加载,然后把tab放到HorizontalScrollView中,在这里注意一个问题,那就是HorizontalScrollView本身的子view个数是有限定的,只能是一个,这一点跟scrollview一样,源码是这样的:

  1. @Override  
  2.     public void addView(View child) {  
  3.         if (getChildCount() > 0) {  
  4.             throw new IllegalStateException(“HorizontalScrollView can host only one direct child”);  
  5.         }  
  6.   
  7.         super.addView(child);  
  8.     }  

我们可以看到如果getChildCount()的个数大于零,就会抛出异常,所以这里我使用一个LinearLayout先包裹所有的textview然后再把LinearLayout放入HorizontalScrollView中,这样就不会抛异常了。代码如下:

  1. LinearLayout linearLayout = new LinearLayout(context);  
  2.        linearLayout.setOrientation(LinearLayout.HORIZONTAL);  
  3.        linearLayout.setLayoutParams(new LinearLayout.LayoutParams(count*tabWidth, LinearLayout.LayoutParams.MATCH_PARENT));  
  4.        for (int i = 0; i < count; i++)  
  5.        {  
  6.            TextView tv = new TextView(getContext());  
  7.            LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(tabWidth,  
  8.                    LinearLayout.LayoutParams.MATCH_PARENT);  
  9.            tv.setGravity(Gravity.CENTER);  
  10.            tv.setTextColor(COLOR_TEXT_NORMAL);  
  11.            tv.setText(titles[i]);  
  12.            tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);//字体大小  
  13.            tv.setLayoutParams(lp);  
  14.            final int finalI = i;  
  15.            tv.setOnClickListener(new OnClickListener()  
  16.            {  
  17.                @Override  
  18.                public void onClick(View v)  
  19.                {  
  20.                    if(viewPager!=null){  
  21.                        viewPager.setCurrentItem(finalI);  
  22.                    }  
  23.                }  
  24.            });  
  25.            linearLayout.addView(tv);  
  26.        }  
  27.        addView(linearLayout);  

而HorizontalScrollView中那个下划线效果,通过dispatchDraw方法实现

  1. @Override  
  2.     protected void dispatchDraw(Canvas canvas)  
  3.     {  
  4.         super.dispatchDraw(canvas);  
  5.         canvas.save();  
  6.         canvas.translate(mTranslationX, getHeight() – lineheight);  
  7.         canvas.drawLine(00, tabWidth, 0, mPaint);//(startX, startY, stopX, stopY, paint)  
  8.         canvas.restore();  
  9.     }  

其滑动效果则通过监听viewpager滑动的OnPageChangeListener接口中的onPageScrolled函数实现,我们知道onPageScrolled有三个参数起源吗如下:

  1. /** 
  2.          * This method will be invoked when the current page is scrolled, either as part 
  3.          * of a programmatically initiated smooth scroll or a user initiated touch scroll. 
  4.          * 
  5.          * @param position Position index of the first page currently being displayed. 
  6.          *                 Page position+1 will be visible if positionOffset is nonzero. 
  7.          * @param positionOffset Value from [0, 1) indicating the offset from the page at position. 
  8.          * @param positionOffsetPixels Value in pixels indicating the offset from position. 
  9.          */  
  10.         void onPageScrolled(int position, float positionOffset, int positionOffsetPixels);  

通过源码可知,第一个参数是当前的位置,第二个参数比较有意思,是指滑动距离相对于整个viewpager宽度的百分比,第三个是滑动的真正距离。这里我们利用第二个参数实现跟随滑动效果。这里我封装了一个函数如下:

  1. public void scroll(int position, float offset)  
  2.     {  
  3.         mTranslationX = tabWidth * (position + offset);  
  4.         scrollTo((int)mTranslationX-(SCREEN_WIDTH-tabWidth)/20);  
  5.         invalidate();  
  6.     }  

解释一下,我们将position和offse(百分比)传进去首先计算下划线应该滑动到的初始位置,然后利用scrollTo函数将HorizontalScrollView进行移动,最后重绘,于是就到达了滑动跟随的效果。全部源码如下:

  1. package com.zp.scrolltest;  
  2.   
  3. import android.content.Context;  
  4. import android.graphics.Canvas;  
  5. import android.graphics.Color;  
  6. import android.graphics.Paint;  
  7. import android.support.v4.view.ViewPager;  
  8. import android.util.AttributeSet;  
  9. import android.util.TypedValue;  
  10. import android.view.Gravity;  
  11. import android.view.View;  
  12. import android.widget.HorizontalScrollView;  
  13. import android.widget.LinearLayout;  
  14. import android.widget.TextView;  
  15.   
  16. /** 
  17.  * Created by ez on 2017/5/4. 
  18.  */  
  19.   
  20. public class MyIndicator extends HorizontalScrollView implements ViewPager.OnPageChangeListener{  
  21.   
  22.     private static final int COLOR_TEXT_NORMAL = 0xFF000000;  
  23.     private static final int COLOR_INDICATOR_COLOR = Color.BLACK;  
  24.   
  25.     private Context context;  
  26.     private  int tabWidth;  
  27.     private String[] titles;  
  28.     private int count;  
  29.     private Paint mPaint;  
  30.     private float mTranslationX;  
  31.     private ViewPager viewPager;  
  32.     private int SCREEN_WIDTH;  
  33.     private float lineheight = 2.0f;  
  34.   
  35.     public MyIndicator(Context context) {  
  36.         this(context, null);  
  37.     }  
  38.   
  39.     public MyIndicator(Context context, AttributeSet attrs) {  
  40.         super(context, attrs);  
  41.         init(context);  
  42.     }  
  43.   
  44.     public MyIndicator(Context context, AttributeSet attrs, int defStyleAttr) {  
  45.         super(context, attrs, defStyleAttr);  
  46.         init(context);  
  47.     }  
  48.   
  49.     private void init(Context context){  
  50.         this.context = context;  
  51.         mPaint = new Paint();  
  52.         mPaint.setColor(COLOR_INDICATOR_COLOR);  
  53.         mPaint.setStrokeWidth(lineheight);//底部指示线的宽度  
  54.         setHorizontalScrollBarEnabled(false);  
  55.         SCREEN_WIDTH = context.getResources().getDisplayMetrics().widthPixels;  
  56.     }  
  57.   
  58.     public void setLineheight(float height){  
  59.         this.lineheight = height;  
  60.         mPaint.setStrokeWidth(lineheight);//底部指示线的宽度  
  61.     }  
  62.   
  63.     public void setViewPager(ViewPager viewPager){  
  64.         this.viewPager = viewPager;  
  65.         viewPager.addOnPageChangeListener(this);  
  66.     }  
  67.   
  68.     public void setTitles(String[] titles){  
  69.         this.titles = titles;  
  70.         count = titles.length;  
  71.         tabWidth = SCREEN_WIDTH/4;  
  72.         generateTitleView();  
  73.     }  
  74.   
  75.     @Override  
  76.     protected void onSizeChanged(int w, int h, int oldw, int oldh) {  
  77.         super.onSizeChanged(w, h, oldw, oldh);  
  78.         tabWidth = SCREEN_WIDTH/4;  
  79.     }  
  80.   
  81.     @Override  
  82.     protected void dispatchDraw(Canvas canvas)  
  83.     {  
  84.         super.dispatchDraw(canvas);  
  85.         canvas.save();  
  86.         canvas.translate(mTranslationX, getHeight() – lineheight);  
  87.         canvas.drawLine(00, tabWidth, 0, mPaint);//(startX, startY, stopX, stopY, paint)  
  88.         canvas.restore();  
  89.     }  
  90.   
  91.     public void scroll(int position, float offset)  
  92.     {  
  93.         mTranslationX = tabWidth * (position + offset);  
  94.         scrollTo((int)mTranslationX-(SCREEN_WIDTH-tabWidth)/20);  
  95.         invalidate();  
  96.     }  
  97.   
  98.     private void generateTitleView()  
  99.     {  
  100.         if (getChildCount() > 0)  
  101.             this.removeAllViews();  
  102.         count = titles.length;  
  103.   
  104.         LinearLayout linearLayout = new LinearLayout(context);  
  105.         linearLayout.setOrientation(LinearLayout.HORIZONTAL);  
  106.         linearLayout.setLayoutParams(new LinearLayout.LayoutParams(count*tabWidth, LinearLayout.LayoutParams.MATCH_PARENT));  
  107.         for (int i = 0; i < count; i++)  
  108.         {  
  109.             TextView tv = new TextView(getContext());  
  110.             LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(tabWidth,  
  111.                     LinearLayout.LayoutParams.MATCH_PARENT);  
  112.             tv.setGravity(Gravity.CENTER);  
  113.             tv.setTextColor(COLOR_TEXT_NORMAL);  
  114.             tv.setText(titles[i]);  
  115.             tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);//字体大小  
  116.             tv.setLayoutParams(lp);  
  117.             final int finalI = i;  
  118.             tv.setOnClickListener(new OnClickListener()  
  119.             {  
  120.                 @Override  
  121.                 public void onClick(View v)  
  122.                 {  
  123.                     if(viewPager!=null){  
  124.                         viewPager.setCurrentItem(finalI);  
  125.                     }  
  126.                 }  
  127.             });  
  128.             linearLayout.addView(tv);  
  129.         }  
  130.         addView(linearLayout);  
  131.     }  
  132.   
  133.     @Override  
  134.     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {  
  135.         scroll(position, positionOffset);  
  136.     }  
  137.   
  138.     @Override  
  139.     public void onPageSelected(int position) {  
  140.   
  141.     }  
  142.   
  143.     @Override  
  144.     public void onPageScrollStateChanged(int state) {  
  145.   
  146.     }  
  147. }  

最后说一下使用,首先在XML中像普通组件一样使用:

  1. <?xml version=“1.0” encoding=“utf-8”?>  
  2. <LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”  
  3.     xmlns:tools=“http://schemas.android.com/tools”  
  4.     android:id=“@+id/activity_main”  
  5.     android:orientation=“vertical”  
  6.     android:layout_width=“match_parent”  
  7.     android:layout_height=“match_parent”  
  8.     tools:context=“com.zp.scrolltest.MainActivity”>  
  9.   
  10.     <com.zp.scrolltest.MyIndicator  
  11.         android:layout_width=“wrap_content”  
  12.         android:layout_height=“40dp”  
  13.         android:background=“@android:color/holo_blue_bright”  
  14.         android:id=“@+id/indicador”/>  
  15.   
  16.     <android.support.v4.view.ViewPager  
  17.         android:layout_width=“match_parent”  
  18.         android:layout_height=“match_parent”  
  19.         android:id=“@+id/pager”/>  
  20.   
  21. </LinearLayout>  

接下来在Java代码中:

  1. indicador = (MyIndicator) findViewById(R.id.indicador);  
  2.         titles = new String[]{
    “a”“b”“c”“d”“e”“f”};  
  3.         indicador.setTitles(titles);  
  4.   
  5.         viewPager = (ViewPager) findViewById(R.id.pager);  
  6.           
  7.         viewPager.setAdapter(mAdapter);  
  8.         indicador.setViewPager(viewPager); 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/159392.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 初衷

    本博客会不定期做技术分享,在学习的过程中遇到或者踩到的坑也会拿出来给大家分享,个人感觉技术这个东西在于分享,交流产生价值。本博客也会记录我的成长,希望在当中留下些许痕迹让刚入门的师傅们参考,最后我

    2021年12月11日
  • js判断是否包含指定字符串_js判断字符串是否相等

    js判断是否包含指定字符串_js判断字符串是否相等js判断字符串是否包含某个字符串方法一:includes方法//str.includes(“”)返回一个布尔值,值为true时表示包含varstr=”helloworld”;if(str.includes(“world”)){alert(“Hi,world”);}方法二:indexOf方法varstr=”123456″;if(str.indexOf(“5”)!=-1){console.log(“字符串123456里包含了5”);

  • mysql获取当前时间+1天_mysql获取当前时间,前一天,后一天[通俗易懂]

    mysql获取当前时间+1天_mysql获取当前时间,前一天,后一天[通俗易懂]负责的项目中,使用的是mysql数据库,页面上要显示当天所注册人数的数量,获取当前的年月日,我使用的是CURDATE(),错误的sql语句eg:SELECTCOUNT(*)FROMUSERWHEREregisterDate>=CURDATE()ANDregisterDate<CURDATE()+1;虽然获取到的数量在测试环境中是正确的,但在发布到线上的时候,发…

  • 2022.01.13 idea激活码(注册激活)

    (2022.01.13 idea激活码)好多小伙伴总是说激活码老是失效,太麻烦,关注/收藏全栈君太难教程,2021永久激活的方法等着你。https://javaforall.cn/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~0HKLM1UCCY-eyJsaWNlbnNlSWQiOi…

  • 计算机病毒简介[通俗易懂]

    计算机病毒简介[通俗易懂]1、计算机病毒的特征1,繁殖性计算机病毒可以像生物病毒一样进行繁殖,当正常程序运行时,它也进行运行自身复制,是否具有繁殖、感染的特征是判断某段程序为计算机病毒的首要条件。2,破坏性计算机中毒后,可能会导致正常的程序无法运行,把计算机内的文件删除或受到不同程度的损坏。破坏引导扇区及BIOS,硬件环境破坏。3,传染性计算机病毒传染性是指计算机病毒通过修改别的程序将自身的复制品或其变体传染到…

  • php递归算法计算n 介乘,递归算法示例——计算N的阶乘「建议收藏」

    php递归算法计算n 介乘,递归算法示例——计算N的阶乘「建议收藏」递归算法,也就是调用方法自身。阶乘算法,N的阶乘为N*(N-1)*…*2*1,1的阶乘是1。下面是示例的代码:packagecom.cqit.edu.test;importjava.util.Scanner;/***@author肖德俊*@versionDec9,20086:02:55PM*/publicclassUseself{/***@paramargs*/pub…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号