首先这是转的:

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/25708045

一哥们去新疆前给了我个任务,就是整这东西,哥们回来了,赶紧做了个,哈哈,可惜没给我带切糕。

新版微信的效果,一眼看上去准备用ViewpagerIndicator来实现,但是需要在Indicator的后面添加消息通知(BadgeView),可惜没有办法自定义Indicator,最后还是自己写了个实现。

主结构:ViewPager和FragmentPagerAdapter

效果图:

1、主布局文件

  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:background="#eee"  
  6.     android:orientation="vertical" >  
  7.       
  8.     <include layout="@layout/top1"/>  
  9.     <include layout="@layout/top2"/>  
  10.   
  11.     <android.support.v4.view.ViewPager  
  12.         android:id="@+id/id_viewpager"  
  13.         android:layout_width="fill_parent"  
  14.         android:layout_height="0dp"  
  15.         android:layout_weight="1" >  
  16.     </android.support.v4.view.ViewPager>  
  17.   
  18.   
  19. </LinearLayout>  


2、top2.xml

  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="wrap_content"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <LinearLayout  
  8.         android:id="@+id/lllayout"  
  9.         android:layout_width="match_parent"  
  10.         android:layout_height="wrap_content"  
  11.         android:orientation="horizontal" >  
  12.   
  13.         <LinearLayout  
  14.             android:id="@+id/id_tab_liaotian_ly"  
  15.             android:layout_width="match_parent"  
  16.             android:layout_height="wrap_content"  
  17.             android:layout_weight="1"  
  18.             android:background="@drawable/guide_round"  
  19.             android:gravity="center"  
  20.             android:orientation="horizontal"  
  21.             android:padding="10dip" >  
  22.   
  23.             <TextView  
  24.                 android:id="@+id/id_liaotian"  
  25.                 android:layout_width="wrap_content"  
  26.                 android:layout_height="wrap_content"  
  27.                 android:gravity="center"  
  28.                 android:text="聊天"  
  29.                 android:textColor="@color/green"  
  30.                 android:textSize="15dip" />  
  31.         </LinearLayout>  
  32.   
  33.         <LinearLayout  
  34.             android:id="@+id/id_tab_faxian_ly"  
  35.             android:layout_width="match_parent"  
  36.             android:layout_height="wrap_content"  
  37.             android:layout_weight="1"  
  38.             android:background="@drawable/guide_round"  
  39.             android:clickable="true"  
  40.             android:gravity="center"  
  41.              android:orientation="horizontal"  
  42.             android:padding="10dip"  
  43.             android:saveEnabled="false" >  
  44.   
  45.             <TextView  
  46.                 android:id="@+id/id_faxian"  
  47.                 android:layout_width="wrap_content"  
  48.                 android:layout_height="wrap_content"  
  49.                 android:gravity="center"  
  50.                 android:text="发现"  
  51.                 android:textColor="@color/black"  
  52.                 android:textSize="15dip" />  
  53.         </LinearLayout>  
  54.   
  55.         <LinearLayout  
  56.             android:id="@+id/id_tab_tongxunlu_ly"  
  57.             android:layout_width="match_parent"  
  58.             android:layout_height="wrap_content"  
  59.             android:layout_weight="1"  
  60.             android:background="@drawable/guide_round"  
  61.             android:focusable="false"  
  62.             android:gravity="center"  
  63.              android:orientation="horizontal"  
  64.             android:padding="10dip" >  
  65.   
  66.             <TextView  
  67.                 android:id="@+id/id_tongxunlu"  
  68.                 android:layout_width="wrap_content"  
  69.                 android:layout_height="wrap_content"  
  70.                 android:gravity="center"  
  71.                 android:text="通讯录"  
  72.                 android:textColor="@color/black"  
  73.                 android:textSize="15dip" />  
  74.         </LinearLayout>  
  75.     </LinearLayout>  
  76.   
  77.     <ImageView  
  78.         android:id="@+id/id_tab_line"  
  79.         android:layout_width="200dp"  
  80.         android:layout_height="wrap_content"  
  81.         android:background="@drawable/vpi__tab_selected_pressed_holo" >  
  82.     </ImageView>  
  83.   
  84. </LinearLayout>  


这个布局也很简单,在布局中加入了一个ImageView,这个会在程序中动态计算宽度,作为Tab的引导线。

3、主程序

  1. package com.example.mainframework04;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import android.os.Bundle;  
  7. import android.support.v4.app.Fragment;  
  8. import android.support.v4.app.FragmentActivity;  
  9. import android.support.v4.app.FragmentPagerAdapter;  
  10. import android.support.v4.view.ViewPager;  
  11. import android.support.v4.view.ViewPager.OnPageChangeListener;  
  12. import android.util.DisplayMetrics;  
  13. import android.util.Log;  
  14. import android.view.Gravity;  
  15. import android.widget.FrameLayout;  
  16. import android.widget.FrameLayout.LayoutParams;  
  17. import android.widget.ImageView;  
  18. import android.widget.LinearLayout;  
  19. import android.widget.TextView;  
  20.   
  21. import com.jauker.widget.BadgeView;  
  22.   
  23. public class MainActivity extends FragmentActivity  
  24. {  
  25.     private ViewPager mViewPager;  
  26.     private FragmentPagerAdapter mAdapter;  
  27.     private List<Fragment> mFragments = new ArrayList<Fragment>();  
  28.   
  29.     /** 
  30.      * 顶部三个LinearLayout 
  31.      */  
  32.     private LinearLayout mTabLiaotian;  
  33.     private LinearLayout mTabFaxian;  
  34.     private LinearLayout mTabTongxunlun;  
  35.   
  36.     /** 
  37.      * 顶部的三个TextView 
  38.      */  
  39.     private TextView mLiaotian;  
  40.     private TextView mFaxian;  
  41.     private TextView mTongxunlu;  
  42.   
  43.     /** 
  44.      * 分别为每个TabIndicator创建一个BadgeView 
  45.      */  
  46.     private BadgeView mBadgeViewforLiaotian;  
  47.     private BadgeView mBadgeViewforFaxian;  
  48.     private BadgeView mBadgeViewforTongxunlu;  
  49.   
  50.     /** 
  51.      * Tab的那个引导线 
  52.      */  
  53.     private ImageView mTabLine;  
  54.     /** 
  55.      * ViewPager的当前选中页 
  56.      */  
  57.     private int currentIndex;  
  58.     /** 
  59.      * 屏幕的宽度 
  60.      */  
  61.     private int screenWidth;  
  62.   
  63.     @Override  
  64.     protected void onCreate(Bundle savedInstanceState)  
  65.     {  
  66.         super.onCreate(savedInstanceState);  
  67.         setContentView(R.layout.activity_main);  
  68.   
  69.         mViewPager = (ViewPager) findViewById(R.id.id_viewpager);  
  70.   
  71.         initView();  
  72.   
  73.         initTabLine();  
  74.   
  75.         /** 
  76.          * 初始化Adapter 
  77.          */  
  78.         mAdapter = new FragmentPagerAdapter(getSupportFragmentManager())  
  79.         {  
  80.             @Override  
  81.             public int getCount()  
  82.             {  
  83.                 return mFragments.size();  
  84.             }  
  85.   
  86.             @Override  
  87.             public Fragment getItem(int arg0)  
  88.             {  
  89.                 return mFragments.get(arg0);  
  90.             }  
  91.         };  
  92.   
  93.         mViewPager.setAdapter(mAdapter);  
  94.   
  95.         /** 
  96.          * 设置监听 
  97.          */  
  98.         mViewPager.setOnPageChangeListener(new OnPageChangeListener()  
  99.         {  
  100.   
  101.             @Override  
  102.             public void onPageSelected(int position)  
  103.             {  
  104.                 // 重置所有TextView的字体颜色  
  105.                 resetTextView();  
  106.                 switch (position)  
  107.                 {  
  108.                 case 0:  
  109.                     /** 
  110.                      * 设置消息通知 
  111.                      */  
  112.                     mTabLiaotian.removeView(mBadgeViewforLiaotian);  
  113.                     mBadgeViewforLiaotian.setBadgeCount(5);  
  114.                     mTabLiaotian.addView(mBadgeViewforLiaotian);  
  115.                     mLiaotian.setTextColor(getResources().getColor(R.color.green));  
  116.                     break;  
  117.                 case 1:  
  118.                     /** 
  119.                      * 设置消息通知 
  120.                      */  
  121.                     mFaxian.setTextColor(getResources().getColor(R.color.green));  
  122.                     mTabFaxian.removeView(mBadgeViewforFaxian);  
  123.                     mBadgeViewforFaxian.setBadgeCount(15);  
  124.                     mTabFaxian.addView(mBadgeViewforFaxian);  
  125.                     break;  
  126.                 case 2:  
  127.                     mTongxunlu.setTextColor(getResources().getColor(R.color.green));  
  128.   
  129.                     break;  
  130.                 }  
  131.   
  132.                 currentIndex = position;  
  133.             }  
  134.   
  135.             @Override  
  136.             public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)  
  137.             {  
  138.                 /** 
  139.                  * 利用position和currentIndex判断用户的操作是哪一页往哪一页滑动 
  140.                  * 然后改变根据positionOffset动态改变TabLine的leftMargin 
  141.                  */  
  142.                 if (currentIndex == 0 && position == 0)// 0->1  
  143.                 {  
  144.                     LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams) mTabLine  
  145.                             .getLayoutParams();  
  146.                     lp.leftMargin = (int) (positionOffset * (screenWidth * 1.0 / 3) + currentIndex * (screenWidth / 3));  
  147.                     mTabLine.setLayoutParams(lp);  
  148.   
  149.                 } else if (currentIndex == 1 && position == 0) // 1->0  
  150.                 {  
  151.                     LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams) mTabLine  
  152.                             .getLayoutParams();  
  153.                     lp.leftMargin = (int) (-(1 - positionOffset) * (screenWidth * 1.0 / 3) + currentIndex  
  154.                             * (screenWidth / 3));  
  155.                     mTabLine.setLayoutParams(lp);  
  156.   
  157.                 } else if (currentIndex == 1 && position == 1) // 1->2  
  158.                 {  
  159.                     LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams) mTabLine  
  160.                             .getLayoutParams();  
  161.                     lp.leftMargin = (int) (positionOffset * (screenWidth * 1.0 / 3) + currentIndex * (screenWidth / 3));  
  162.                     mTabLine.setLayoutParams(lp);  
  163.                 } else if (currentIndex == 2 && position == 1) // 2->1  
  164.                 {  
  165.                     LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams) mTabLine  
  166.                             .getLayoutParams();  
  167.                     lp.leftMargin = (int) (-(1 - positionOffset) * (screenWidth * 1.0 / 3) + currentIndex  
  168.                             * (screenWidth / 3));  
  169.                     mTabLine.setLayoutParams(lp);  
  170.   
  171.                 }  
  172.   
  173.             }  
  174.   
  175.             @Override  
  176.             public void onPageScrollStateChanged(int state)  
  177.             {  
  178.             }  
  179.         });  
  180.   
  181.         mViewPager.setCurrentItem(1);  
  182.   
  183.     }  
  184.   
  185.     /** 
  186.      * 根据屏幕的宽度,初始化引导线的宽度 
  187.      */  
  188.     private void initTabLine()  
  189.     {  
  190.         mTabLine = (ImageView) findViewById(R.id.id_tab_line);  
  191.         DisplayMetrics outMetrics = new DisplayMetrics();  
  192.         getWindow().getWindowManager().getDefaultDisplay().getMetrics(outMetrics);  
  193.         screenWidth = outMetrics.widthPixels;  
  194.         LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams) mTabLine.getLayoutParams();  
  195.         lp.width = screenWidth / 3;  
  196.         mTabLine.setLayoutParams(lp);  
  197.     }  
  198.   
  199.     /** 
  200.      * 重置颜色 
  201.      */  
  202.     protected void resetTextView()  
  203.     {  
  204.         mLiaotian.setTextColor(getResources().getColor(R.color.black));  
  205.         mFaxian.setTextColor(getResources().getColor(R.color.black));  
  206.         mTongxunlu.setTextColor(getResources().getColor(R.color.black));  
  207.     }  
  208.   
  209.     /** 
  210.      * 初始化控件,初始化Fragment 
  211.      */  
  212.     private void initView()  
  213.     {  
  214.   
  215.         mTabLiaotian = (LinearLayout) findViewById(R.id.id_tab_liaotian_ly);  
  216.         mTabFaxian = (LinearLayout) findViewById(R.id.id_tab_faxian_ly);  
  217.         mTabTongxunlun = (LinearLayout) findViewById(R.id.id_tab_tongxunlu_ly);  
  218.   
  219.         mLiaotian = (TextView) findViewById(R.id.id_liaotian);  
  220.         mFaxian = (TextView) findViewById(R.id.id_faxian);  
  221.         mTongxunlu = (TextView) findViewById(R.id.id_tongxunlu);  
  222.   
  223.         MainTab01 tab01 = new MainTab01();  
  224.         MainTab02 tab02 = new MainTab02();  
  225.         MainTab03 tab03 = new MainTab03();  
  226.         mFragments.add(tab01);  
  227.         mFragments.add(tab02);  
  228.         mFragments.add(tab03);  
  229.   
  230.         mBadgeViewforFaxian = new BadgeView(this);  
  231.         mBadgeViewforLiaotian = new BadgeView(this);  
  232.         mBadgeViewforTongxunlu = new BadgeView(this);  
  233.     }  
  234. }  


主要就是为ViewPager设置 FragmentPagerAdapter,然后添加切换的监听,生成BadgeView,这里没有使用 BadgeView.setTargetView(targetView),因为我希望通知显示在文本的后面,setTargetView可能只能设置显 示位置为目标控件的内部位置。

再次就是TabLine的跟随手指的效果,首先会根据Tab页的数量 为TabLine设置宽度,然后在onPageScrolled中根据position,positionOffset,currentIndex,判断 用户当前手指滑动的方向,然后根据positionOffset这个百分比乘以TabLine的宽度,动态设置TabLine的leftMargin实现 跟随手指移动的效果。

4、每个Fragment的代码

  1. package com.example.mainframework04;  
  2.   
  3. import android.os.Bundle;  
  4. import android.support.v4.app.Fragment;  
  5. import android.view.LayoutInflater;  
  6. import android.view.View;  
  7. import android.view.ViewGroup;  
  8.   
  9. public class MainTab01 extends Fragment  
  10. {  
  11.   
  12.     @Override  
  13.     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)  
  14.     {  
  15.         return  inflater.inflate(R.layout.main_tab_01, container, false);  
  16.       
  17.     }  
  18.   
  19. }  


3个标签页基本一致,不重复贴了。

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:id="@+id/ly_main_weixin"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     android:background="#fcfcfc"  
  7.     android:orientation="vertical" >  
  8.   
  9.     <TextView   
  10.         android:layout_width="fill_parent"  
  11.         android:layout_height="0dp"  
  12.         android:layout_weight="1"  
  13.         android:gravity="center"  
  14.         android:text="this is first tab !"  
  15.         android:textColor="#000000"  
  16.         android:textSize="30sp"  
  17.         />  
  18.   
  19. </LinearLayout>  


Fragment的布局文件,同样三个基本一致。




好了,结束,看起来挺复杂,实现起来还可以。代码写得比较仓促,有啥不足地方请指出来。最后求留言,求赞~



源码点击下载


包含BadgeView的完整代码点击下载