Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android應用經典主界面框架之二:仿網易新聞客戶端、CSDN 客戶端 (Fragment ViewPager)

Android應用經典主界面框架之二:仿網易新聞客戶端、CSDN 客戶端 (Fragment ViewPager)

編輯:關於Android編程

第二種主界面風格則是以網易新聞、鳳凰新聞以及新推出的新浪博客(閱讀版)為代表,使用ViewPager+Fragment,即ViewPager裡適配器裡放的不是一般的View,而是Fragment。所以適配器不能繼承PagerAdapter,而要繼承FragmentPagerAdapter,這是在Android.support.v4.app.FragmentPagerAdapter包裡的。有點奇葩的是,FragmentPagerAdapter只在這個包裡有,在android.app.*這個包下面麼有。到後面會發現,只能用android.support.v4.app.*包下面的東西。兩個包裡的FragmentManager是不通用的,而且兩個包裡提供的Fragment也不大一樣。如果繼承android.app.*下的Fragment,則不能重新寫構造函數,只能用默認的。v4的包裡麼有這個限制。

下圖是網易新聞、鳳凰新聞、新浪博客的截圖:

 

\

 

關於仿網易新聞客戶端代碼已經很多了,本人主要根據開源的這個CSDN客戶端的制作,准備一步步搞下。這本是一個大牛之作發在oschina上,參考鏈接裡分5步去實現。我看了它的代碼,是染在一起的。比如要完這個導航不需要額外的三個包,而他的資源裡是弄一起的。所以准備自己玩玩,順便記錄開發中的問題。

 

錨點

 

第一步:最上面的導航欄

即有“網易新聞”四個大字這一欄。布局文件head_title_panel.xml:

[html]view plaincopy

print?

 

在CODE上查看代碼片

 

 

派生到我的代碼片

 

android:layout_height="wrap_content"

android:background="@color/light_blue"

android:orientation="horizontal">

android:id="@+id/headIcon"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center_vertical"

android:layout_marginLeft="8dp"

android:layout_marginRight="4dp"

android:src="@drawable/biz_navigation_tab_news_pressed"/>

android:id="@+id/headDivider"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center_vertical"

android:layout_marginLeft="4dp"

android:layout_marginRight="4dp"

android:src="@drawable/base_action_bar_back_divider"/>

android:id="@+id/headTV"

android:layout_width="0dp"

android:layout_height="wrap_content"

android:layout_gravity="center_vertical"

android:layout_marginLeft="4dp"

android:layout_weight="1"

android:text="CSDN資訊"

android:textColor="@color/white"

android:textSize="21sp"

android:textStyle="bold">

為了日後操作上的方便,我將它映射成一個HeadTitlePanel.java文件,可以看到這種寫法跟上篇上下panel的定義是有點區別的。

[java]view plaincopy

print?

 

在CODE上查看代碼片

 

 

派生到我的代碼片

 

packageorg.yanzi.ui;

importorg.yanzi.csdnproject.R;

importandroid.content.Context;

importandroid.util.AttributeSet;

importandroid.view.LayoutInflater;

importandroid.view.View;

importandroid.widget.ImageView;

importandroid.widget.RelativeLayout;

importandroid.widget.TextView;

publicclassHeadTitlePanelextendsRelativeLayout{

privateContextmContext;

privateTextViewmHeadTV;

privateImageViewmHeadIcon;

privateImageViewmHeadDivider;

publicHeadTitlePanel(Contextcontext,AttributeSetattrs){

super(context,attrs);

//TODOAuto-generatedconstructorstub

mContext=context;

Viewparent=LayoutInflater.from(mContext).inflate(R.layout.head_title_panel,this,true);

mHeadTV=(TextView)parent.findViewById(R.id.headTV);

}

}

 

錨點

 

第二步:ViewPager的導航欄

這個本來我是准備自己封裝個的,網上也有用Radiobutton封裝的,考慮到它這個導航欄還是不固定長度可以滑動的,時間原因暫時不封裝了,使用開源Android-ViewPagerIndicator-master.zip 這個包,這個人的github鏈接:https://github.com/JakeWharton將其中的library文件夾改名ViewPagerIndicator_library導進來。這個裡面有好幾種Indicator,我們主要用TabPageIndicator這個。

第三步:MainActivity的布局:

activity_main.xml

[html]view plaincopy

print?

 

在CODE上查看代碼片

 

 

派生到我的代碼片

 

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="#eee"

tools:context=".MainActivity">

android:id="@+id/head_title_panel"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_alignParentTop="true"/>

android:id="@+id/page_indicator"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_below="@id/head_title_panel"

android:background="@color/transparentblue"/>

android:id="@+id/view_pager"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_below="@id/page_indicator"

/>

MainActivity.java

[java]view plaincopy

print?

 

在CODE上查看代碼片

 

 

派生到我的代碼片

 

packageorg.yanzi.csdnproject;

importorg.yanzi.viewpager.adapter.TabAdapter;

importcom.viewpagerindicator.TabPageIndicator;

importandroid.os.Bundle;

importandroid.app.Activity;

importandroid.app.FragmentManager;

importandroid.view.Menu;

importandroid.support.v4.app.FragmentActivity;

importandroid.support.v4.app.FragmentPagerAdapter;

importandroid.support.v4.view.ViewPager;

publicclassMainActivityextendsFragmentActivity{

privateTabPageIndicatormPageIndicator;

privateViewPagermViewPager;

privateFragmentPagerAdapterfragPagerAdapter;

@Override

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

initUI();

fragPagerAdapter=newTabAdapter(getSupportFragmentManager());

mViewPager.setAdapter(fragPagerAdapter);

mPageIndicator.setViewPager(mViewPager,0);

}

@Override

publicbooleanonCreateOptionsMenu(Menumenu){

//Inflatethemenu;thisaddsitemstotheactionbarifitispresent.

getMenuInflater().inflate(R.menu.main,menu);

returntrue;

}

privatevoidinitUI(){

mPageIndicator=(TabPageIndicator)findViewById(R.id.page_indicator);

mViewPager=(ViewPager)findViewById(R.id.view_pager);

}

}

出奇的簡單,比單純用Fragment還簡單,原因是只需把Fragment塞到適配器裡就ok了,適配器為我們做了Fragment的切換等工作,我們能做的也就是在適配器裡new Fragment的時候判斷是否已存在。以下幾點需要注意:

1、在styles.xml裡它定義了樣式:

[html]view plaincopy

print?

 

在CODE上查看代碼片

 

 

派生到我的代碼片

 

@style/MyWidget.TabPageIndicator

@drawable/init_pic

true

5000

@null

center

@drawable/vpi__tab_indicator

22dip

22dip

8dp

8dp

@style/MyTextAppearance.TabPageIndicator

16sp

1

bold

@color/black

這個是依賴於導進去的包的。

2、它這裡用了android:windowBackground的屬性,所以app開啟瞬間會有圖片彈出,之後設置MainActivity的布局背景為android:background="#eee",又把圖片替換了。如果不設android:background="#eee" 會一直看到這個圖片不消失。

3、因為開篇講的原因,MainActivity只能繼承自FragmentActivity。

 

錨點

 

第四步:MainFragment.java,此類繼承Fragment,且是android.support.v4.app.Fragment下的。

[java]view plaincopy

print?

 

在CODE上查看代碼片

 

 

派生到我的代碼片

 

packageorg.yanzi.fragment;

importorg.yanzi.csdnproject.R;

importandroid.os.Bundle;

importandroid.support.v4.app.Fragment;

importandroid.view.LayoutInflater;

importandroid.view.View;

importandroid.view.ViewGroup;

importandroid.widget.TextView;

publicclassMainFragmentextendsFragment{

privateintmNewsType=0;

@Override

publicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer,

BundlesavedInstanceState){

//TODOAuto-generatedmethodstub

Viewv=inflater.inflate(R.layout.tab_item_fragment_main,null);

TextViewtip=(TextView)v.findViewById(R.id.id_tip);

Bundleb=getArguments();

Stringtitle=b.getString("TITLES");

tip.setText(title);

returnv;

}

@Override

publicvoidonActivityCreated(BundlesavedInstanceState){

//TODOAuto-generatedmethodstub

super.onActivityCreated(savedInstanceState);

}

}

就是弄了一個布局,然後從中取得參數並顯示。

 

錨點

 

第五步:ViewPager的適配器TabAdapter.java

[java]view plaincopy

print?

 

在CODE上查看代碼片

 

 

派生到我的代碼片

 

packageorg.yanzi.viewpager.adapter;

importorg.yanzi.constant.Constant;

importorg.yanzi.fragment.MainFragment;

importandroid.os.Bundle;

importandroid.support.v4.app.Fragment;

importandroid.support.v4.app.FragmentManager;

importandroid.support.v4.app.FragmentPagerAdapter;

publicclassTabAdapterextendsFragmentPagerAdapter{

publicTabAdapter(FragmentManagerfm){

super(fm);

//TODOAuto-generatedconstructorstub

}

@Override

publicFragmentgetItem(intposition){

//TODOAuto-generatedmethodstub

MainFragmentfragment=newMainFragment();

Bundleb=newBundle();

Stringtitle=Constant.TITLES[position];

b.putString("TITLES",title);

fragment.setArguments(b);

returnfragment;

}

@Override

publicCharSequencegetPageTitle(intposition){

//TODOAuto-generatedmethodstub

returnConstant.TITLES[position];

}

@Override

publicintgetCount(){

//TODOAuto-generatedmethodstub

returnConstant.TITLES.length;

}

}

主要是重寫getItem,在這裡實例化Fragment,同時設傳遞的參數。其實這裡可以通過 [java]view plaincopy

print?

 

在CODE上查看代碼片

 

 

派生到我的代碼片

 

FragmentManager 按照Tag查找對應的Fragment是否存在,再進行實例化。

另外,getPageTitle這個接口必須重寫,其實看TabPageIndicator.Java這個類的實現可以發現,它需要傳進去一個ViewPager,然後獲得適配器,從適配器裡得到Title。因為用了這個開源包,不能再用ViewPager的setOnPageChangeListener接口,只能用mPageIndicator.setOnPageChangeListener(listener)進行監聽。

完畢,源碼鏈接:鏈接:http://pan.baidu.com/s/1bn4EFbp 密碼:dx4s

效果如下:

 

\
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved