繼上篇,要實現點擊側邊欄的標題,新聞頁隨之變動,實際的原理是側邊欄的四個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,很簡單