带你实现开发者头条APP(三) 首页实现

简介:

title: 带你实现开发者头条APP(三) 首页实现
tags: 轮播广告,ViewPager切换,圆形图片
grammar_cjkRuby: true
---

一.前言

今天实现开发者头条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,还有其他的一些布局文件的代码我就不一一贴出来了。。。有需要的自行下载源码.

目录
相关文章
|
7月前
|
开发者 iOS开发
【教程】无法验证 app 需要互联网连接以验证是否信任开发者
【教程】无法验证 app 需要互联网连接以验证是否信任开发者
|
7月前
|
iOS开发 开发者
苹果iOS App Store上架操作流程详解:从开发者账号到应用发布
很多开发者在开发完iOS APP、进行内测后,下一步就面临上架App Store,不过也有很多同学对APP上架App Store的流程不太了解,下面我们来说一下iOS APP上架App Store的具体流程,如有未涉及到的部分,大家可以及时咨询,共同探讨。
|
7月前
|
移动开发
钉钉H5微应用配置IP,应用首页地址报错:app url exceeds max length limit,这个怎么处理?
钉钉H5微应用配置IP,应用首页地址报错:app url exceeds max length limit,这个怎么处理?
640 0
|
7月前
|
开发者 iOS开发
处理开发者账号到期导致 APP 下架的方处理开发者账号到期导致 APP 下架的方法
处理开发者账号到期导致 APP 下架的方处理开发者账号到期导致 APP 下架的方法
|
4月前
|
安全 开发者 UED
欧盟新规:苹果App Store开发者需公开联系方式,透明度提升还是隐私挑战?
欧盟加强数字服务监管,苹果宣布自10月16日起,欧盟区App Store实施新规:开发者须公开联系方式,提升透明度。政策区分个人与公司开发者信息要求,旨在改善用户体验和服务质量,但引发隐私担忧。苹果需采取措施保护隐私,新规亦考验市场竞争与用户权益平衡。
56 0
|
7月前
|
移动开发 小程序 API
【7月开发者日回顾】小程序回跳APP链路、相机组件等多个新能力计划公布!
【7月开发者日回顾】小程序回跳APP链路、相机组件等多个新能力计划公布!
66 2
|
7月前
|
iOS开发 开发者
苹果 iOS App Store 上架操作流程详解:从开发者账号到应用发布
苹果 iOS App Store 上架操作流程详解:从开发者账号到应用发布
|
7月前
|
XML Android开发 数据格式
Android Studio App开发实战项目之实现淘宝电商App首页界面(附源码,可用于大作业参考)
Android Studio App开发实战项目之实现淘宝电商App首页界面(附源码,可用于大作业参考)
857 1
|
2月前
|
JSON 小程序 JavaScript
uni-app开发微信小程序的报错[渲染层错误]排查及解决
uni-app开发微信小程序的报错[渲染层错误]排查及解决
625 7