文档章节

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

 冷小菜
发布于 2014/12/13 14:07
字数 1326
阅读 64
收藏 0

转载请标明出处: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的完整代码点击下载



本文转载自:http://blog.csdn.net/lmj623565791/article/details/25708045

粉丝 2
博文 63
码字总数 0
作品 0
海淀
私信 提问
Android 高仿微信实时聊天 基于百度云推送

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lmj623565791/article/details/38799363 转载请标明出处:http://blog.csdn.net/lmj623565791/article/detai...

鸿洋_
2014/08/24
0
0
仿微信的IM聊天时间显示格式(含iOS/Android/Web实现)[图文+源码]

本文为原创分享,转载请注明出处。 1、引言 即时通讯IM应用中的聊天消息时间显示是个再常见不过的需求,现在都讲究用户体验,所以时间显示再也不能像传统软件一样简单粗地暴显示成“年/月/日...

JackJiang2011
02/23
0
0
仿微信的IM聊天时间显示格式(含iOS/Android/Web实现)[图文+源码]

本文为原创分享,转载请注明出处。 1、引言 即时通讯IM应用中的聊天消息时间显示是个再常见不过的需求,现在都讲究用户体验,所以时间显示再也不能像传统软件一样简单粗地暴显示成“年/月/日...

首席大胸器
02/23
366
0
CSDN_LQR/LQRWeChat

重大消息!!! 新版高仿微信已经开源,因为基于融云SDK,使用了 Rxjava+Retrofit+MVP+Glide 等新技术开发,代码结构上可以完全不一样,所以另开了一个项目。新版高仿微信使用到了自动布局来...

CSDN_LQR
2017/02/07
0
0
Android 自定义控件打造史上最简单的侧滑菜单

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lmj623565791/article/details/39185641 转载请标明出处:http://blog.csdn.net/lmj623565791/article/detai...

鸿洋_
2014/09/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Mysql备份还有这么多套路,还不了解下?

逻辑备份和物理备份 逻辑备份 逻辑备份用于备份数据库的结构(CREAET DATABASE、CREATE TABLE)和数据(INSERT),这种备份类型适合数据量小、跨SQL服务器、需要修改数据等场景。如mysqldump...

架构文摘
13分钟前
4
0
吊打面试官——秒杀系统设计

首先设计一个系统之前,我们需要先确认我们的业务场景是怎么样子的,我就带着大家一起假设一个场景好吧。 场景 我们现在要卖100件下面这个婴儿纸尿裤,然后我们根据以往这样秒杀活动的数据经...

java后端开发
18分钟前
3
0
高频电子电路电磁兼容的设计要点

电磁兼容的问题常发生于高频状态下,个别问题(电压跌落与瞬时中断等)除外。高频思维,总而言之,就是器件的特性、电路的特性,在高频情况下和常规中低频 状态下是不一样的,如果仍然按照普...

demyar
20分钟前
2
0
JDK 12 JVM 垃圾回收器 Shenandoah GC 的实践案例

https://www.infoq.cn/article/L4LU1J0VxXtA6ASeGYbV

perofu
29分钟前
3
0
Linux下的计划任务--cron

linux任务计划cron介绍 大部分系统管理工作都是通过定期自动执行某个脚本来完成的,Linux的cron就是用来定期执行脚本的。 Linux任务计划功能的操作都是通过crontab命令来完成的,常用的选项有...

爱米修啊
31分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部