首先看一下界面效果图,MainActivity就是使用ViewPager实现新闻、精选和设置三个页面的。
以下展开来看一下,首先看一下布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
android:orientation="vertical" >
<com.wesley.todaynews.view.NoScrollViewPager
android:id="@+id/vp_content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<RadioGroup
android:id="@+id/rg_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#a000"
android:gravity="center_vertical"
android:orientation="horizontal" >
<RadioButton
android:id="@+id/rb_news"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:button="@null"
android:drawableTop="@drawable/news_radio_selector"
android:gravity="center"
android:padding="1dp"
android:text="新闻"
android:textColor="@drawable/text_color_selector"
android:textSize="13sp" />
<RadioButton
android:id="@+id/rb_photos"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:button="@null"
android:drawableTop="@drawable/photos_radio_selector"
android:gravity="center"
android:padding="1dp"
android:text="精选"
android:textColor="@drawable/text_color_selector"
android:textSize="13sp" />
<RadioButton
android:id="@+id/rb_settings"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:button="@null"
android:drawablePadding="1dp"
android:drawableTop="@drawable/settings_radio_selector"
android:gravity="center"
android:padding="1dp"
android:text="设置"
android:textColor="@drawable/text_color_selector"
android:textSize="13sp" />
</RadioGroup>
</LinearLayout>
一目了然的布局文件,线性布局里面包含了一个ViewPager和一个RadioGroup(三个RadioButton可以自由切换),这个ViewPager的唯一不同点是进行了一个简单的自定义,实现了禁止主界面的ViewPager的左右滑动切换效果(这样是为了后面新闻界面的ViewPager进行左右滑动切换tab)。
来看一下自定义的ViewPager的主要代码:
// 表示事件是否拦截,返回false表示不拦截,可以让嵌套在内部的ViewPager响应左右划动事件
@Override
public boolean onInterceptTouchEvent(MotionEvent arg0) {
return false;
}
可以看到onInterceptTouchEvent方法里面返回false,这是代表不对事件进行拦截,因为onInterceptTouchEvent是控制事件自Root 到 Child的传递,在这里也就是可以让子view(新闻页面中的ViewPager)接收到滑动事件进行相应的处理。
接下来看一下MainActivity中的代码:
首先是在initView()中找到对应控件的id
private void initView() {
rgGroup = (RadioGroup) findViewById(R.id.rg_group);
vpContent = (ViewPager) findViewById(R.id.vp_content);
}
然后在initData()方法中,进行RadioGroup的处理和ViewPager的数据初始化
rgGroup.check(R.id.rb_news);// 默认勾选首页
// 初始化3个子页面
mPagerList = new ArrayList<BasePager>();
mPagerList.add(new NewsPager(this));
mPagerList.add(new PhotosPager(this));
mPagerList.add(new SettingPager(this));
vpContent.setAdapter(new ContentAdapter());
rgGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId) {
case R.id.rb_news:
vpContent.setCurrentItem(0, false);
break;
case R.id.rb_photos:
vpContent.setCurrentItem(1, false);
break;
case R.id.rb_settings:
vpContent.setCurrentItem(2, false);
break;
default:
break;
}
}
});
这里的BasePager是新闻、精选和设置三个页面的基类,主要的作用是根据不同的子页面(新闻、精选和设置)进行不同的处理,包括返回不同的布局,进行不同数据的处理,这里会在接下来的新闻子页面进行展示,这里略过。同时监听RadioGroup的check事件,根据不同的选择设定ViewPager相应的展示页面。
vpContent.setCurrentItem(0, false);其中第二个参数的false表示切换页面的时候取消动画,默认的ViewPager切换的时候会有一个滑动的动画,这里直接去掉。
接下来就是ViewPager的适配器代码
/**
* 内容ViewPager的适配器
*
* @author zhangbingwei
*
*/
class ContentAdapter extends PagerAdapter {
@Override
public int getCount() {
return mPagerList.size();
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
@Override
public Object instantiateItem(View container, int position) {
BasePager pager = mPagerList.get(position);
((ViewGroup) container).addView(pager.mRootView);
pager.initData();// 初始化数据,预加载下一个页面
return pager.mRootView;
}
@Override
public void destroyItem(View container, int position, Object object) {
((ViewPager) container).removeView((View) object);
}
}
默认的就是实现这四个方法,相信大家都很熟悉了(掌握ViewPager的前提),这里要提一下的就是instantiateItem这个方法,原理就是通过ViewPager当前所在页面的位置获取对应的子页面(新闻、精选和设置三个),然后根据对应的子页面添加视图到ViewPager容器中,并且初始化相应页面的数据,也就是
pager.initData();// 初始化数据,预加载下一个页面
这行代码的作用。其中mRootView是基类中定义的View,他是根据不同的子页面来返回不同的View。例如当我们切换到新闻页面的时候,他会展示新闻列表,切换到精选页面的时候,会展示图片流。这些都是有mRootView进行返回的,这些会在接下来的子页面中进行展示。
到这里MainActivity基本完了,不过我这里还做了一些额外的设置,例如双击返回按钮退出,从其他子页面返回到新闻页面的时候,新闻页面的标签要重定位到头条标签(也就是第一个页签)。看下面的代码:
private long exitTime = 0;
/**
* 重写返回键功能,实现连按两次退出App
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
// 按返回键的时候让新闻页面的页签回到第一个页签位置
NewsPager newsPager = (NewsPager) mPagerList.get(0);
if (newsPager.vpNews.getCurrentItem() == 0) {
exit();
} else {
newsPager.mIndicator.setCurrentItem(0);
}
return false;
}
return super.onKeyDown(keyCode, event);
}
public void exit() {
if (System.currentTimeMillis() - exitTime > 2000) {
Toast.makeText(getApplicationContext(), "再按一次返回退出",
Toast.LENGTH_SHORT).show();
exitTime = System.currentTimeMillis();
} else {
finish();
System.exit(0);
}
}
这里重写了onKeyDown()方法,获取到第一个新闻子页面,然后进行条件判定:如果当前是在新闻页面的第一个标签(也就是头条页签),那么就会执行下面的exit()方法进行两次返回键退出的实现效果;如果当前不是在新闻页面的第一个标签,那么点击返回键的时候就会跳转到新闻页面的第一个标签(头条页签)。
在exit()方法中,获取两次点击返回键的时间,如果小于2s,就会推出,否则,不退出。
以上就是小项目 口袋新闻主界面MainActivity的介绍,有错误的地方欢迎指出来,感谢阅读!