另外一種主界面風格則是以網易新聞、鳳凰新聞以及新推出的新浪博客(閱讀版)為代表。使用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的包里么有這個限制。
下圖是網易新聞、鳳凰新聞、新浪博客的截圖:

關於仿網易新聞client代碼已經非常多了,本人主要依據開源的這個CSDNclient的制作,准備一步步搞下。這本是一個大牛之作發在oschina上,參考鏈接里分5步去實現。
我看了它的代碼。是染在一起的。比方要完這個導航不須要額外的三個包。而他的資源里是弄一起的。
所以准備自己玩玩,順便記錄開發中的問題。
第一步:最上面的導航欄
即有“網易新聞”四個大字這一欄。
布局文件head_title_panel.xml:
<?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="wrap_content" android:background="@color/light_blue" android:orientation="horizontal" > <ImageView 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" /> <ImageView 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" /> <TextView 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"> </TextView> </LinearLayout>
為了日后操作上的方便,我將它映射成一個HeadTitlePanel.java文件,能夠看到這樣的寫法跟上篇 上下panel的定義是有點差別的。
package org.yanzi.ui;
import org.yanzi.csdnproject.R;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class HeadTitlePanel extends RelativeLayout {
private Context mContext;
private TextView mHeadTV;
private ImageView mHeadIcon;
private ImageView mHeadDivider;
public HeadTitlePanel(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
mContext = context;
View parent = 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
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#eee"
tools:context=".MainActivity" >
<org.yanzi.ui.HeadTitlePanel
android:id="@+id/head_title_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true" />
<com.viewpagerindicator.TabPageIndicator
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.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/page_indicator"
/>
</RelativeLayout>
MainActivity.java
package org.yanzi.csdnproject;
import org.yanzi.viewpager.adapter.TabAdapter;
import com.viewpagerindicator.TabPageIndicator;
import android.os.Bundle;
import android.app.Activity;
import android.app.FragmentManager;
import android.view.Menu;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
public class MainActivity extends FragmentActivity {
private TabPageIndicator mPageIndicator;
private ViewPager mViewPager;
private FragmentPagerAdapter fragPagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initUI();
fragPagerAdapter = new TabAdapter(getSupportFragmentManager());
mViewPager.setAdapter(fragPagerAdapter);
mPageIndicator.setViewPager(mViewPager, 0);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private void initUI(){
mPageIndicator = (TabPageIndicator)findViewById(R.id.page_indicator);
mViewPager = (ViewPager)findViewById(R.id.view_pager);
}
}
出奇的簡單,比單純用Fragment還簡單,原因是僅僅需把Fragment塞到適配器里就ok了。適配器為我們做了Fragment的切換等工作。我們能做的也就是在適配器里new Fragment的時候推斷是否已存在。
以下幾點須要注意:
1、在styles.xml里它定義了樣式:
<style name="MyTheme" parent="AppBaseTheme">
<item name="vpiTabPageIndicatorStyle">@style/MyWidget.TabPageIndicator</item>
<item name="android:windowBackground">@drawable/init_pic</item>
<item name="android:windowNoTitle">true</item>
<item name="android:animationDuration">5000</item>
<item name="android:windowContentOverlay">@null</item>
</style>
<style name="MyWidget.TabPageIndicator" parent="Widget">
<item name="android:gravity">center</item>
<item name="android:background">@drawable/vpi__tab_indicator</item>
<item name="android:paddingLeft">22dip</item>
<item name="android:paddingRight">22dip</item>
<item name="android:paddingTop">8dp</item>
<item name="android:paddingBottom">8dp</item>
<item name="android:textAppearance">@style/MyTextAppearance.TabPageIndicator</item>
<item name="android:textSize">16sp</item>
<item name="android:maxLines">1</item>
</style>
<style name="MyTextAppearance.TabPageIndicator" parent="Widget">
<item name="android:textStyle">bold</item>
<item name="android:textColor">@color/black</item>
</style>這個是依賴於導進去的包的。
2、它這里用了android:windowBackground的屬性,所以app開啟瞬間會有圖片彈出,之后設置MainActivity的布局背景為android:background="#eee",又把圖片替換了。假設不設android:background="#eee" 會一直看到這個圖片不消失。
3、由於開篇講的原因,MainActivity僅僅能繼承自FragmentActivity。
第四步:MainFragment.java,此類繼承Fragment。且是android.support.v4.app.Fragment下的。
package org.yanzi.fragment;
import org.yanzi.csdnproject.R;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class MainFragment extends Fragment {
private int mNewsType = 0;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View v = inflater.inflate(R.layout.tab_item_fragment_main, null);
TextView tip = (TextView) v.findViewById(R.id.id_tip);
Bundle b = getArguments();
String title = b.getString("TITLES");
tip.setText(title);
return v;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
}
}
就是弄了一個布局,然后從中取得參數並顯示。第五步:ViewPager的適配器TabAdapter.java
package org.yanzi.viewpager.adapter;
import org.yanzi.constant.Constant;
import org.yanzi.fragment.MainFragment;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
public class TabAdapter extends FragmentPagerAdapter {
public TabAdapter(FragmentManager fm) {
super(fm);
// TODO Auto-generated constructor stub
}
@Override
public Fragment getItem(int position) {
// TODO Auto-generated method stub
MainFragment fragment = new MainFragment();
Bundle b = new Bundle();
String title = Constant.TITLES[position];
b.putString("TITLES", title);
fragment.setArguments(b);
return fragment;
}
@Override
public CharSequence getPageTitle(int position) {
// TODO Auto-generated method stub
return Constant.TITLES[position];
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return Constant.TITLES.length;
}
}
主要是重寫getItem,在這里實例化Fragment,同一時候設傳遞的參數。
事實上這里能夠通過
FragmentManager依照Tag查找相應的Fragment是否存在,再進行實例化。另外。getPageTitle這個接口必須重寫。事實上看TabPageIndicator.java這個類的實現能夠發現,它須要傳進去一個ViewPager,然后獲得適配器。從適配器里得到Title。由於用了這個開源包,不能再用ViewPager的setOnPageChangeListener接口,僅僅能用mPageIndicator.setOnPageChangeListener(listener)進行監聽。
完成,源代碼鏈接:鏈接:http://pan.baidu.com/s/1bn4EFbp password:dx4s
效果例如以下:
