高仿微信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>
这个布局也非常easy,在布局中增加了一个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的布局文件,相同三个基本一致。
好了,结束,看起来挺复杂,实现起来还能够。代码写得比較仓促,有啥不足地方请指出来。最后求留言,求赞~