[安卓]新聞客戶端(四) 主頁面之slidingMenu & fragment(2)

繼上篇,要實現點擊側邊欄的標題,新聞頁隨之變動,實際的原理是側邊欄的四個listener被點擊後,通過mActivity找到contentFragment,再找到其下的viewpager,然後找到相應的framelayout,去replace。

具體來說,要在側邊欄響應,listener,其中要根據選中的標題,來顯示具體的新聞頁,setCurrentMenuDetailPager(position),這個方法在初始化數據中調用;

這個方法內,要先通過mainActivity獲得mActivity,再通過這個mActivity去調用mainActivity的getContentFragment方法,再調用到contentFragment中的getNewsCenterPager方法找到具體的newspager,再去調用他的setCurrentMenuDetailPager來完成頁面的顯示

側邊欄中

public void initData() {
		// 初始化數據,點擊事件,同時點擊後填充數據,adapter
		super.initData();		
		lv_left_menu.setOnItemClickListener(new OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				// TODO Auto-generated method stub			
				mCurrentPos = position;
				menulistadapter.notifyDataSetChanged();	
				//點擊側邊欄改變新聞頁的內容
				setCurrentMenuDetailPager(position);
			}			
		});	
	}
	private void setCurrentMenuDetailPager(int position) {
		// TODO Auto-generated method stub
		MainActivity MainUI = (MainActivity) mActivity;
		MainUI.getContentFragment().getNewsCenterPager().setCurrentMenuDetailPager(position);
	}

主頁中

// 獲取主頁面fragment
	public ContentFragment getContentFragment() {
		FragmentManager fm = getSupportFragmentManager();
		ContentFragment fragment = (ContentFragment) fm.findFragmentByTag(FRAGMENT_CONTENT);
		return fragment;
	}

ContentFragment中

public NewsCenterPager getNewsCenterPager(){	
		return (NewsCenterPager) mPagerList.get(1);
	}

最後,NewsCenterPager中,注意,他是掛在幀佈局中的,所以最好清除之前的佈局,否則可能有重疊現象;然後找到mPagers這個list,裝4個新聞子內容,根據位置信息來添加

//響應側邊欄的點擊事件,顯示具體的內容
	public void setCurrentMenuDetailPager(int position) {
		//在這個pager裏面的flcontent(幀佈局)裏面增加一個佈局		
		 BaseMenuDetailPager baseMenuDetailPager = mPagers.get(position);
		 flContent.removeAllViews();// 清除之前的佈局
		 flContent.addView( baseMenuDetailPager.mRootView);
		
		 baseMenuDetailPager.initData();// 初始化當前頁面的數據
		 toggleSlidingMenu();
	}

這樣,就能完成點擊側邊欄改變新聞頁內容的功能

再來實現側邊欄的新聞版塊,首先我們需要一個view用來填充,之前直接用的text,這裏應該有一個佈局,上面一欄有一個viewPagerIndicator,viewpager裏的標題欄,這個需要導包,再加上一個imagebutton,點擊後來顯示更多功能鍵,組成一個水平佈局;同時,下面應該是一整個的viewpager,可以滑動,這裏由於功能需求,也是寫了一個類繼承viewpager,後面再說

<?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" >
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
      <com.viewpagerindicator.TabPageIndicator
        android:id="@+id/indicator"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        android:layout_weight="1"/>
      <ImageButton 
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:padding="5dp"
          android:layout_gravity="center_vertical"
          android:background="@android:color/transparent"
          android:src="@drawable/news_cate_arr"
          android:id="@+id/ib_newsmenudetail_arrow"/>
    </LinearLayout>
    <com.example.mynewsapp.view.CanScrollViewPager
        android:id="@+id/vp_menu_detail"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>


此時服務器端的數據更多了,有層次關係,children,新聞裏分各種新聞,NewsMenuDetailPager裏除了繼承Base的構造方法外,還需要一個新的構造方法,參數裏應該帶上更多數據,同時,在NewsCenterPager裏,填充的時候,響應的代碼也應該變化

public class NewsMenuDetailPager extends BaseMenuDetailPager{
	private ArrayList<NewsTabData> tabdata;
	public NewsMenuDetailPager(Activity activity) {
		super(activity);
		// TODO Auto-generated constructor stub
	}
	public NewsMenuDetailPager(Activity mActivity,
			ArrayList<NewsTabData> children) {
		// TODO Auto-generated constructor stub
		super(mActivity);
		tabdata = children;
	}

// 準備4個菜單詳情頁
		mPagers = new ArrayList<BaseMenuDetailPager>();
		/*mPagers.add(new NewsMenuDetailPager(mActivity));*/
		mPagers.add(new NewsMenuDetailPager(mActivity,mNewsData.data.get(0).children));

對於這個children,是一個複雜佈局,所以需要一個新的類來裝他,TabDetailPager,其實裝的就是mRootView,同時需要一個佈局,list

<?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" >
    <ListView
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:cacheColorHint="#FFF"
        android:id="@+id/lv_tab_detail_news"/>
</LinearLayout>


來看這個佈局

首先是viewpager,他需要adapter,在初始化數據時調用,他的數據來自於解析服務器端

看其封裝的數據,children下就是新聞子欄目標題,12個,而children在一開始,點擊新聞中心這個button時就已經解析到了,所以直接傳到adapter就好

所以這裏adapter內,如前文所說,要另一個構造函數,參數帶的children,在其內,拿到children,並將數據給一個arraylist,這樣也無需自己去聯網解析

然後填充viewpager時,又需要一個裝滿view的list,每次在adapter內初始化一個item時,根據position回傳一個view,所以在填數據之前,要先把這個裝view的list裝滿

adapter內的幾個方法,都是要根據TabDetailPager來做相關操作

初始化item是,把tablist裏的東西拿出來封裝成一個類,再用這個類的mRootView來初始化item,這個流程就是搞一個list,再把它填滿,在把他裏面的rootview拿出來給item初始化

然後這時候view裏還需要數據,順便初始化一下,初始化的方法在TabDetailPager內,這裏調用即可,也就是那邊弄得什麼數據,這邊就顯示什麼數據

這裏indicator需要導第三方庫,可以根據需求修改源碼,而不是直接導封裝好的jar包。之前倒庫的時候又同名的,這裏先在外面把這個庫的名字改了再放到workspace裏

public class NewsMenuDetailPager extends BaseMenuDetailPager{
	private ArrayList<NewsTabData> tabdata;
	private ViewPager vp_menu_newsdetail;
	private ArrayList<TabDetailPager>  tabList ;
	private TabPageIndicator indicator;
	private ImageButton ib_newsmenudetail_arrow;
	
	public NewsMenuDetailPager(Activity activity) {
		super(activity);
		// TODO Auto-generated constructor stub
	}
	public NewsMenuDetailPager(Activity mActivity,
			ArrayList<NewsTabData> children) {
		// TODO Auto-generated constructor stub
		super(mActivity);
		tabdata = children;
	}

	@Override
	public View initViews() {
		View view = View.inflate(mActivity, R.layout.news_menu_detail, null);
		  vp_menu_newsdetail = (ViewPager) view.findViewById(R.id.vp_menu_detail);
		  indicator = (TabPageIndicator)view.findViewById(R.id.indicator);
		  //indicator.setViewPager(vp_menu_newsdetail);這裏寫會報錯,因爲initView的時候 adapter還沒有
		  ib_newsmenudetail_arrow = (ImageButton) view.findViewById(R.id.ib_newsmenudetail_arrow);	  
		  ib_newsmenudetail_arrow.setOnClickListener(new OnClickListener() {		
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				int currentItem = vp_menu_newsdetail.getCurrentItem();
				vp_menu_newsdetail.setCurrentItem(++currentItem, false);
			}
		});		  
		return view;
	}
	@Override
	public void initData() {
		// TODO Auto-generated method stub
		super.initData();
        tabList = new ArrayList<TabDetailPager>();	
		for (int i =0;i<tabdata.size();i++){
			tabList.add(new TabDetailPager(mActivity,tabdata.get(i)));
		}		
		//給detial頁面中的viewpager 設置數據
		 vp_menu_newsdetail.setAdapter(new  MenuDetialVpAdapter());		
         indicator.setViewPager(vp_menu_newsdetail); 
	}
	
	class MenuDetialVpAdapter extends PagerAdapter{

		@Override
		public int getCount() {
			// TODO Auto-generated method stub
			return tabList.size();
		}

		@Override
		public boolean isViewFromObject(View arg0, Object arg1) {
			// TODO Auto-generated method stub
			return arg0==arg1;
		}
		
		@Override
		public Object instantiateItem(ViewGroup container, int position) {
			TabDetailPager tabDetailPager = tabList.get(position);
			container.addView(tabDetailPager.mRootView);
			tabDetailPager.initData();
			return tabList.get(position).mRootView;		
		}	
		@Override
		public void destroyItem(ViewGroup container, int position, Object object) {
			// TODO Auto-generated method stub		
		    container.removeView(tabList.get(position).mRootView);
		}		
		@Override
		public CharSequence getPageTitle(int position) {
		   return tabdata.get(position).title;
		}
	}
}

另外,僅僅導入了indicator還是不夠的,雖然小標題欄能滑動,但是沒有文本顯示標題,需要重寫title,也是從children中拿的,如上代碼所示

然後調整格式

這裏導入的庫再引用的,直接在庫的文件裏看styles,然後要改什麼屬性,就直接點進去改,這是原來的


這裏主要也是背景和文字在點擊時的顏色變動,給了一個selector,比如背景,沒選中時時透明色,選中了給一個圖標,字體選中時紅色,未選中時黑色

修改後





還有此時背景黑色,可以去項目的main裏面改成白色

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFF"
    android:id="@+id/fl_content">
</FrameLayout>

然後manifest裏應該註冊theme

<activity android:name=".MainActivity"
            android:theme="@style/Theme.PageIndicatorDefaults">
        </activity>


還有一個button,不能在佈局裏寫個onclick屬性,然後再寫個方法來啓用這個listener,因爲這個類是一個單純的類,系統不調用他,所以應該通過setOnClickListener來註冊他

 ib_newsmenudetail_arrow.setOnClickListener(new OnClickListener() {		
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				int currentItem = vp_menu_newsdetail.getCurrentItem();
				//當前的獲取到,加一個就是滑動後的下一個,false代表中間不要過渡動畫
				vp_menu_newsdetail.setCurrentItem(++currentItem, false);
			}
		});		  

然後還有個bug,點擊側邊欄的新聞後,在新聞頁裏左右滑動,總是會自動脫拖出標題欄,往左滑的時候,畫面也不正常,這是由於安卓touch機制引起的,所以前面的viewpager是繼承寫的,然後這裏要處理ontouch事件,同前面的類似,而且這裏還有一個問題,在第一個頁面的時候就不能往左拖了,在這裏改一下,需要做一個判斷,讓他的父控件能處理,才能給到activity,再給到leftmenu,第0個item還是讓父控件處理

public class CanScrollViewPager extends ViewPager{
	public CanScrollViewPager(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}
	public CanScrollViewPager(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}
	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {		
		if (getCurrentItem() != 0) {
			getParent().requestDisallowInterceptTouchEvent(true);// 用getParent去請求,不攔截
		} else {// 如果是第一個頁面,需要顯示側邊欄, 請求父控件攔截
			getParent().requestDisallowInterceptTouchEvent(false);// 攔截
		}	
		return super.dispatchTouchEvent(ev);
	}
}


然後要完善tabDetailMenu,他是一個複雜佈局,用來顯示具體內容的,內部是一個viewpager和list,看具體的服務器端的數據,裏面具體的內容是給了一個URL,指向一些文件


URL對應的文件夾下,也有一個JSON數據


topnews下有4個資源,對應着頁面裏橫向的viewpager

另外news下由10條新聞,對應着list裏的數據

這個數據的解析,實際上在點擊側邊欄新聞後,newsmenu裏要獲取到這個數據,adapter裏要填充,調用的tabmenudetail初始化數據方法,要在其中去解析數據

想要解析這些數據,則需要在父親初始化tabmenu時,把數據傳進來,也就是需要新的構造函數

解析依然用的xutils,很簡單



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章