[安卓]新闻客户端(四) 主页面之slidingMenu & fragment(2)

来源:互联网 发布:java 编码url 空格 20 编辑:程序博客网 时间:2024/04/30 00:46

继上篇,要实现点击侧边栏的标题,新闻页随之变动,实际的原理是侧边栏的四个listener被点击后,通过mActivity找到contentFragment,再找到其下的viewpager,然后找到相应的framelayout,去replace。

具体来说,要在侧边栏响应,listener,其中要根据选中的标题,来显示具体的新闻页,setCurrentMenuDetailPager(position),这个方法在初始化数据中调用;

这个方法内,要先通过mainActivity获得mActivity,再通过这个mActivity去调用mainActivity的getContentFragment方法,再调用到contentFragment中的getNewsCenterPager方法找到具体的newspager,再去调用他的setCurrentMenuDetailPager来完成页面的显示

侧边栏中

public void initData() {// 初始化数据,点击事件,同时点击后填充数据,adaptersuper.initData();lv_left_menu.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view,int position, long id) {// TODO Auto-generated method stubmCurrentPos = position;menulistadapter.notifyDataSetChanged();//点击侧边栏改变新闻页的内容setCurrentMenuDetailPager(position);}});}private void setCurrentMenuDetailPager(int position) {// TODO Auto-generated method stubMainActivity MainUI = (MainActivity) mActivity;MainUI.getContentFragment().getNewsCenterPager().setCurrentMenuDetailPager(position);}

主页中

// 获取主页面fragmentpublic 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 stubsuper(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 stubsuper(mActivity);tabdata = children;}@Overridepublic 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() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubint currentItem = vp_menu_newsdetail.getCurrentItem();vp_menu_newsdetail.setCurrentItem(++currentItem, false);}});  return view;}@Overridepublic void initData() {// TODO Auto-generated method stubsuper.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{@Overridepublic int getCount() {// TODO Auto-generated method stubreturn tabList.size();}@Overridepublic boolean isViewFromObject(View arg0, Object arg1) {// TODO Auto-generated method stubreturn arg0==arg1;}@Overridepublic Object instantiateItem(ViewGroup container, int position) {TabDetailPager tabDetailPager = tabList.get(position);container.addView(tabDetailPager.mRootView);tabDetailPager.initData();return tabList.get(position).mRootView;}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {// TODO Auto-generated method stub    container.removeView(tabList.get(position).mRootView);}@Overridepublic 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() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubint 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}@Overridepublic 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 0
原创粉丝点击