首页 > 代码库 > 高仿微信5.2.1主界面架构 包含消息通知

高仿微信5.2.1主界面架构 包含消息通知

转载请标明出处: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的布局文件,同样三个基本一致。




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



源码点击下载


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