Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 仿知乎日報第六篇:為MainFragement加載數據

仿知乎日報第六篇:為MainFragement加載數據

編輯:關於Android編程

一.前面講了,MainFragment的布局就是一個ViewPager,而ViewPager的一個個頁面就是首頁,日常心理學,用戶推薦日報,電影日報,不許無聊,設計日報,大公司日報,財經日報,互聯網安全,開始游戲,音樂日報,動漫日報,體育日報這13個頁面組成。

所以呢,接下來我們要創建這13個頁面,大致思路就是將這13個頁面共同的內容和邏輯抽取為BasePage,然後13個頁面繼承這個BasePage,在各自的Page裡面寫各自不同的東西。

那BasePage裡面的結構依然是MVC結構,initView()方法裡面是加載布局,initData()方法裡面是加載數據,initListener()方法裡面是加載各種事件。其中我們會為這13個頁面寫一個共同的布局文件,然後在initView()裡面加載出來。這個時候這個布局應該設為成員變量,然後用getRoot()方法得到這個布局。要這個布局有什麼用呢?我們前面說這13個頁面是ViewPager的頁面,在ViewPager的instantiateItem()方法裡面需要加載13個頁面的View。

二.

1.說了這麼多,首先我們要看看13個頁面究竟是什麼樣的。

\

\

 

 

注意:這13個頁面布局除了首頁不一樣,其他12個頁面都是一樣的,就像上面設計日報的布局一樣。接下來我們用代碼來講到底實現的

2.

代碼:(main_fragment_base_page.xml)

 

 


 
    
 
        
 
        
 
        
 
        
    
 
   
  
   
      
    
   
 


 

效果:

 

\

 

\

 

整個就是一個LinearLayout,上面是一個自己定義的ActionBar,就是一個RelativeLayout,裡面有兩個ImageButton,一個TextView。左邊的ImageButton是開關toggle,右邊的ImageButton是設置setting。這個setting的ImageButton只有首頁有,其他頁面都沒有,所以設為看不見,home頁面的時候再設為看得見。下面就是一個ListView。

這時候你會好奇,中間的東西呢,我特意用半透明的黑色遮住了。這部分布局為什麼不直接放在ListView的上面呢?如果真的把這部分布局放在ListView上面,那麼你的手指往上滑的時候,只有ListView的內容是往上面滾動的,這部分布局是不動的,因為它不是ListView的一部分,怎麼會跟著ListView一起滾呢。所以我們把部分抽取出來,單獨放在一個布局文件,再在代碼中把布局加載成一個View,作為ListView的頭,用ListView的addHeaderView()方法將頭布局加載進來。

3.ListView的頭布局文件 (main_content_head_view.xml)

 

 


 
    
 
        <framelayout android:layout_height="match_parent" android:layout_width="match_parent">
 
            
 
            
        </framelayout>
 
        <framelayout android:id="@+id/fl_main_content_lunbo_points" android:layout_alignparentbottom="true" android:layout_centerhorizontal="true" android:layout_height="wrap_content" android:layout_marginbottom="20dp" android:layout_width="wrap_content">
 
            
            
        </framelayout>
 
        
    
 
    <framelayout android:layout_height="40dp" android:layout_marginbottom="10dp" android:layout_margintop="20dp" android:layout_width="match_parent">
 
        
 
        
 
            
 
            
            
        
    </framelayout>
 


 

 

效果:

\

 

\

 

 

整個就是一個LinearLayout,上面是一個RelativeLayout,用黃色框起來的部分在首頁是ViewPager,在其他頁面是ImageView,大小都是一樣,都是match父布局RelativeLayout。現在我們的需求就是ViewPager和ImageView位於相同的位置,只是在不同的頁面一個顯示一個不顯示。怎樣實現呢?很簡單,只要將這兩個布局都放在FrameLayout裡面就可以FrameLayout會把他們疊放在一起,這個時候呢,只要在首頁顯示ViewPager,隱藏ImageView,在其他頁面顯示ImageView,隱藏ViewPager就可以了

藍色框起來的部分也是這樣,TextView和LinearLayout都放在FrameLayout裡面,在首頁顯示TextView,隱藏LinearLayout,在其他頁面顯示LinearLayout,隱藏TextView。

首頁的ViewPager的下面部分會生成和ViewPager的頁面數量相同的灰色的點,當滑倒相應的頁面的時候,相應位置的點會動態變成白色。說起來好像不好理解,其實大部分人在實際使用App的時候應該或多或少地遇到過,聯系下實際就可以了。

4.還有一個地方需要特別講解一下首頁的ViewPager又不是正常的ViewPager,而是一個自定義的InterceptViewPage。我們要繼承一下ViewPager,對它進行一點修改。

代碼:

 

public class InterceptViewPager extends ViewPager {
 
    private float mDownX;
    private float mDownY;
 
    public InterceptViewPager(Context context, AttributeSet attrs){
       super(context, attrs);
       // TODO自動生成的構造函數存根
    }
 
    public InterceptViewPager(Context context) {
       super(context);
       // TODO自動生成的構造函數存根
    }
 
    @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;
//     	   如果是橫向滑動
           if (Math.abs(dX) > Math.abs(dY)) {
//         請求父控件不攔截Touch事件,自己來處理
              getParent().requestDisallowInterceptTouchEvent(true);
           }
 
           break;
 
      
       default:
           break;
       }
       return super.dispatchTouchEvent(ev);
    }
 
}


 

其實代碼很簡單,就是當橫向滑動的時候,滑動事件讓父組件不要攔截,由自己來處理。如果不做這樣一個小修改的話,你會發現從左往右滑的時候沒有問題,一旦從右往左滑的時候會把菜單區域滑出來,因為父組件也有滑動事件。

三.我們布局都准備好了,現在要回到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() {
//     開關一點擊,則拿到SlidingMenu,用toggle方法控制菜單區域的開關
       ibToggleButton.setOnClickListener(new OnClickListener() {
          
           @Override
           public void onClick(View v) {
              mainActivity.getSlidingMenu().toggle();
           }
       });
//  設置按鈕一點擊,則進入設置的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方法中調用該方法為布局加載數據
     */
    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;
    }
 
}

 

四. 創建首頁,日常心理學,用戶推薦日報,電影日報,不許無聊,設計日報,大公司日報,財經日報,互聯網安全,開始游戲,音樂日報,動漫日報,體育日報這13個頁面。

\

所有頁面都繼承BasePage,並重寫initData()方法,super.initData(themeDailyNumber)執行父類的initData()方法中的所有邏輯,然後再執行自己的方法

以設計日報DesignPage為例:

 

public class DesignPage extends ThemeDailyBasePage {
 
    public DesignPage(MainActivity mainActivity) {
       super(mainActivity);
       // TODO自動生成的構造函數存根
    }
    @Override
    public void initData(String themeDailyNumber) {
       tvTitle.setText("設計日報");
       super.initData(themeDailyNumber);
    }
 
}


 

其他的頁面都是這樣,頁面就加載好了,怎樣為各個頁面加載數據後面會講。

五.13個頁面終於創建好了,現在我們要把他們作為數據源添加到ViewPager裡面去

 

public class MainFragment extends BaseFragment {
//  13個頁面的集合
    private List allPages = new ArrayList();
    private MyViewPager  mViewPager;
//  12個主題日報的id,例如日常心理學的id為13,用戶推薦日報對應的id為12,
//  後面獲取相應的主題日報的url為http://news-at.zhihu.com/api/4/theme/  + id
//  例如要拿到日常心理學日報的數據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();
//     創建13個頁面對象,作為ViewPager的數據源
       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);
      
      
    }
//  根據傳進來的位置編號在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) {
//         根據position拿到相應的頁面
           BasePage selectedPage = allPages.get(position);
//         拿到相應頁面的View,加到容器中
           container.addView(selectedPage.getRoot());
//         在這裡調用initData()方法加載13個頁面的數據。
//         如果selectedPosition為0,則為首頁
//         如果selectedPosition不為0,則是其他12個主題日報,把對應的id傳進去
           if (selectedPosition != 0) {
              selectedPage.initData(themeDailyNumber[selectedPosition -1]);
           }else {
              selectedPage.initData("");
           }
          
           return selectedPage.getRoot();
       }
      
    }
 
}

 

上面的過程也容易:

1)創建13頁面的對象,加進集合中作為ViewPager的數據源

2)用數據源為ViewPager創建Adapter

3)為ViewPager設置Adapter

你們只需要看懂上面過程的代碼就可以了,其他的後面會講到

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