仿知乎日報第六篇:為MainFragement加載數(shù)據(jù)
來源:程序員人生 發(fā)布時間:2016-10-04 11:31:23 閱讀次數(shù):2886次
1.前面講了,MainFragment的布局就是1個ViewPager,而ViewPager的1個個頁面就是首頁,平常心理學,用戶推薦日報,電影日報,不準無聊,設計日報,大公司日報,財經(jīng)日報,互聯(lián)網(wǎng)安全,開始游戲,音樂日報,動漫日報,體育日報這13個頁面組成。
所以呢,接下來我們要創(chuàng)建這13個頁面,大致思路就是將這13個頁面共同的內容和邏輯抽取為BasePage,然后13個頁面繼承這個BasePage,在各自的Page里面寫各自不同的東西。
那BasePage里面的結構仍然是MVC結構,initView()方法里面是加載布局,initData()方法里面是加載數(shù)據(jù),initListener()方法里面是加載各種事件。其中我們會為這13個頁面寫1個共同的布局文件,然后在initView()里面加載出來。這個時候這個布局應當設為成員變量,然后用getRoot()方法得到這個布局。要這個布局有甚么用呢?我們前面說這13個頁面是ViewPager的頁面,在ViewPager的instantiateItem()方法里面需要加載13個頁面的View。
2.
1.說了這么多,首先我們要看看13個頁面究竟是甚么樣的。


注意:這13個頁面布局除首頁不1樣,其他12個頁面都是1樣的,就像上面設計日報的布局1樣。接下來我們用代碼來說到底實現(xiàn)的
2.
代碼:(main_fragment_base_page.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#3CB371"
android:gravity="center_vertical">
<ImageButton
android:id="@+id/ib_base_toggle"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@android:color/transparent"
android:paddingLeft="15dp"
android:src="@drawable/img_menu" />
<TextView
android:id="@+id/tv_base_title"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/ib_base_toggle"
android:gravity="center"
android:text="首頁"
android:textColor="#FFFFFF"
android:textSize="23sp"/>
<ImageButton
android:id="@+id/ib_base_login"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:layout_marginRight="45dp"
android:background="@android:color/transparent"
android:src="@drawable/message"
android:visibility="gone"/>
<ImageButton
android:id="@+id/ib_base_setting"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:layout_marginRight="15dp"
android:background="@android:color/transparent"
android:src="@drawable/abc_ic_menu_moreoverflow_mtrl_alpha"
android:visibility="gone"/>
</RelativeLayout>
<ListView
android:id="@+id/lv_main_content_news"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:dividerHeight="0dp"
android:divider="@null"
android:cacheColorHint="@android:color/transparent"
>
</ListView>
</LinearLayout>
效果:


全部就是1個LinearLayout,上面是1個自己定義的ActionBar,就是1個RelativeLayout,里面有兩個ImageButton,1個TextView。左側的ImageButton是開關toggle,右側的ImageButton是設置setting。這個setting的ImageButton只有首頁有,其他頁面都沒有,所以設為看不見,home頁面的時候再設為看得見。下面就是1個ListView。
這時候候你會好奇,中間的東西呢,我特地用半透明的黑色遮住了。這部份布局為何不直接放在ListView的上面呢?如果真的把這部份布局放在ListView上面,那末你的手指往上滑的時候,只有ListView的內容是往上面轉動的,這部份布局是不動的,由于它不是ListView的1部份,怎樣會隨著ListView1起滾呢。所以我們把部份抽取出來,單獨放在1個布局文件,再在代碼中把布局加載成1個View,作為ListView的頭,用ListView的addHeaderView()方法將頭布局加載進來。
3.ListView的頭布局文件 (main_content_head_view.xml)
<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="match_parent"
android:layout_height="230dp">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.zhihudiary.view.InterceptViewPager
android:id="@+id/vp_main_content_luobopic"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<ImageView
android:id="@+id/iv_main_content_pic"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#696969"
android:scaleType="fitXY"
android:visibility="gone"/>
</FrameLayout>
<FrameLayout
android:id="@+id/fl_main_content_lunbo_points"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="20dp">
<LinearLayout
android:id="@+id/ll_main_content_lunbo_points"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
</LinearLayout>
</FrameLayout>
<TextView
android:id="@+id/tv_main_content_news_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="40dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:textColor="#FFFFFF"
android:textSize="20sp"/>
</RelativeLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginBottom="10dp"
android:layout_marginTop="20dp">
<TextView
android:id="@+id/tv_main_content_home_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="20dp"
android:gravity="center"
android:text="本日熱文"
android:textColor="#8B8682"
android:textSize="14sp"/>
<LinearLayout
android:id="@+id/ll_main_content_editors"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="20dp"
android:text="主編"
android:textColor="#8B8682"
android:textSize="14sp"/>
<LinearLayout
android:id="@+id/ll_main_content_editor_pics"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="20dp"
android:gravity="center_vertical"
android:orientation="horizontal">
</LinearLayout>
</LinearLayout>
</FrameLayout>
</LinearLayout>
效果:


全部就是1個LinearLayout,上面是1個RelativeLayout,用黃色框起來的部份在首頁是ViewPager,在其他頁面是ImageView,大小都是1樣,都是match父布局RelativeLayout。現(xiàn)在我們的需求就是ViewPager和ImageView位于相同的位置,只是在不同的頁面1個顯示1個不顯示。怎樣實現(xiàn)呢?很簡單,只要將這兩個布局都放在FrameLayout里面就能夠FrameLayout會把他們疊放在1起,這個時候呢,只要在首頁顯示ViewPager,隱藏ImageView,在其他頁面顯示ImageView,隱藏ViewPager就能夠了
藍色框起來的部份也是這樣,TextView和LinearLayout都放在FrameLayout里面,在首頁顯示TextView,隱藏LinearLayout,在其他頁面顯示LinearLayout,隱藏TextView。
首頁的ViewPager的下臉部分會生成和ViewPager的頁面數(shù)量相同的灰色的點,當滑倒相應的頁面的時候,相應位置的點會動態(tài)變成白色。說起來好像不好理解,其實大部份人在實際使用App的時候應當或多或少地遇到過,聯(lián)系下實際就能夠了。
4.還有1個地方需要特別講授1下首頁的ViewPager又不是正常的ViewPager,而是1個自定義的InterceptViewPage。我們要繼承1下ViewPager,對它進行1點修改。
代碼:
public class InterceptViewPager extends ViewPager {
private float mDownX;
private float mDownY;
public InterceptViewPager(Context context, AttributeSet attrs){
super(context, attrs);
// TODO自動生成的構造函數(shù)存根
}
public InterceptViewPager(Context context) {
super(context);
// TODO自動生成的構造函數(shù)存根
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mDownX = ev.getX();
mDownY = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
float moveX = ev.getX();
float moveY = ev.getY();
float dX = moveX - mDownX;
float dY = moveY - mDownY;
// <span style="white-space:pre"> </span> 如果是橫向滑動
if (Math.abs(dX) > Math.abs(dY)) {
// 要求父控件不攔截Touch事件,自己來處理
getParent().requestDisallowInterceptTouchEvent(true);
}
break;
default:
break;
}
return super.dispatchTouchEvent(ev);
}
}
其實代碼很簡單,就是當橫向滑動的時候,滑動事件讓父組件不要攔截,由自己來處理。如果不做這樣1個小修改的話,你會發(fā)現(xiàn)從左往右滑的時候沒有問題,1旦從右往左滑的時候會把菜單區(qū)域滑出來,由于父組件也有滑動事件。
3.我們布局都準備好了,現(xiàn)在要回到BasePage頁面把它們加載進來 (BasePage.java)
public abstract class BasePage {
// 權限為protected,則所有的子類可以直接使用
protected ImageButton ibLogin;
protected ImageButton ibSetting;
protected ImageButton ibToggleButton;
protected TextView tvTitle;
protected ListView lvNews;
protected ViewPager vpLunboPic;
protected LinearLayout llLunboPoints;
protected TextView tvLunboTitle;
protected MainActivity mainActivity;
protected TextView tvHomeTitle;
protected LinearLayout llEditorPics;
protected LinearLayout llEditors;
private View mBaseView;
protected FrameLayout mFlLunboPoints;
protected ImageView ivPic;
public BasePage(MainActivity mainActivity) {
// 把上下文傳進來,即MainActivity,MainActivity是Activity,也是Context的子類
this.mainActivity = mainActivity;
// 加載布局
initView();
// 初始化事件
initListener();
}
/**
* 初始化事件
*/
protected void initListener() {
// 開關1點擊,則拿到SlidingMenu,用toggle方法控制菜單區(qū)域的開關
ibToggleButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mainActivity.getSlidingMenu().toggle();
}
});
// 設置按鈕1點擊,則進入設置的Activity
ibSetting.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(mainActivity,SettingActivity.class);
mainActivity.startActivity(intent);
}
});
}
/**
*
* @param themeDailyNumber主題日報的序號
* MainFragment中的ViewPager的instantiateItem方法中調用該方法為布局加載數(shù)據(jù)
*/
public void initData(String themeDailyNumber){
};
protected void initView() {
// 加載布局
mBaseView = View.inflate(mainActivity,
R.layout.main_fragment_base_page, null);
ibSetting = (ImageButton) mBaseView.findViewById(R.id.ib_base_setting);
tvTitle = (TextView) mBaseView.findViewById(R.id.tv_base_title);
lvNews = (ListView) mBaseView.findViewById(R.id.lv_main_content_news);
ibToggleButton = (ImageButton) mBaseView
.findViewById(R.id.ib_base_toggle);
/* vpLunboPic= (ViewPager) mBaseView
.findViewById(R.id.vp_main_content_luobopic);
llLunboPoints = (LinearLayout) mBaseView
.findViewById(R.id.ll_main_content_lunbo_points);
tvLunboTitle = (TextView) mBaseView
.findViewById(R.id.tv_main_content_news_title);
tvHomeTitle = (TextView) mBaseView
.findViewById(R.id.tv_main_content_home_title);
llEditorPics = (LinearLayout) mBaseView
.findViewById(R.id.ll_main_content_editor_pics);
llEditors = (LinearLayout) mBaseView
.findViewById(R.id.ll_main_content_editors);*/
// 為ListView加載頭布局
initHeadView();
}
private void initHeadView() {
// 加載頭布局,并拿出里面的組件
View headView = View.inflate(mainActivity,
R.layout.main_content_head_view, null);
vpLunboPic = (ViewPager) headView
.findViewById(R.id.vp_main_content_luobopic);
ivPic = (ImageView) headView.findViewById(R.id.iv_main_content_pic);
llLunboPoints = (LinearLayout) headView
.findViewById(R.id.ll_main_content_lunbo_points);
tvLunboTitle = (TextView) headView
.findViewById(R.id.tv_main_content_news_title);
tvHomeTitle = (TextView) headView
.findViewById(R.id.tv_main_content_home_title);
llEditorPics = (LinearLayout) headView
.findViewById(R.id.ll_main_content_editor_pics);
llEditors = (LinearLayout) headView
.findViewById(R.id.ll_main_content_editors);
mFlLunboPoints = (FrameLayout) headView.findViewById(R.id.fl_main_content_lunbo_points);
// 把頭布局加進ListView中
lvNews.addHeaderView(headView);
}
/**
* @return布局View,MainFragment中的ViewPager的instantiateItem調用這個方法,
* 可以把頁面的布局顯示在ViewPager上面
*/
public View getRoot() {
return mBaseView;
}
}
4. 創(chuàng)建首頁,平常心理學,用戶推薦日報,電影日報,不準無聊,設計日報,大公司日報,財經(jīng)日報,互聯(lián)網(wǎng)安全,開始游戲,音樂日報,動漫日報,體育日報這13個頁面。

所有頁面都繼承BasePage,并重寫initData()方法,super.initData(themeDailyNumber)履行父類的initData()方法中的所有邏輯,然后再履行自己的方法
以設計日報DesignPage為例:
public class DesignPage extends ThemeDailyBasePage {
public DesignPage(MainActivity mainActivity) {
super(mainActivity);
// TODO自動生成的構造函數(shù)存根
}
@Override
public void initData(String themeDailyNumber) {
tvTitle.setText("設計日報");
super.initData(themeDailyNumber);
}
}
其他的頁面都是這樣,頁面就加載好了,怎樣為各個頁面加載數(shù)據(jù)后面會講。
5.13個頁面終究創(chuàng)建好了,現(xiàn)在我們要把他們作為數(shù)據(jù)源添加到ViewPager里面去
public class MainFragment extends BaseFragment {
// 13個頁面的集合
private List<BasePage> allPages = new ArrayList<BasePage>();
private MyViewPager mViewPager;
// 12個主題日報的id,例如平常心理學的id為13,用戶推薦日報對應的id為12,
// 后面獲得相應的主題日報的url為http://news-at.zhihu.com/api/4/theme/ + id
// 例如要拿到平常心理學日報的數(shù)據(jù)url為http://news-at.zhihu.com/api/4/theme/13
private String[] themeDailyNumber = { "13", "12", "3", "11", "4",
"5", "6", "10", "2", "7", "9", "8" };
private int selectedPosition = 0;
@Override
protected View initView() {
// 加載布局
View root = View.inflate(mainActivity, R.layout.main_fragment_base, null);
// 拿到布局中的ViewPager組件
mViewPager = (MyViewPager) root.findViewById(R.id.vp_base_fragment);
return root;
}
@Override
protected void initData() {
super.initData();
// 創(chuàng)建13個頁面對象,作為ViewPager的數(shù)據(jù)源
HomeBasePage homeBasePage = new HomeBasePage(mainActivity);
DailyPsychologyPage dailyPsychologyPage = newDailyPsychologyPage(mainActivity);
UserRecommendPage userRecommendPage = new UserRecommendPage(mainActivity);
MoviePage moviePage = new MoviePage(mainActivity);
NoBoringPage noBoringPage = new NoBoringPage(mainActivity);
DesignPage designPage = new DesignPage(mainActivity);
BigCompanyPage bigCompanyPage = new BigCompanyPage(mainActivity);
FinancePage financePage = new FinancePage(mainActivity);
InternetPage internetPage = new InternetPage(mainActivity);
GamePage gamePage = new GamePage(mainActivity);
MusicPage musicPage = new MusicPage(mainActivity);
CartoonPage cartoonPage = new CartoonPage(mainActivity);
SportsPage sportsPage = new SportsPage(mainActivity);
// 13個頁面加進集合
allPages.add(homeBasePage);
allPages.add(dailyPsychologyPage);
allPages.add(userRecommendPage);
allPages.add(moviePage);
allPages.add(noBoringPage);
allPages.add(designPage);
allPages.add(bigCompanyPage);
allPages.add(financePage);
allPages.add(internetPage);
allPages.add(gamePage);
allPages.add(musicPage);
allPages.add(cartoonPage);
allPages.add(sportsPage);
// 為ViewPager設置Adapter
MyAdapter myAdapter = new MyAdapter();
mViewPager.setAdapter(myAdapter);
}
// 根據(jù)傳進來的位置編號在13個頁面之間切換
public void switchPage(int position){
// selectedPosition成員變量記錄傳進來的編號
this.selectedPosition = position;
// 這個方法會調用Adapter中的getView方法
mViewPager.setCurrentItem(position);
}
private class MyAdapter extends PagerAdapter{
@Override
public int getCount() {
// TODO自動生成的方法存根
return allPages.size();
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
// TODO自動生成的方法存根
return arg0 == arg1;
}
@Override
public void destroyItem(ViewGroup container, int position, Objectobject) {
// TODO自動生成的方法存根
container.removeView((View) object);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
// 根據(jù)position拿到相應的頁面
BasePage selectedPage = allPages.get(position);
// 拿到相應頁面的View,加到容器中
container.addView(selectedPage.getRoot());
// 在這里調用initData()方法加載13個頁面的數(shù)據(jù)。
// 如果selectedPosition為0,則為首頁
// 如果selectedPosition不為0,則是其他12個主題日報,把對應的id傳進去
if (selectedPosition != 0) {
selectedPage.initData(themeDailyNumber[selectedPosition ⑴]);
}else {
selectedPage.initData("");
}
return selectedPage.getRoot();
}
}
}
上面的進程也容易:
1)創(chuàng)建13頁面的對象,加進集合中作為ViewPager的數(shù)據(jù)源
2)用數(shù)據(jù)源為ViewPager創(chuàng)建Adapter
3)為ViewPager設置Adapter
你們只需要看懂上面進程的代碼就能夠了,其他的后面會講到
生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對您的學習有所幫助,可以手機掃描二維碼進行捐贈