题记
大家清明假期快乐!!!!
下面简单介绍下拨号界面运用ViewPager+Fragment实现的主界面。
ViewPager和Fragment
原生拨号应用界面的ViewPager由mViewPager+mViewPagerTabs组成。
mViewPager:ViewPager,用于与容纳fragment,并使用adapter与数据进行交互。
mViewPagerTabs:这里我认为是为了更好的定义ViewPager的Title使用。(相当于更加灵活的ViewPager的“头部”)。
代码如下:
mViewPager的初始化:
// 初始化ViewPager
mViewPager = (ViewPager) parentView.findViewById(R.id.lists_pager);
mViewPagerAdapter = new ViewPagerAdapter(getChildFragmentManager());
// 设置Adapter,与fragment建立联系
mViewPager.setAdapter(mViewPagerAdapter);
mViewPager.setOffscreenPageLimit(TAB_COUNT_WITH_VOICEMAIL - 1);
mViewPager.setOnPageChangeListener(this);
ViewPagerAdapter代码如下:
public class ViewPagerAdapter extends FragmentPagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public long getItemId(int position) {
return getRtlPosition(position);
}
@Override
public Fragment getItem(int position) {
switch (getRtlPosition(position)) {
case TAB_INDEX_SPEED_DIAL:
mSpeedDialFragment = new SpeedDialFragment();
return mSpeedDialFragment;
case TAB_INDEX_RECENTS:
mRecentsFragment = new CallLogFragment(CallLogQueryHandler.CALL_TYPE_ALL,
MAX_RECENTS_ENTRIES, System.currentTimeMillis() - OLDEST_RECENTS_DATE);
return mRecentsFragment;
case TAB_INDEX_ALL_CONTACTS:
mAllContactsFragment = new AllContactsFragment();
return mAllContactsFragment;
case TAB_INDEX_VOICEMAIL:
mVoicemailFragment = new CallLogFragment(Calls.VOICEMAIL_TYPE);
return mVoicemailFragment;
}
throw new IllegalStateException("No fragment at position " + position);
}
**//初始化Fragment; ViewPager.addNewItem() ->instantiateItem->getItem()**
@Override
public Object instantiateItem(ViewGroup container, int position) {
// On rotation the FragmentManager handles rotation. Therefore getItem() isn't called.
// Copy the fragments that the FragmentManager finds so that we can store them in
// instance variables for later.
final Fragment fragment =
(Fragment) super.instantiateItem(container, position);
if (fragment instanceof SpeedDialFragment) {
mSpeedDialFragment = (SpeedDialFragment) fragment;
} else if (fragment instanceof CallLogFragment && position == TAB_INDEX_RECENTS) {
mRecentsFragment = (CallLogFragment) fragment;
} else if (fragment instanceof AllContactsFragment) {
mAllContactsFragment = (AllContactsFragment) fragment;
} else if (fragment instanceof CallLogFragment && position == TAB_INDEX_VOICEMAIL) {
mVoicemailFragment = (CallLogFragment) fragment;
}
return fragment;
}
@Override
public int getCount() {
return mHasActiveVoicemailProvider ? TAB_COUNT_WITH_VOICEMAIL : TAB_COUNT_DEFAULT;
}
@Override
public CharSequence getPageTitle(int position) {
return mTabTitles[position];
}
}
在每次 ViewPager 需要一个用以显示的 Object 的时候,函数instantiateItem都会被 ViewPager.addNewItem() 调用;函数instantiateItem中判断一下要生成的 Fragment 是否已经生成过了,如果生成过了,就使用旧的,旧的将被 Fragment.attach();如果没有,就调用 getItem() 生成一个新的,新的对象将被 FragmentTransation.add();
上述完成了mViewPager+Fragment的布局。
ViewPagerTabs的使用
ViewPagerTabs代码定义及实现:
//图标
mTabIcons = new int[TAB_COUNT_WITH_VOICEMAIL];
mTabIcons[TAB_INDEX_SPEED_DIAL] = R.drawable.tab_speed_dial;
mTabIcons[TAB_INDEX_RECENTS] = R.drawable.tab_recents;
mTabIcons[TAB_INDEX_ALL_CONTACTS] = R.drawable.tab_contacts;
mTabIcons[TAB_INDEX_VOICEMAIL] = R.drawable.tab_voicemail;
//初始化ViewPageTabs。
mViewPagerTabs = (ViewPagerTabs) parentView.findViewById(R.id.lists_pager_header);
mViewPagerTabs.setTabIcons(mTabIcons);
//mViewPagerTabs与ViewPager进行关联
mViewPagerTabs.setViewPager(mViewPager);
上述代码实现了mViewPagerTabs 和mViewPager关联,那么怎么实现将上方图标设置为mViewPager的Title的呢?下面分析mViewPagerTabs的实现:主要的看函数setViewPager():
public void setViewPager(ViewPager viewPager) {
mPager = viewPager;
//此处实现添加TAB项,并向addTabs函数传入上面的mViewPagerAdapter。
addTabs(mPager.getAdapter());
}
private void addTabs(PagerAdapter adapter) {
mTabStrip.removeAllViews();
final int count = adapter.getCount();
for (int i = 0; i < count; i++) {
//设置Tab项
addTab(adapter.getPageTitle(i), i);
}
}
下述代码就是详细的设置mViewPager的Tab页,并设置Tab页的监听事件。
private void addTab(CharSequence tabTitle, final int position) {
View tabView;
if (mTabIcons != null && position < mTabIcons.length) {
View iconView = new View(getContext());
iconView.setBackgroundResource(mTabIcons[position]);
iconView.setContentDescription(tabTitle);
tabView = iconView;
} else {
final TextView textView = new TextView(getContext());
textView.setText(tabTitle);
textView.setBackgroundResource(R.drawable.view_pager_tab_background);
// Assign various text appearance related attributes to child views.
if (mTextStyle > 0) {
textView.setTypeface(textView.getTypeface(), mTextStyle);
}
if (mTextSize > 0) {
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize);
}
if (mTextColor != null) {
textView.setTextColor(mTextColor);
}
textView.setAllCaps(mTextAllCaps);
textView.setGravity(Gravity.CENTER);
tabView = textView;
}
tabView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mPager.setCurrentItem(getRtlPosition(position));
}
});
tabView.setOnLongClickListener(new OnTabLongClickListener(position));
tabView.setPadding(mSidePadding, 0, mSidePadding, 0);
mTabStrip.addView(tabView, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.MATCH_PARENT, 1));
// Default to the first child being selected
if (position == 0) {
mPrevSelected = 0;
tabView.setSelected(true);
}
}
至此也将mViewPagerTabs和mViewPager进行完美结合;mViewPagerTabs的作用就是讲Tab的设置独立出来,方便进行定制和复用。
后记
后续会进行通话记录页面的详细分析,也就是CallLogFragment的详细布局及数据实现。
Keep Moving!!!