Android開發(fā)之開發(fā)者頭條APP(三)實(shí)現(xiàn)首頁
相關(guān)閱讀:
Android開發(fā)之開發(fā)者頭條(一)啟動(dòng)頁實(shí)現(xiàn)
Android開發(fā)之開發(fā)者頭條(二)實(shí)現(xiàn)左滑菜單
title: 帶你實(shí)現(xiàn)開發(fā)者頭條APP(三) 首頁實(shí)現(xiàn)
tags: 輪播廣告,ViewPager切換,圓形圖片
grammar_cjkRuby: true
一.前言
今天實(shí)現(xiàn)開發(fā)者頭條APP的首頁。是本系列的第三篇文章,效果圖如下:
從gif動(dòng)態(tài)效果圖中我們可以看出,最外層有三個(gè)tab(精選,訂閱,發(fā)現(xiàn)),在精選界面頂部有一個(gè)輪播的圖片廣告,廣告下面是一個(gè)精選文章列表。
二.外層三個(gè)tab實(shí)現(xiàn)
我這里用Viewpager實(shí)現(xiàn)的,可以左右滑動(dòng),靈活的隱藏下面fragment的顯示隱藏。
1.布局文件
布局文件比較簡(jiǎn)單,上面包涵三個(gè)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="發(fā)現(xiàn)" 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.初始化三個(gè)Fragment 并且填充到ViewPager,給ViewPager設(shè)置改變監(jiān)聽。
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填充適配器,實(shí)現(xiàn)起來很簡(jiǎn)單。
/** * 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.指示器初始化
當(dāng)我們Viewpager滑動(dòng)的時(shí)候需要滑動(dòng)指示器,并且指示器的寬度占屏幕的三分之一,所以我們需要在activity創(chuàng)建的時(shí)候給指示器賦值哦,并且移動(dòng)到起始位置。
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切換時(shí)應(yīng)該做什么?
1).移動(dòng)指示器
2).改變文字顏色
3).設(shè)置當(dāng)前選中,指示器移動(dòng)的時(shí)候需要用到。
private OnPageChangeListener pageChangeListener=new OnPageChangeListener() { @Override public void onPageSelected(int index){ translateAnimation(index);//移動(dòng)指示器 changeTextColor(index);//改變文字顏色 currentIndex=index;//設(shè)置當(dāng)前選中 } @Override public void onPageScrolled(int arg0, float arg1, int arg2) {} @Override public void onPageScrollStateChanged(int arg0) {} };
6.指示器移動(dòng)方法translateAnimation
傳入一個(gè)下標(biāo)判斷當(dāng)前位置,然后判斷上次的位置,知道從哪里移動(dòng)到哪個(gè)位置,然后開啟android自帶的移動(dòng)動(dòng)畫。
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){//發(fā)現(xiàn)->訂閱 animation=new TranslateAnimation((screenWidth/3)*2,screenWidth/3,0,0); } break; case 2://訂閱-》發(fā)現(xiàn) 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實(shí)現(xiàn)
從整體來看,就是一個(gè)ListView,頂部輪播是ListView的頭部。頭部輪播也是用的ViewPager實(shí)現(xiàn),起始這里跟我們第一篇文章講的開發(fā)者頭條APP啟動(dòng)頁實(shí)現(xiàn)原理很相似。然后再加一個(gè)定時(shí)器隔一段時(shí)間設(shè)置ViewPager的當(dāng)前頁面即可。
說明:我們這里的圖片用的是靜態(tài)的,一個(gè)商業(yè)APP輪播圖片肯定是從服務(wù)器獲取的,開發(fā)者頭條app就是從服務(wù)器獲取。
1.頭布局文件
就是一個(gè)ViewPager+裝載點(diǎn)點(diǎn)點(diǎn)的LinearLayout 然后外層布局設(shè)置一個(gè)高度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="公眾號(hào):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.可滑動(dòng)的靜態(tài)圖片實(shí)現(xiàn)
初始化輪播的Viewpager,初始化點(diǎn)點(diǎn)點(diǎn)View,并且加入線性布局,最后把整個(gè)布局加入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;// 設(shè)置點(diǎn)點(diǎn)點(diǎn)view的左邊距 layoutParams.rightMargin = 10;// 設(shè)置點(diǎn)點(diǎn)點(diǎn)view的右邊距 group.addView(imageView, layoutParams); } listView=(ListView) rootView.findViewById(R.id.list); listView.addHeaderView(headView);
3.如何實(shí)現(xiàn)輪播效果
我這邊是用Timer+Handler實(shí)現(xiàn),Timer用來計(jì)時(shí),Handler用來更新UI。
注意事項(xiàng):
1).在輪播的時(shí)候需要判斷是否已經(jīng)最后一頁
2).更新UI需要在主線程。
private Timer timer; private final int CAROUSEL_TIME = 3000;//滾動(dòng)間隔 timer = new Timer(true);//初始化計(jì)時(shí)器 timer.schedule(task, 0, CAROUSEL_TIME);//延時(shí)0ms后執(zhí)行,3000ms執(zhí)行一次 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){//已經(jīng)滾動(dòng)到最后,從第一頁開始 viewPager.setCurrentItem(0); }else{//開始下一頁 viewPager.setCurrentItem(currentIndex+1); } break; } }; };
關(guān)于Android開發(fā)之開發(fā)者頭條APP(三)實(shí)現(xiàn)首頁的相關(guān)介紹,就給大家介紹這么多,希望對(duì)大家有所幫助!
- Material Design系列之Behavior上滑顯示返回頂部按鈕
- Material Design系列之Behavior實(shí)現(xiàn)支付密碼彈窗和商品屬性選擇效果
- Material Design系列之自定義Behavior支持所有View
- 詳解在PHP的Yii框架中使用行為Behaviors的方法
- 淺談JavaScript的Polymer框架中的behaviors對(duì)象
- ThinkPHP行為擴(kuò)展Behavior應(yīng)用實(shí)例詳解
- Android仿即刻首頁垂直滾動(dòng)圖,炫酷到底!
- Android模仿知乎的回答詳情頁的動(dòng)畫效果
- Material Design系列之Behavior實(shí)現(xiàn)Android知乎首頁
相關(guān)文章
Android Spinner與適配器模式詳解及實(shí)例代碼
這篇文章主要介紹了Android Spinner與適配器模式詳解相關(guān)資料,并附代碼實(shí)例,需要的朋友可以參考下2016-10-10最新Android版本、代號(hào)、對(duì)應(yīng)API/NDK級(jí)別、發(fā)布時(shí)間及市場(chǎng)份額
這篇文章主要介紹了最新Android版本、代號(hào)、對(duì)應(yīng)API/NDK級(jí)別、發(fā)布時(shí)間及市場(chǎng)份額,在開發(fā)Android應(yīng)用時(shí)會(huì)碰到如何選擇Android版本級(jí)API級(jí)別的問題,看完這篇文章后相信這個(gè)問題會(huì)迎刃而解2017-12-12Android開發(fā)Jetpack組件Lifecycle原理篇
這一篇文章來介紹Android?Jetpack架構(gòu)組件的Lifecycle;?Lifecycle用于幫助開發(fā)者管理Activity和Fragment?的生命周期,?由于Lifecycle是LiveData和ViewModel的基礎(chǔ);所以需要先學(xué)習(xí)它2022-08-08Android事件分發(fā)機(jī)制(上) ViewGroup的事件分發(fā)
這篇文章主要為大家詳細(xì)介紹了Android ViewGroup的事件分發(fā)機(jī)制上篇,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01Android實(shí)現(xiàn)倒計(jì)時(shí)的按鈕效果
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)倒計(jì)時(shí)的按鈕效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-12-12Android利用Java優(yōu)雅消除復(fù)雜條件表達(dá)式的方法
這篇文章主要介紹了Android利用Java優(yōu)雅消除復(fù)雜條件表達(dá)式,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值。感興趣的小伙伴可以參考一下2022-06-06Android?nonTransitiveRClass資源沖突問題淺析
這篇文章主要介紹了Android?nonTransitiveRClass資源沖突問題,別搞錯(cuò)了,nonTransitiveRClass不能解決資源沖突,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-12-12