一.前言
今天实现开发者头条APP的首页。是本系列的第三篇文章,效果图如下:

从gif动态效果图中我们可以看出,最外层有三个tab(精选,订阅,发现),在精选界面顶部有一个轮播的图片广告,广告下面是一个精选文章列表。
二.外层三个tab实现
我这里用Viewpager实现的,可以左右滑动,灵活的隐藏下面fragment的显示隐藏。
1.布局文件
布局文件比较简单,上面包涵三个TextView的RelativeLayout + 下面的ViewPager
- <?xml version="1.0" encoding="utf-8"?>
 - <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 - android:layout_width="match_parent"
 - android:layout_height="match_parent"
 - android:background="@color/white_normal">
 - <RelativeLayout
 - android:id="@+id/ll_title"
 - android:layout_width="match_parent"
 - android:layout_height="44dp" >
 - <LinearLayout
 - android:layout_width="match_parent"
 - android:layout_height="match_parent"
 - android:background="@color/main_color"
 - android:orientation="horizontal" >
 - <TextView
 - android:id="@+id/tv_selected"
 - android:layout_width="0dp"
 - android:layout_height="wrap_content"
 - android:layout_gravity="center_vertical"
 - android:layout_weight="1"
 - android:gravity="center_horizontal"
 - android:text="精选"
 - android:textColor="@drawable/main_title_txt_sel" />
 - <TextView
 - android:id="@+id/tv_subscribe"
 - android:layout_width="0dp"
 - android:layout_height="wrap_content"
 - android:layout_gravity="center_vertical"
 - android:layout_weight="1"
 - android:gravity="center_horizontal"
 - android:text="订阅"
 - android:textColor="@drawable/main_title_txt_sel" />
 - <TextView
 - android:id="@+id/tv_find"
 - android:layout_width="0dp"
 - android:layout_height="wrap_content"
 - android:layout_gravity="center_vertical"
 - android:layout_weight="1"
 - android:gravity="center_horizontal"
 - android:text="发现"
 - android:textColor="@drawable/main_title_txt_sel" />
 - </LinearLayout>
 - <View
 - android:id="@+id/view_indicator"
 - android:layout_width="15dp"
 - android:layout_height="2dp"
 - android:layout_alignParentBottom="true"
 - android:background="@color/white_normal" />
 - </RelativeLayout>
 - <android.support.v4.view.ViewPager
 - android:id="@+id/viewpager_home"
 - android:layout_width="match_parent"
 - android:layout_height="match_parent"
 - android:layout_below="@+id/ll_title"/>
 - </RelativeLayout>
 
2.初始化三个Fragment 并且填充到ViewPager,给ViewPager设置改变监听。
- vPager = (ViewPager) rootView.findViewById(R.id.viewpager_home);
 - SelectedFragment selectedFragment=new SelectedFragment();
 - SubscribeFragment subscribeFragment=new SubscribeFragment();
 - FindFragment findFragment=new FindFragment();
 - list.add(selectedFragment);
 - list.add(subscribeFragment);
 - list.add(findFragment);
 - adapter = new FragmentAdapter(getActivity().getSupportFragmentManager(),list);
 - vPager.setAdapter(adapter);
 - vPager.setOffscreenPageLimit(2);
 - vPager.setCurrentItem(0);
 - vPager.setOnPageChangeListener(pageChangeListener);
 
3.FragmentAdapter.java
继承FragmentStatePagerAdapter,Viewpager填充适配器,实现起来很简单。
- /**
 - * ViewPager适配器
 - * @author ansen
 - * @create time 2016-04-18
 - */
 - public class FragmentAdapter extends FragmentStatePagerAdapter {
 - private List<Fragment> list;
 - public FragmentAdapter(FragmentManager fm, List<Fragment> list) {
 - super(fm);
 - this.list = list;
 - }
 - public FragmentAdapter(FragmentManager fm) {
 - super(fm);
 - }
 - @Override
 - public Fragment getItem(int arg0) {
 - return list.get(arg0);
 - }
 - @Override
 - public int getCount() {
 - return list.size();
 - }
 - }
 
4.指示器初始化
当我们Viewpager滑动的时候需要滑动指示器,并且指示器的宽度占屏幕的三分之一,所以我们需要在activity创建的时候给指示器赋值哦,并且移动到起始位置。
- private void initCursorPosition(){
 - LayoutParams layoutParams=viewIndicator.getLayoutParams();
 - layoutParams.width=screenWidth/3;
 - viewIndicator.setLayoutParams(layoutParams);
 - TranslateAnimation animation = new TranslateAnimation(-screenWidth/3,0,0,0);
 - animation.setFillAfter(true);
 - viewIndicator.startAnimation(animation);
 - }
 
5.Viewpager切换时应该做什么?
1).移动指示器
2).改变文字颜色
3).设置当前选中,指示器移动的时候需要用到。
- private OnPageChangeListener pageChangeListener=new OnPageChangeListener() {
 - @Override
 - public void onPageSelected(int index){
 - translateAnimation(index);//移动指示器
 - changeTextColor(index);//改变文字颜色
 - currentIndex=index;//设置当前选中
 - }
 - @Override
 - public void onPageScrolled(int arg0, float arg1, int arg2) {}
 - @Override
 - public void onPageScrollStateChanged(int arg0) {}
 - };
 
6.指示器移动方法translateAnimation
传入一个下标判断当前位置,然后判断上次的位置,知道从哪里移动到哪个位置,然后开启android自带的移动动画。
- private void translateAnimation(int index){
 - TranslateAnimation animation = null;
 - switch (index){
 - case 0://订阅->精选
 - animation=new TranslateAnimation((screenWidth/3),0,0,0);
 - break;
 - case 1://
 - if(0==currentIndex){//精选->订阅
 - animation=new TranslateAnimation(0,screenWidth/3,0,0);
 - }else if(2==currentIndex){//发现->订阅
 - animation=new TranslateAnimation((screenWidth/3)*2,screenWidth/3,0,0);
 - }
 - break;
 - case 2://订阅-》发现
 - animation=new TranslateAnimation(screenWidth/3,(screenWidth/3)*2,0,0);
 - break;
 - }
 - animation.setFillAfter(true);
 - animation.setDuration(300);
 - viewIndicator.startAnimation(animation);
 - }
 
7.获取屏幕宽高
我这边把方法写在activity里面,在工作中大家最好把他放到工具类里面。
- private void getScreenSize(Activity context) {
 - DisplayMetrics dm = new DisplayMetrics();
 - context.getWindowManager().getDefaultDisplay().getMetrics(dm);
 - screenWidth = dm.widthPixels;
 - screenHeight = dm.heightPixels;
 - }
 
三."精选" Fragment实现
从整体来看,就是一个ListView,顶部轮播是ListView的头部。头部轮播也是用的ViewPager实现,起始这里跟我们第一篇文章讲的开发者头条APP启动页实现原理很相似。然后再加一个定时器隔一段时间设置ViewPager的当前页面即可。
说明:我们这里的图片用的是静态的,一个商业APP轮播图片肯定是从服务器获取的,开发者头条app就是从服务器获取。
1.头布局文件
就是一个ViewPager+装载点点点的LinearLayout 然后外层布局设置一个高度200dp
- <?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:orientation="vertical" >
 - <RelativeLayout
 - android:layout_width="wrap_content"
 - android:layout_height="200dp" >
 - <android.support.v4.view.ViewPager
 - android:id="@+id/viewpager"
 - android:layout_width="match_parent"
 - android:layout_height="match_parent" />
 - <TextView
 - android:id="@+id/tv_content"
 - android:layout_width="wrap_content"
 - android:layout_height="wrap_content"
 - android:layout_alignParentBottom="true"
 - android:layout_marginBottom="10dp"
 - android:layout_marginLeft="5dp"
 - android:text="公众号:ansen_666" />
 - <RelativeLayout
 - android:layout_width="fill_parent"
 - android:layout_height="wrap_content"
 - android:orientation="vertical" >
 - <LinearLayout
 - android:id="@+id/viewGroup"
 - android:layout_width="fill_parent"
 - android:layout_height="wrap_content"
 - android:layout_alignParentBottom="true"
 - android:layout_marginBottom="5dp"
 - android:gravity="center_horizontal"
 - android:orientation="horizontal"/>
 - </RelativeLayout>
 - </RelativeLayout>
 - </LinearLayout>
 
2.可滑动的静态图片实现
初始化轮播的Viewpager,初始化点点点View,并且加入线性布局,最后把整个布局加入ListView头部。
- viewPager = (ViewPager)headView.findViewById(R.id.viewpager);
 - selectedPagerAdapter=new SelectedPagerAdapter(getActivity(),carousePagerSelectView);
 - viewPager.setOffscreenPageLimit(2);
 - viewPager.setCurrentItem(0);
 - viewPager.setOnPageChangeListener(onPageChangeListener);
 - viewPager.setAdapter(selectedPagerAdapter);
 - ViewGroup group = (ViewGroup) headView.findViewById(R.id.viewGroup);// 初始化底部显示控件
 - tips = new ImageView[3];
 - for (int i = 0; i < tips.length; i++){
 - ImageView imageView = new ImageView(getActivity());
 - if (i == 0) {
 - imageView.setBackgroundResource(R.drawable.page_indicator_focused);
 - } else {
 - imageView.setBackgroundResource(R.drawable.page_indicator_unfocused);
 - }
 - tips[i] = imageView;
 - LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
 - layoutParams.leftMargin = 10;// 设置点点点view的左边距
 - layoutParams.rightMargin = 10;// 设置点点点view的右边距
 - group.addView(imageView, layoutParams);
 - }
 - listView=(ListView) rootView.findViewById(R.id.list);
 - listView.addHeaderView(headView);
 
3.如何实现轮播效果
我这边是用Timer+Handler实现,Timer用来计时,Handler用来更新UI。
注意事项:
1).在轮播的时候需要判断是否已经最后一页
2).更新UI需要在主线程。
- private Timer timer;
 - private final int CAROUSEL_TIME = 3000;//滚动间隔
 
- timer = new Timer(true);//初始化计时器
 - timer.schedule(task, 0, CAROUSEL_TIME);//延时0ms后执行,3000ms执行一次
 
- TimerTask task = new TimerTask() {
 - public void run() {
 - handler.sendEmptyMessage(CAROUSEL_TIME);
 - }
 - };
 
- private Handler handler=new Handler(){
 - public void handleMessage(Message msg) {
 - switch (msg.what) {
 - case CAROUSEL_TIME:
 - if(currentIndex>=tips.length-1){//已经滚动到最后,从第一页开始
 - viewPager.setCurrentItem(0);
 - }else{//开始下一页
 - viewPager.setCurrentItem(currentIndex+1);
 - }
 - break;
 - }
 - };
 - };
 
4.其他
还有精品列表ListView列表的适配器,还有三个Tab点击改变文字颜色,还有显示圆形头像自定义的View,还有其他的一些布局文件的代码我就不一一贴出来了。。。有需要的自行下载源码.

发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。