转自:http://blog.sina.com.cn/s/blog_9f233c070101azf1.html
在Android4.0中,Contacts 拨号界面的分页方式是怎么样的呢?是通过传统的TabHost+tab的方式吗?
不是的,而是通过ActionBar + tab + view Pager的方式实现的。
具体的实现详情,请见下面的详细剖析。
在DialtactsActivity类中,通过向ActionBar中添加Tab的方式实现分页,每页显示的内容,则通过ViewPager对象设置的Adapter对象来设置。
在onCreate()方法中
顺序调用
setupDialer();
setupCallLog();
setupFavorites();
方法加载将三哥tab加载到ActionBar中
下面以setupDialer 为例,逐行描述一下其加载过程
private void setupDialer() {
final Tab tab = getActionBar().newTab();
tab.setContentDescription(R.string.dialerIconLabel);
tab.setTabListener(mTabListener);
tab.setIcon(R.drawable.ic_tab_dialer);
getActionBar().addTab(tab);
}
final Tab tab = getActionBar().newTab();
新建一个Tab页
tab.setContentDescription(R.string.dialerIconLabel);
为该tab也设置描述,基本上没意义,也不显示,只是存储一些临时的数据
tab.setTabListener(mTabListener);
设置监听器,当点击该tab页时触发该事件
tab.setIcon(R.drawable.ic_tab_dialer);
给该tab也添加显示的图标
getActionBar().addTab(tab);
将该tab页添加到ActionBar中
其它几个方法的具体实现也类似。
那么,您想想, Activity 多次调用getActionBar().addTab(tab) 添加tab都是添加到一个ActionBar中了吗? 有此疑问的朋友请点击
那么创建三个tab就可以了吗?
不是的, DialtactsActivity中又对ActionBar进行了下面的处理
getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
getActionBar().setDisplayShowTitleEnabled(false);
getActionBar().setDisplayShowHomeEnabled(false);
第一句将ActionBar设置为“Tab导航”模式
第二句将ActionBar设置为标题不可见
第三句将ActionBar设置为显示主界面按钮不可用
是不是感觉缺了点什么?tab 页内显示的内容呢?
先别急,我们继续往下走
上文提到tab.setTabListener(mTabListener),现在我们来看看这个监听器到底做了什么
private final TabListener mTabListener = new TabListener() {
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
if (mViewPager.getCurrentItem() != tab.getPosition()) {
mViewPager.setCurrentItem(tab.getPosition(), true);
}
….
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
};
看到了吗?
if (mViewPager.getCurrentItem() != tab.getPosition()) {
mViewPager.setCurrentItem(tab.getPosition(), true);
}
将tab和ViewPager联系到一起了。
tab.getPosition()获得当前tab的位置返回int值
mViewPager.getCurrentItem()返回滑动页当前的item编号,返回int值
mViewPager.setCurrentItem(tab.getPosition(), true); 设置viewPager的平滑滚动到tab设置的位置
当tab的位置和ViewPager的当前页不等时,重新设置viewpager的当前页
看样子就是这了,tab页的内容肯定就是通过mViewPager来设置的。
下面我们继续跟进mViewPager
private ViewPager mViewPager;
首先声明mViewPager 为类的私有成员
在onCreate()方法中被初始化
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(new ViewPagerAdapter(getFragmentManager()));
mViewPager.setOnPageChangeListener(mPageChangeListener);
第一句
mViewPager = (ViewPager) findViewById(R.id.pager);
我们来看类的布局文件dialtacts_activity.xml文件
在该文件中有一处
<com.android.contacts.activities.DialtactsViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
原来mViewPager 就是布局中的pager啊
com.android.contacts.activities.DialtactsViewPager
好像不是传统的ViewPager,难道DialtactsViewPager继承了DialtactsViewPager?
答案是正确的
public class DialtactsViewPager extends ViewPager
好,我们接下来继续看看viewPager对象往下都做了些什么
第二句mViewPager.setAdapter(new ViewPagerAdapter(getFragmentManager()));
为ViewPager对象设置了一个Adapter
我们来看看Adapter的具体内容
public class ViewPagerAdapter extends FragmentPagerAdapter {
private DialpadFragment mDialpadFragment;
private CallLogFragment mCallLogFragment;
private PhoneFavoriteFragment mPhoneFavoriteFragment;
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
switch (position) {
case TAB_INDEX_DIALER:
if (mDialpadFragment == null) {
mDialpadFragment = new DialpadFragment();
}
return mDialpadFragment;
…
}
throw new IllegalStateException("No fragment at position " + position);
}
@Override
public int getCount() {
return TAB_INDEX_COUNT;
}
}
哦,我明白了,原来在Adapter里面建立了三种Fragment对象
然后通过当前的选中位置来返回当前页是哪个fragment对象,在fragment对象里面设置页面的具体内容。
既然Adapter设置好了,已经可以滑动了,也就是已经可以实现切换效果了,google接下来还要干什么了呢?
mViewPager.setOnPageChangeListener(mPageChangeListener);
private class PageChangeListener implements OnPageChangeListener {
private int mCurrentPosition = -1;
private int mNextPosition = -1;
@Override
public void onPageScrolled(
int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
final ActionBar actionBar = getActionBar();
if (mCurrentPosition == position) {
Log.w(TAG, "Previous position and next position became same (" + position + ")");
}
actionBar.selectTab(actionBar.getTabAt(position));
mNextPosition = position;
}
public void setCurrentPosition(int position) {
mCurrentPosition = position;
}
@Override
public void onPageScrollStateChanged(int state) {
switch (state) {
case ViewPager.SCROLL_STATE_IDLE: {
if (mCurrentPosition >= 0) {
sendFragmentVisibilityChange(mCurrentPosition, false);
}
if (mNextPosition >= 0) {
sendFragmentVisibilityChange(mNextPosition, true);
}
invalidateOptionsMenu();
mCurrentPosition = mNextPosition;
break;
}
case ViewPager.SCROLL_STATE_DRAGGING:
case ViewPager.SCROLL_STATE_SETTLING:
default:
break;
}
}
}
private Fragment getFragmentAt(int position) {
switch (position) {
case TAB_INDEX_DIALER:
return mDialpadFragment;
case TAB_INDEX_CALL_LOG:
return mCallLogFragment;
case TAB_INDEX_FAVORITES:
return mPhoneFavoriteFragment;
default:
throw new IllegalStateException("Unknown fragment index: " + position);
}
}
private void sendFragmentVisibilityChange(int position, boolean visibility) {
final Fragment fragment = getFragmentAt(position);
if (fragment instanceof ViewPagerVisibilityListener) {
((ViewPagerVisibilityListener) fragment).onVisibilityChanged(visibility);
}
}
通过上面的操作,了解到PageChangeListener 的主要作用是在页面滑动过程中,menu菜单键有可见到不可见的。
最后希望朋友们按照我的思路自己跟一遍代码,这样您将会得到更大的收获,小弟才疏学浅,有肯定地方不到位,希望大家指正!
如果我的一点点总结,对您的有一丁点帮助,那么我将会感到莫大的欣慰!
分享到:
相关推荐
android4.0 Contacts 联系人 android4.0 Contacts 联系人
本篇文章是我近期研究Contacts源码的总结
以前上传的联系人模块忘记把jar包放上去了 实在抱歉 现在添加上去 有需要的可以下载
android4.0 Contacts 通讯录源码
Android 源码分析_Contacts
安卓Android源码——Contacts.rar
整个Contacts模块的应用层源代码,可参考学习使用。
基于Android4.4Contacts源码,不可独立运行
Android应用源码之Contacts.zip项目安卓应用源码下载Android应用源码之Contacts.zip项目安卓应用源码下载 1.适合学生毕业设计研究参考 2.适合个人学习研究参考 3.适合公司开发项目技术参考
Android 系统应用 联系人 Contacts 源码,2013年11月份下载
android Contacts 源码eclipse编译Contacts 联系人 eclipse 源码此为android Contacts 联系人源码在eclipse编译的APK。 可以运行在 android4.4 以及一下的系统中,本人通过大量修改 直接安装运行即可。
android contacts源码,很好的学习参考材料
Android5.0 Contacts联系人源码
android_8.1、android go Contacts 谷歌原生代码。。。
Android Contacts API. Quick Start Initialize Contacts Library public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); Contacts.initialize(this); } ...
Android4.2.2_r1版本Contacts联系人模块源码
android contacts qurey mode
android4.1(JellyBean) 联系人数据存储模块源码 ContactsProvider.rar,git下载后,打包的,去除了git信息,只有源码
android4.1.1原生系统Contacts代码
Android4.1 Contacts源码,学习使用,要想运行需要找Framework jar包和phone等