转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/25708045
一哥们去*前给了我个任务,就是整这东西,哥们回来了,赶紧做了个,哈哈,可惜没给我带切糕。
新版微信的效果,一眼看上去准备用ViewpagerIndicator来实现,但是需要在Indicator的后面添加消息通知(BadgeView),可惜没有办法自定义Indicator,最后还是自己写了个实现。
主结构:ViewPager和FragmentPagerAdapter
效果图:
1、主布局文件
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="#eee"
- android:orientation="vertical" >
- <include layout="@layout/top1"/>
- <include layout="@layout/top2"/>
- <android.support.v4.view.ViewPager
- android:id="@+id/id_viewpager"
- android:layout_width="fill_parent"
- android:layout_height="0dp"
- android:layout_weight="1" >
- </android.support.v4.view.ViewPager>
- </LinearLayout>
2、top2.xml
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical" >
- <LinearLayout
- android:id="@+id/lllayout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal" >
- <LinearLayout
- android:id="@+id/id_tab_liaotian_ly"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:background="@drawable/guide_round"
- android:gravity="center"
- android:orientation="horizontal"
- android:padding="10dip" >
- <TextView
- android:id="@+id/id_liaotian"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:text="聊天"
- android:textColor="@color/green"
- android:textSize="15dip" />
- </LinearLayout>
- <LinearLayout
- android:id="@+id/id_tab_faxian_ly"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:background="@drawable/guide_round"
- android:clickable="true"
- android:gravity="center"
- android:orientation="horizontal"
- android:padding="10dip"
- android:saveEnabled="false" >
- <TextView
- android:id="@+id/id_faxian"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:text="发现"
- android:textColor="@color/black"
- android:textSize="15dip" />
- </LinearLayout>
- <LinearLayout
- android:id="@+id/id_tab_tongxunlu_ly"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:background="@drawable/guide_round"
- android:focusable="false"
- android:gravity="center"
- android:orientation="horizontal"
- android:padding="10dip" >
- <TextView
- android:id="@+id/id_tongxunlu"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:text="通讯录"
- android:textColor="@color/black"
- android:textSize="15dip" />
- </LinearLayout>
- </LinearLayout>
- <ImageView
- android:id="@+id/id_tab_line"
- android:layout_width="200dp"
- android:layout_height="wrap_content"
- android:background="@drawable/vpi__tab_selected_pressed_holo" >
- </ImageView>
- </LinearLayout>
这个布局也很简单,在布局中加入了一个ImageView,这个会在程序中动态计算宽度,作为Tab的引导线。
3、主程序
- package com.example.mainframework04;
- import java.util.ArrayList;
- import java.util.List;
- import android.os.Bundle;
- import android.support.v4.app.Fragment;
- import android.support.v4.app.FragmentActivity;
- import android.support.v4.app.FragmentPagerAdapter;
- import android.support.v4.view.ViewPager;
- import android.support.v4.view.ViewPager.OnPageChangeListener;
- import android.util.DisplayMetrics;
- import android.util.Log;
- import android.view.Gravity;
- import android.widget.FrameLayout;
- import android.widget.FrameLayout.LayoutParams;
- import android.widget.ImageView;
- import android.widget.LinearLayout;
- import android.widget.TextView;
- import com.jauker.widget.BadgeView;
- public class MainActivity extends FragmentActivity
- {
- private ViewPager mViewPager;
- private FragmentPagerAdapter mAdapter;
- private List<Fragment> mFragments = new ArrayList<Fragment>();
- /**
- * 顶部三个LinearLayout
- */
- private LinearLayout mTabLiaotian;
- private LinearLayout mTabFaxian;
- private LinearLayout mTabTongxunlun;
- /**
- * 顶部的三个TextView
- */
- private TextView mLiaotian;
- private TextView mFaxian;
- private TextView mTongxunlu;
- /**
- * 分别为每个TabIndicator创建一个BadgeView
- */
- private BadgeView mBadgeViewforLiaotian;
- private BadgeView mBadgeViewforFaxian;
- private BadgeView mBadgeViewforTongxunlu;
- /**
- * Tab的那个引导线
- */
- private ImageView mTabLine;
- /**
- * ViewPager的当前选中页
- */
- private int currentIndex;
- /**
- * 屏幕的宽度
- */
- private int screenWidth;
- @Override
- protected void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- mViewPager = (ViewPager) findViewById(R.id.id_viewpager);
- initView();
- initTabLine();
- /**
- * 初始化Adapter
- */
- mAdapter = new FragmentPagerAdapter(getSupportFragmentManager())
- {
- @Override
- public int getCount()
- {
- return mFragments.size();
- }
- @Override
- public Fragment getItem(int arg0)
- {
- return mFragments.get(arg0);
- }
- };
- mViewPager.setAdapter(mAdapter);
- /**
- * 设置监听
- */
- mViewPager.setOnPageChangeListener(new OnPageChangeListener()
- {
- @Override
- public void onPageSelected(int position)
- {
- // 重置所有TextView的字体颜色
- resetTextView();
- switch (position)
- {
- case 0:
- /**
- * 设置消息通知
- */
- mTabLiaotian.removeView(mBadgeViewforLiaotian);
- mBadgeViewforLiaotian.setBadgeCount(5);
- mTabLiaotian.addView(mBadgeViewforLiaotian);
- mLiaotian.setTextColor(getResources().getColor(R.color.green));
- break;
- case 1:
- /**
- * 设置消息通知
- */
- mFaxian.setTextColor(getResources().getColor(R.color.green));
- mTabFaxian.removeView(mBadgeViewforFaxian);
- mBadgeViewforFaxian.setBadgeCount(15);
- mTabFaxian.addView(mBadgeViewforFaxian);
- break;
- case 2:
- mTongxunlu.setTextColor(getResources().getColor(R.color.green));
- break;
- }
- currentIndex = position;
- }
- @Override
- public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
- {
- /**
- * 利用position和currentIndex判断用户的操作是哪一页往哪一页滑动
- * 然后改变根据positionOffset动态改变TabLine的leftMargin
- */
- if (currentIndex == 0 && position == 0)// 0->1
- {
- LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams) mTabLine
- .getLayoutParams();
- lp.leftMargin = (int) (positionOffset * (screenWidth * 1.0 / 3) + currentIndex * (screenWidth / 3));
- mTabLine.setLayoutParams(lp);
- } else if (currentIndex == 1 && position == 0) // 1->0
- {
- LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams) mTabLine
- .getLayoutParams();
- lp.leftMargin = (int) (-(1 - positionOffset) * (screenWidth * 1.0 / 3) + currentIndex
- * (screenWidth / 3));
- mTabLine.setLayoutParams(lp);
- } else if (currentIndex == 1 && position == 1) // 1->2
- {
- LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams) mTabLine
- .getLayoutParams();
- lp.leftMargin = (int) (positionOffset * (screenWidth * 1.0 / 3) + currentIndex * (screenWidth / 3));
- mTabLine.setLayoutParams(lp);
- } else if (currentIndex == 2 && position == 1) // 2->1
- {
- LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams) mTabLine
- .getLayoutParams();
- lp.leftMargin = (int) (-(1 - positionOffset) * (screenWidth * 1.0 / 3) + currentIndex
- * (screenWidth / 3));
- mTabLine.setLayoutParams(lp);
- }
- }
- @Override
- public void onPageScrollStateChanged(int state)
- {
- }
- });
- mViewPager.setCurrentItem(1);
- }
- /**
- * 根据屏幕的宽度,初始化引导线的宽度
- */
- private void initTabLine()
- {
- mTabLine = (ImageView) findViewById(R.id.id_tab_line);
- DisplayMetrics outMetrics = new DisplayMetrics();
- getWindow().getWindowManager().getDefaultDisplay().getMetrics(outMetrics);
- screenWidth = outMetrics.widthPixels;
- LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams) mTabLine.getLayoutParams();
- lp.width = screenWidth / 3;
- mTabLine.setLayoutParams(lp);
- }
- /**
- * 重置颜色
- */
- protected void resetTextView()
- {
- mLiaotian.setTextColor(getResources().getColor(R.color.black));
- mFaxian.setTextColor(getResources().getColor(R.color.black));
- mTongxunlu.setTextColor(getResources().getColor(R.color.black));
- }
- /**
- * 初始化控件,初始化Fragment
- */
- private void initView()
- {
- mTabLiaotian = (LinearLayout) findViewById(R.id.id_tab_liaotian_ly);
- mTabFaxian = (LinearLayout) findViewById(R.id.id_tab_faxian_ly);
- mTabTongxunlun = (LinearLayout) findViewById(R.id.id_tab_tongxunlu_ly);
- mLiaotian = (TextView) findViewById(R.id.id_liaotian);
- mFaxian = (TextView) findViewById(R.id.id_faxian);
- mTongxunlu = (TextView) findViewById(R.id.id_tongxunlu);
- MainTab01 tab01 = new MainTab01();
- MainTab02 tab02 = new MainTab02();
- MainTab03 tab03 = new MainTab03();
- mFragments.add(tab01);
- mFragments.add(tab02);
- mFragments.add(tab03);
- mBadgeViewforFaxian = new BadgeView(this);
- mBadgeViewforLiaotian = new BadgeView(this);
- mBadgeViewforTongxunlu = new BadgeView(this);
- }
- }
主要就是为ViewPager设置FragmentPagerAdapter,然后添加切换的监听,生成BadgeView,这里没有使用BadgeView.setTargetView(targetView),因为我希望通知显示在文本的后面,setTargetView可能只能设置显示位置为目标控件的内部位置。
再次就是TabLine的跟随手指的效果,首先会根据Tab页的数量为TabLine设置宽度,然后在onPageScrolled中根据position,positionOffset,currentIndex,判断用户当前手指滑动的方向,然后根据positionOffset这个百分比乘以TabLine的宽度,动态设置TabLine的leftMargin实现跟随手指移动的效果。
4、每个Fragment的代码
- package com.example.mainframework04;
- import android.os.Bundle;
- import android.support.v4.app.Fragment;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- public class MainTab01 extends Fragment
- {
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
- {
- return inflater.inflate(R.layout.main_tab_01, container, false);
- }
- }
3个标签页基本一致,不重复贴了。
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/ly_main_weixin"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:background="#fcfcfc"
- android:orientation="vertical" >
- <TextView
- android:layout_width="fill_parent"
- android:layout_height="0dp"
- android:layout_weight="1"
- android:gravity="center"
- android:text="this is first tab !"
- android:textColor="#000000"
- android:textSize="30sp"
- />
- </LinearLayout>
Fragment的布局文件,同样三个基本一致。
好了,结束,看起来挺复杂,实现起来还可以。代码写得比较仓促,有啥不足地方请指出来。最后求留言,求赞~