zoukankan      html  css  js  c++  java
  • 带你实现开发者头条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,还有其他的一些布局文件的代码我就不一一贴出来了。。。有需要的自行下载源码.

    四.源码下载

    点击下载源码

    五.相关文章

    带你实现开发者头条(一) 启动页实现
    带你实现开发者头条(二) 实现左滑菜单

    **推荐下自己创建的Android开发 QQ群: 202928390欢迎大家的加入. **

    如果你想第一时间看我们的后期文章,扫码关注公众号,每周不定期推送Android开发实战教程文章,你还等什么,赶快关注吧,学好技术,出任ceo,赢取白富美。。。。

          Android开发666 - 安卓开发技术分享
                扫描二维码加关注
    

    Android开发666

  • 相关阅读:
    九宫格小游戏源码分享
    DeviceOne 竟然做出来如此复杂的App
    DeviceOne 让你一见钟情的App快速开发平台
    MySQL初始化
    MySQL的操作
    MySQL
    Library
    Python模块
    Anaconda的使用
    面向对象之成员修饰 特殊成员 methclass
  • 原文地址:https://www.cnblogs.com/yishaochu/p/5410508.html
Copyright © 2011-2022 走看看