Android—(实现仿网易新闻的顶部导航指示器)

来源:互联网 发布:网络教育的优点 编辑:程序博客网 时间:2024/04/29 06:54

效果图如下,点击对应的Tab标签或者滑动屏幕则可跳转到对应的页面,并且底部的横线也会滑动到对应的Tab标签下面


顶部的导航栏使用三个TextView实现,下划线就是一个ImageView加载了一张横线图片,内容区是用ViewPager实现。

需要注意的是,使用ViewPager控件需要导入Android.support.v4.jar兼容包,不过如果你是使用AndroidStudio,则会自动导入

页面布局代码

activity_main.xml

[html] view plain copy
  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.   
  7.     <!-- 顶部导航栏 -->  
  8.     <LinearLayout  
  9.         android:layout_width="match_parent"  
  10.         android:layout_height="40dp"  
  11.         android:orientation="horizontal">  
  12.   
  13.         <TextView  
  14.             android:id="@+id/tv01"  
  15.             android:layout_width="0dp"  
  16.             android:layout_height="match_parent"  
  17.             android:layout_weight="1"  
  18.             android:gravity="center"  
  19.             android:text="今日"  
  20.             android:textColor="#ff0000"  
  21.             android:textSize="18sp" />  
  22.   
  23.         <TextView  
  24.             android:id="@+id/tv02"  
  25.             android:layout_width="0dp"  
  26.             android:layout_height="match_parent"  
  27.             android:layout_weight="1"  
  28.             android:gravity="center"  
  29.             android:text="明天"  
  30.             android:textSize="18sp" />  
  31.   
  32.         <TextView  
  33.             android:id="@+id/tv03"  
  34.             android:layout_width="0dp"  
  35.             android:layout_height="match_parent"  
  36.             android:layout_weight="1"  
  37.             android:gravity="center"  
  38.             android:text="后天"  
  39.             android:textSize="18sp" />  
  40.     </LinearLayout>  
  41.   
  42.     <!-- Tab底部下划线 -->  
  43.     <ImageView  
  44.         android:id="@+id/iv_tab_bottom_img"  
  45.         android:layout_width="wrap_content"  
  46.         android:layout_height="2dp"  
  47.         android:scaleType="matrix"  
  48.         android:src="@drawable/ic_orange_line" />  
  49.   
  50.     <!-- 内容页 -->  
  51.     <android.support.v4.view.ViewPager  
  52.         android:id="@+id/vPager"  
  53.         android:layout_width="wrap_content"  
  54.         android:layout_height="match_parent"  
  55.         android:layout_gravity="center"  
  56.         android:background="#ffffff" />  
  57.   
  58. </LinearLayout>  


还需要三个Tab页面作为VIewPager的内容展示页,分别取名 tab_01.xml、tab_02.xml,tab_03.xml 把里面的数字改一改就好了

[html] view plain copy
  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.   
  7.     <TextView  
  8.         android:layout_width="match_parent"  
  9.         android:layout_height="match_parent"  
  10.         android:gravity="center"  
  11.         android:textSize="180sp"  
  12.         android:text="1"/>  
  13.   
  14. </LinearLayout>  


接下来就是主要代码了,详细的解释在代码里

[java] view plain copy
  1. public class MainActivity extends AppCompatActivity implements View.OnClickListener {  
  2.   
  3.     private List<View> listViews;  
  4.     private ImageView cursorIv;  
  5.     private TextView tab01, tab02, tab03;  
  6.     private TextView[] titles;  
  7.     private ViewPager viewPager;  
  8.   
  9.     /** 
  10.      * 偏移量(手机屏幕宽度 / 选项卡总数 - 选项卡长度) / 2 
  11.      */  
  12.     private int offset = 0;  
  13.   
  14.     /** 
  15.      * 下划线图片宽度 
  16.      */  
  17.     private int lineWidth;  
  18.   
  19.     /** 
  20.      * 当前选项卡的位置 
  21.      */  
  22.     private int current_index = 0;  
  23.   
  24.     /** 
  25.      * 选项卡总数 
  26.      */  
  27.     private static final int TAB_COUNT = 3;  
  28.   
  29.     private static final int TAB_0 = 0;  
  30.   
  31.     private static final int TAB_1 = 1;  
  32.   
  33.     private static final int TAB_2 = 2;  
  34.   
  35.     @Override  
  36.     protected void onCreate(Bundle savedInstanceState) {  
  37.         super.onCreate(savedInstanceState);  
  38.         setContentView(R.layout.activity_main);  
  39.         initUI();  
  40.         initImageView();  
  41.         initVPager();  
  42.     }  
  43.   
  44.     /** 
  45.      * 初始化布局和监听 
  46.      */  
  47.     private void initUI() {  
  48.         viewPager = (ViewPager) findViewById(R.id.vPager);  
  49.         cursorIv = (ImageView) findViewById(R.id.iv_tab_bottom_img);  
  50.         tab01 = (TextView) findViewById(R.id.tv01);  
  51.         tab02 = (TextView) findViewById(R.id.tv02);  
  52.         tab03 = (TextView) findViewById(R.id.tv03);  
  53.   
  54.         tab01.setOnClickListener(this);  
  55.         tab02.setOnClickListener(this);  
  56.         tab03.setOnClickListener(this);  
  57.   
  58.     }  
  59.   
  60.     /** 
  61.      * 初始化底部下划线 
  62.      */  
  63.     private void initImageView() {  
  64.         // 获取图片宽度  
  65.         lineWidth = BitmapFactory.decodeResource(getResources(), R.drawable.ic_orange_line).getWidth();  
  66.         // Android提供的DisplayMetrics可以很方便的获取屏幕分辨率  
  67.         DisplayMetrics dm = new DisplayMetrics();  
  68.         getWindowManager().getDefaultDisplay().getMetrics(dm);  
  69.         int screenW = dm.widthPixels; // 获取分辨率宽度  
  70.         offset = (screenW / TAB_COUNT - lineWidth) / 2;  // 计算偏移值  
  71.         Matrix matrix = new Matrix();  
  72.         matrix.postTranslate(offset, 0);  
  73.         // 设置下划线初始位置  
  74.         cursorIv.setImageMatrix(matrix);  
  75.     }  
  76.   
  77.     /** 
  78.      * 初始化ViewPager并添加监听事件 
  79.      */  
  80.     private void initVPager() {  
  81.         listViews = new ArrayList<>();  
  82.         LayoutInflater mInflater = getLayoutInflater();  
  83.         listViews.add(mInflater.inflate(R.layout.tab_01, null));  
  84.         listViews.add(mInflater.inflate(R.layout.tab_02, null));  
  85.         listViews.add(mInflater.inflate(R.layout.tab_03, null));  
  86.         viewPager.setAdapter(new MyPagerAdapter(listViews));  
  87.         viewPager.setCurrentItem(0);  
  88.         titles = new TextView[]{tab01, tab02, tab03};  
  89.         viewPager.setOffscreenPageLimit(titles.length);  
  90.         viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {  
  91.             int one = offset * 2 + lineWidth;  
  92.   
  93.             @Override  
  94.             public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {  
  95.             }  
  96.   
  97.             @Override  
  98.             public void onPageSelected(int position) {  
  99.                 // 下划线开始移动前的位置  
  100.                 float fromX = one * current_index;  
  101.                 // 下划线移动完毕后的位置  
  102.                 float toX = one * position;  
  103.                 Animation animation = new TranslateAnimation(fromX, toX, 00);  
  104.                 animation.setFillAfter(true);  
  105.                 animation.setDuration(500);  
  106.                 // 给图片添加动画  
  107.                 cursorIv.startAnimation(animation);  
  108.                 // 当前Tab的字体变成红色  
  109.                 titles[position].setTextColor(Color.RED);  
  110.                 titles[current_index].setTextColor(Color.BLACK);  
  111.                 current_index = position;  
  112.             }  
  113.   
  114.             @Override  
  115.             public void onPageScrollStateChanged(int state) {  
  116.             }  
  117.         });  
  118.     }  
  119.   
  120.     /** 
  121.      * ViewPager适配器 
  122.      */  
  123.     public class MyPagerAdapter extends PagerAdapter {  
  124.   
  125.         public List<View> mListViews;  
  126.   
  127.         public MyPagerAdapter(List<View> mListViews) {  
  128.             this.mListViews = mListViews;  
  129.         }  
  130.   
  131.         @Override  
  132.         public void destroyItem(ViewGroup container, int position, Object object) {  
  133.             container.removeView(mListViews.get(position));  
  134.         }  
  135.   
  136.         @Override  
  137.         public Object instantiateItem(ViewGroup container, int position) {  
  138.             container.addView(mListViews.get(position), 0);  
  139.             return mListViews.get(position);  
  140.         }  
  141.   
  142.         @Override  
  143.         public int getCount() {  
  144.             return mListViews.size();  
  145.         }  
  146.   
  147.         @Override  
  148.         public boolean isViewFromObject(View view, Object object) {  
  149.             return view == object;  
  150.         }  
  151.   
  152.     }  
  153.   
  154.     @Override  
  155.     public void onClick(View v) {  
  156.         switch (v.getId()) {  
  157.             case R.id.tv01:  
  158.                 // 避免重复加载  
  159.                 if (viewPager.getCurrentItem() != TAB_0) {  
  160.                     viewPager.setCurrentItem(TAB_0);  
  161.                 }  
  162.                 break;  
  163.             case R.id.tv02:  
  164.                 if (viewPager.getCurrentItem() != TAB_1) {  
  165.                     viewPager.setCurrentItem(TAB_1);  
  166.                 }  
  167.                 break;  
  168.             case R.id.tv03:  
  169.                 if (viewPager.getCurrentItem() != TAB_2) {  
  170.                     viewPager.setCurrentItem(TAB_2);  
  171.                 }  
  172.                 break;  
  173.         }  
  174.     }  
  175.   
  176. }  


如果嫌下划线走的太慢的话,可以设置animation.setDuration(100),传入的毫秒数字越小动画执行的越快,越大则越慢

要注意animation.setFillAfter()一定要设置为true,防止下划线图片返回,Animation动画终止时让ImageView停留在最后一帧,不然下划线又会回到没有执行Animation之前的状态,如下图

其实这个效果也可使用Google提供的TabLayout来实现:《使用TabLayout制作下划线能滑动的Tab标签页》


Demo源码:传送门


阅读全文
0 0
原创粉丝点击