实现微信的整体界面和ViewPager指示器跟随手指拖动的动画效果。包含了ViewPager与FragmentPagerAdapter的使用,透过分析OnPagerChangeListener手动控制指示器的动画效果,以及如何使用BadgeView消息通知。
效果如下:
核心代码如下:
package com.imooc.weixin;
import android.graphics.Color;
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.view.Display;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.jauker.widget.BadgeView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends FragmentActivity{
/*** 横向滑动ViewPager ***/
private ViewPager mViewPager;
/*** 适配器 ***/
private FragmentPagerAdapter mAdapter;
/*** Fragment集合 ***/
private List<Fragment> mDatas;
/*** 会话 ***/
private TextView mChatTextView;
/*** 朋友圈 ***/
private TextView mFriendTextView;
/*** 通讯录 ***/
private TextView mContactTextView;
private LinearLayout mChatLinearLayout;
/*** BadgeView ***/
private BadgeView mBadgeView;
/*** 指示器line ***/
private ImageView mTabline;
/*** 记录屏幕的1/3 ***/
private int mScreen1_3;
/*** 记录当前滑动页面下标 ***/
private int mCurrentPageIndex;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
/*** 初始化TabLine ***/
initTabLine();
/*** 初始化View ***/
initView();
}
private void initTabLine() {
/*** 跟随手指滑动的line ***/
mTabline = (ImageView) findViewById(R.id.id_iv_tabline);
/*** 滑动line设置为屏幕的1/3 ***/
Display display = getWindow().getWindowManager().getDefaultDisplay();
DisplayMetrics outMetrics = new DisplayMetrics();
display.getMetrics(outMetrics);
mScreen1_3 = outMetrics.widthPixels / 3;
LayoutParams lp = mTabline.getLayoutParams();
lp.width = mScreen1_3;
mTabline.setLayoutParams(lp);
}
private void initView() {
mViewPager = (ViewPager) findViewById(R.id.id_viewpager);
mChatTextView = (TextView) findViewById(R.id.id_tv_chat);
mFriendTextView = (TextView) findViewById(R.id.id_tv_friend);
mContactTextView = (TextView) findViewById(R.id.id_tv_contact);
mChatLinearLayout = (LinearLayout) findViewById(R.id.id_ll_chat);
mDatas = new ArrayList<>();
/*** 初始化3个Fragment ***/
ChatMainTabFragment tab01 = new ChatMainTabFragment();
FriendMainTabFragment tab02 = new FriendMainTabFragment();
ContactMainTabFragment tab03 = new ContactMainTabFragment();
mDatas.add(tab01);
mDatas.add(tab02);
mDatas.add(tab03);
/*** 设置适配器 ***/
mAdapter = new FragmentPagerAdapter(getSupportFragmentManager())
{
@Override
public int getCount() {
return mDatas.size();
}
@Override
public Fragment getItem(int arg0) {
return mDatas.get(arg0);
}
};
mViewPager.setAdapter(mAdapter);
/*** 在onPageSelected方法里面修改滑动的字体颜色变化和消息提醒的设置 ***/
/*** 在onPageScrolled通过不停的setLayoutParams来修改TabLine的位置 ***/
mViewPager.setOnPageChangeListener(new OnPageChangeListener()
{
@Override
public void onPageSelected(int position) {
resetTextView();
switch (position)
{
case 0:
if (mBadgeView != null) {
mChatLinearLayout.removeView(mBadgeView);
}
mBadgeView = new BadgeView(MainActivity.this);
mBadgeView.setBadgeCount(7);
mChatLinearLayout.addView(mBadgeView);
mChatTextView.setTextColor(Color.parseColor("#008000"));
break;
case 1:
mFriendTextView.setTextColor(Color.parseColor("#008000"));
break;
case 2:
mContactTextView.setTextColor(Color.parseColor("#008000"));
break;
}
mCurrentPageIndex = position;
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPx) {
LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams)mTabline.getLayoutParams();
if (mCurrentPageIndex == 0 && position == 0)// 0->1 {
lp.leftMargin = (int) (positionOffset * mScreen1_3 + mCurrentPageIndex*mScreen1_3);
} else if (mCurrentPageIndex == 1 && position == 0)// 1->0 {
lp.leftMargin = (int) (mCurrentPageIndex * mScreen1_3 + (positionOffset - 1) * mScreen1_3);
} else if (mCurrentPageIndex == 1 && position == 1) // 1->2{
lp.leftMargin = (int) (mCurrentPageIndex * mScreen1_3 +positionOffset* mScreen1_3);
} else if (mCurrentPageIndex == 2 && position == 1) // 2->1 {
lp.leftMargin = (int) (mCurrentPageIndex * mScreen1_3 + ( positionOffset-1)* mScreen1_3);
}
mTabline.setLayoutParams(lp);
}
@Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
} });
}
/*** 在每次修改字体颜色之前 先将所有的字体颜色进行重置为黑色 ***/
protected void resetTextView() {
mChatTextView.setTextColor(Color.BLACK);
mFriendTextView.setTextColor(Color.BLACK);
mContactTextView.setTextColor(Color.BLACK);
}
}
以上为部分核心代码,可以看到在onPageScrolled函数中写了大量的判断,显的很麻烦,后续进行简化。
总结:
实现Tab类型的布局大致有一下方式:
(1) ViewPager+多个布局文件 底部是RadioButton或者LinearLayout 通过点击不断的切换
(2)FragmentManager+Fragment Google在3.0以后推出Fragment,通过不断的替换中间内容区域
(3)ViewPager+FragmentPagerAdapter 就是以上实现方式 最大的特点是可以左右滑动
(4)TabHost 已经过时 不推荐使用
以上四种方式,如果主界面需要滑动切换,推荐使用第三种方式,但如果界面很复杂,需要考虑滑动冲突等因素,因为最外层是ViewPager,后期架构更改会有很大影响。如果不需要滑动切换,就使用第二种方式,毕竟Google也推荐使用Fragment来布局了。可根据自己项目的需要选择合适的布局。