[安卓]新闻客户端(四) 主页面之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,很简单



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值