DialtactsActivity.java
protected void onCreate(Bundle icicle) { this.setTheme(R.style.DialtactsTheme); super.onCreate(icicle); final Intent intent = getIntent(); fixIntent(intent); //解析布局文件 DialpadGlobals globals = DialpadGlobals.getGlobals(this); try { //得到mDialpadActivityView ---dialtacts_activity.xml View view = globals.getDialpadActivityView(); if(view != null){ Log.d(TAG, "get view from application"); setContentView(view); }else{ tryToSetContentView(); } } catch (Exception e) { tryToSetContentView(); } mContactListFilterController = globals.getContactListFilterController(); mContactListFilterController.addListener(mContactListFilterListener); View viewDialtacts = findViewById(R.id.dialtacts_frame); if (viewDialtacts != null && mFirstLayoutListener != null) { viewDialtacts.addOnLayoutChangeListener(mFirstLayoutListener); } //设置滚动页ViewPages mViewPager = (ViewPager) findViewById(R.id.pager); if (mViewPager != null) { mViewPager.setAdapter(new ViewPagerAdapter(getFragmentManager())); if (mPageChangeListener != null) { mViewPager.setOnPageChangeListener(mPageChangeListener); } mViewPager.setOffscreenPageLimit(2); } //设置滚动页的tab标签属性 int tabHeight = (int) getResources().getDimensionPixelSize(R.dimen.universe_ui_tab_height); Log.d(TAG,"tabHeight="+tabHeight); getActionBar().setAlternativeTabStyle(true); getActionBar().setTabHeight(tabHeight); getActionBar().setLogo(R.mipmap.ic_launcher_contacts); // Do same width calculation as ActionBar does DisplayMetrics dm = getResources().getDisplayMetrics(); int minCellSize = getResources().getDimensionPixelSize(R.dimen.fake_menu_button_min_width); int cellCount = dm.widthPixels / minCellSize; int fakeMenuItemWidth = dm.widthPixels / cellCount; if (DEBUG) Log.d(TAG, "The size of fake menu buttons (in pixel): " + fakeMenuItemWidth); //设置按钮mMenuButton mMenuButton = findViewById(R.id.overflow_menu); if (mMenuButton != null) { mMenuButton.setMinimumWidth(fakeMenuItemWidth); if (ViewConfiguration.get(this).hasPermanentMenuKey()) { // This is required for dialpad button's layout, so must not use GONE here. mMenuButton.setVisibility(View.INVISIBLE); } else { mMenuButton.setOnClickListener(this); } } //设置按钮mSearchButton mSearchButton = findViewById(R.id.searchButton); if (mSearchButton != null) { mSearchButton.setMinimumWidth(fakeMenuItemWidth); mSearchButton.setOnClickListener(this); } //添加Dialer、CallLog、Contacts、Favorites标签 setupDialer(); setupCallLog(); if(UniverseUtils.UNIVERSEUI_SUPPORT){ setupAllContacts(); } setupFavorites(); getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); getActionBar().setDisplayShowTitleEnabled(false); getActionBar().setDisplayShowHomeEnabled(false); // Load the last manually loaded tab mPrefs = PreferenceManager.getDefaultSharedPreferences(this); setCurrentTab(intent); if (UI.FILTER_CONTACTS_ACTION.equals(intent.getAction()) && icicle == null) { setupFilterText(intent); } if(UniverseUtils.UNIVERSEUI_SUPPORT){ mViewPager.setVisibility(View.VISIBLE); } }
在DialtactsActivity的onCreate函数中通过DialpadGlobals加载布局文件,以单例模式获取DialpadGlobals实例对象:
DialpadGlobals.java
public static DialpadGlobals getGlobals(Context context) { if (INSTANCE == null) { INSTANCE = new DialpadGlobals(context); } return INSTANCE; }
DialpadGlobals对象的构造过程:
private DialpadGlobals(Context context) { mContext = context; mInflater = LayoutInflater.from(context); Log.d(TAG, "The Optimization do not support UUI."); initGlobalsTouchLocal(); initGlobalsNotTouchLocal(); try { Class.forName("com.android.contacts.activities.DialtactsActivity"); Class.forName("com.android.contacts.dialpad.DialpadFragment"); Class.forName("com.android.contacts.calllog.CallLogFragment"); } catch (ClassNotFoundException e) { e.printStackTrace(); } IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_LOCALE_CHANGED); mContext.registerReceiver(mBroadcast, filter); }
函数首先加载各个布局文件,然后加载相应的类。
private void initGlobalsTouchLocal() { Resources resource = mContext.getResources(); mDialpadActivityView = mInflater.inflate(R.layout.dialtacts_activity, null); mDialpadFragmentView = mInflater.inflate(R.layout.dialpad_list_fragment, null); mCaLLLogFragmentView = mInflater.inflate(R.layout.call_log_fragment, null); // pre load DialpadFragment mCurrentCountryIso = ContactsUtils.getCurrentCountryIso(mContext); mProhibitedPhoneNumberRegexp = resource.getString(R.string.config_prohibited_phone_number_regexp); }
这样电话拨号界面就保存在DialpadGlobals类的成员mDialpadActivityView中,通过View view = globals.getDialpadActivityView()就可以得到拨号视图了。
dialtacts_activity.xml布局
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingTop="?android:attr/actionBarSize" android:id="@+id/dialtacts_frame"> <android.support.v4.view.ViewPager android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent" /> <ImageButton android:id="@+id/searchButton" android:layout_width="wrap_content" android:layout_height="?android:attr/actionBarSize" android:layout_gravity="bottom|left" android:state_enabled="false" android:background="?android:attr/selectableItemBackground" android:contentDescription="@string/description_search_button" android:src="@drawable/ic_dial_action_search"/> <ImageButton android:id="@+id/overflow_menu" android:layout_width="wrap_content" android:layout_height="?android:attr/actionBarSize" android:layout_gravity="bottom|right" android:src="@drawable/ic_menu_overflow" android:contentDescription="@string/action_menu_overflow_description" android:nextFocusLeft="@id/digits" android:background="?android:attr/selectableItemBackground"/> </FrameLayout>
//设置滚动页ViewPages mViewPager = (ViewPager) findViewById(R.id.pager); if (mViewPager != null) { mViewPager.setAdapter(new ViewPagerAdapter(getFragmentManager())); if (mPageChangeListener != null) { mViewPager.setOnPageChangeListener(mPageChangeListener); } mViewPager.setOffscreenPageLimit(2); }
滑动适配器
public class ViewPagerAdapter extends FragmentPagerAdapter { public ViewPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { switch (position) { //拨号界面 case TAB_INDEX_DIALER_NEWUI: return new DialpadFragment(); //联系人界面 case TAB_INDEX_CONTACTS_NEWUI: mAllFragment = new DefaultContactBrowseListFragment(); mAllFragment.mIsDisplayInDialer = true; return mAllFragment; //通话记录界面 case TAB_INDEX_CALL_LOG_NEWUI: return new CallLogFragment(); //收藏界面 case TAB_INDEX_FAVORITES_NEWUI: return new PhoneFavoriteFragment(); default: throw new IllegalStateException("No fragment at position " + position); } } @Override public void setPrimaryItem(ViewGroup container, int position, Object object) { if (DEBUG) { Log.d(TAG, "FragmentPagerAdapter#setPrimaryItem(), position: " + position); } super.setPrimaryItem(container, position, object); } @Override public int getCount() { if(UniverseUtils.UNIVERSEUI_SUPPORT){ return TAB_INDEX_COUNT_NEWUI; } else { return TAB_INDEX_COUNT; } } }
各个视图类之间的关系图:
setupDialer(); setupCallLog(); setupAllContacts(); setupFavorites();
private void setupDialer() { final Tab tab = getActionBar().newTab(); LayoutInflater inflater = getLayoutInflater(); View view = inflater.inflate(R.layout.dialtacts_tab_new_ui, null); ImageView dialView = (ImageView)view.findViewById(R.id.tab_icon); if(dialView != null){ dialView.setImageResource(R.drawable.ic_tab_dialer_newui); } TextView dialText = (TextView) view.findViewById(R.id.tab_text); if(dialText!=null){ dialText.setText(R.string.dialerIconLabel); } tab.setCustomView(view); tab.setTabListener(mTabListener); getActionBar().addTab(tab); }
private void setupCallLog() { final Tab tab = getActionBar().newTab(); LayoutInflater inflater = getLayoutInflater(); View view = inflater.inflate(R.layout.dialtacts_tab_new_ui, null); ImageView dialView = (ImageView)view.findViewById(R.id.tab_icon); if(dialView != null){ dialView.setImageResource(R.drawable.ic_tab_recent_newui); } TextView dialText = (TextView) view.findViewById(R.id.tab_text); if(dialText!=null){ dialText.setText(R.string.recentCallsIconLabel); } tab.setCustomView(view); tab.setTabListener(mTabListener); getActionBar().addTab(tab); }
private void setupFavorites() { final Tab tab = getActionBar().newTab(); LayoutInflater inflater = getLayoutInflater(); View view = inflater.inflate(R.layout.dialtacts_tab_new_ui, null); ImageView dialView = (ImageView)view.findViewById(R.id.tab_icon); if(dialView != null){ dialView.setImageResource(R.drawable.ic_tab_starred_newui); } TextView dialText = (TextView) view.findViewById(R.id.tab_text); if(dialText!=null){ dialText.setText(R.string.contactsFavoritesLabel); } tab.setCustomView(view); tab.setTabListener(mTabListener); getActionBar().addTab(tab); }
private void setupAllContacts() { final Tab tab = getActionBar().newTab(); LayoutInflater inflater = getLayoutInflater(); View view = inflater.inflate(R.layout.dialtacts_tab_new_ui, null); ImageView dialView = (ImageView)view.findViewById(R.id.tab_icon); if(dialView != null){ dialView.setImageResource(R.drawable.ic_tab_all_newui); } TextView dialText = (TextView) view.findViewById(R.id.tab_text); if(dialText!=null){ dialText.setText(R.string.people); } tab.setCustomView(view); tab.setTabListener(mTabListener); getActionBar().addTab(tab); }
拨号视图加载过程:
DialpadFragment.java
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) { //调用父类DialMatchFragment的onCreateView View fragmentView = super.onCreateView(inflater ,container ,savedState); // Load up the resources for the text field. Resources r = getResources(); mAdditionalButtonsRow = fragmentView.findViewById(R.id.dialpadAdditionalButtons); mDialpad = fragmentView.findViewById(R.id.dialpad_container); // This is null in landscape mode. mDigitsContainer = fragmentView.findViewById(R.id.digits_container); mDigits = (EditText) fragmentView.findViewById(R.id.digits); if(mDigits != null){ mDigits.setSingleLine(); mDigits.setKeyListener(DialerKeyListener.getInstance()); mDigits.setOnClickListener(this); mDigits.setOnKeyListener(this); mDigits.setOnLongClickListener(this); mDigits.addTextChangedListener(this); } ... return fragmentView; }
父类DialMatchFragment的onCreateView函数实现
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mView = inflateView(inflater, container); mListView = (ListView) mView.findViewById(android.R.id.list); if (mListView == null) { throw new RuntimeException( "Your content must have a ListView whose id attribute is android.R.id.list'"); } View emptyView = mView.findViewById(com.android.internal.R.id.empty); if (emptyView != null) { mListView.setEmptyView(emptyView); if (emptyView instanceof ContactListEmptyView) { mEmptyView = (ContactListEmptyView) emptyView; } } ... return mView; }
调用该类的inflateView函数来加载布局,该函数在DialMatchFragment的子类中实现
DialpadFragment.java
protected View inflateView(LayoutInflater inflater, ViewGroup container) { DialpadGlobals globals = DialpadGlobals.getGlobals(getActivity()); View view = globals.getDialpadFragmentView(); if (view != null) { Log.d(TAG, "get view from application"); return view; } else { return inflater.inflate(R.layout.dialpad_list_fragment, null); } }
DialpadFragment布局dialpad_list_fragment_ui.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/top" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="@android:color/transparent" android:layout_alignParentTop="true" android:paddingLeft="@dimen/dialpad_horizontal_margin" android:paddingRight="@dimen/dialpad_horizontal_margin" > <FrameLayout android:id="@+id/showdial" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_alignParentTop="true" android:background="@android:color/transparent" android:layout_marginBottom="59dip"> <include android:id="@+id/account_filter_header_container" layout="@layout/account_filter_header" /> <include layout="@layout/dialpad_add_contacts_newui"/> <View android:id="@+id/dialpad_background" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="visible" android:background="@drawable/dialpad_list_bg_sprd"/> <ListView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginRight="?attr/contact_browser_list_padding_right" android:layout_weight="1" android:fadingEdge="none" android:divider="@null" android:paddingLeft="?attr/contact_browser_list_padding_left" android:paddingTop="?attr/contact_browser_list_padding_left" android:background="@drawable/dialpad_list_bg_sprd" android:fastScrollEnabled="true" /> <ViewStub android:id="@+id/footer_stub" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout="@layout/footer_panel" /> <LinearLayout android:id="@+id/maindial" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="95dip" android:layout_alignParentBottom="true" android:background="@android:color/transparent" android:orientation="vertical" > <View android:layout_width="match_parent" android:layout_height="1dip" android:background="@android:color/transparent" /> <!-- 按键部分 --> <include layout="@layout/dialpad_new_ui" /> <!-- 拨号按钮 --> <include layout="@layout/dialpad_additional_buttons_dial_new_ui" /> </LinearLayout> </FrameLayout> <ListView android:id="@+id/dialpadChooser" android:layout_width="match_parent" android:background="@drawable/dialpad_list_bg_sprd" android:layout_height="1dip" android:layout_weight="1" /> </LinearLayout>
account_filter_header.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/account_filter_header_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:paddingTop="@dimen/list_header_extra_top_padding" android:layout_marginLeft="@dimen/contact_browser_list_header_left_margin" android:layout_marginRight="@dimen/contact_browser_list_header_right_margin" android:background="?android:attr/selectableItemBackground" android:visibility="gone"> <TextView android:id="@+id/account_filter_header" style="@style/ContactListSeparatorTextViewStyle" android:paddingLeft="@dimen/contact_browser_list_item_text_indent" /> </LinearLayout>
dialpad_add_contacts_newui.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/dialpadAddContactsButton" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center_horizontal" android:background="@drawable/dialpad_list_bg_sprd" android:orientation="horizontal" > <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/addContactLayout" android:clickable="true" android:background="@drawable/call_add_contact_button_pressed_new_ui" android:layout_gravity="center" android:gravity="center"> <TextView android:layout_gravity="center" android:gravity="center" android:clickable="false" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableLeft="@drawable/call_addcontract_icon_sprd" android:text="@string/create_new_contact" android:textSize="20sp" /> </RelativeLayout> </RelativeLayout>
dialpad.xml 拨号盘
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/dialpad_container" android:layout_width="match_parent" android:layout_height="295dip" android:background="@android:color/transparent" android:orientation="vertical" > <View android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_alignParentTop="true" android:layout_marginBottom="465dip" android:background="@android:color/transparent" android:clickable="false" android:focusable="false" /> <SlidingDrawer android:id="@+id/dialer_container" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentBottom="true" android:layout_gravity="center_horizontal" android:background="@android:color/transparent" android:content="@+id/dialpad" android:handle="@+id/handle" > <View android:id="@id/handle" android:layout_width="fill_parent" android:layout_height="0px" android:background="@android:color/transparent" android:clickable="false" android:focusable="false" /> <LinearLayout android:id="@id/dialpad" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/call_number_bg_sprd" android:orientation="vertical" > <LinearLayout android:id="@+id/digits_bkg" android:layout_width="match_parent" android:layout_height="72dip" android:background="@android:color/transparent" android:gravity="center" > <LinearLayout android:id="@+id/digits_container" android:layout_width="match_parent" android:layout_height="72dip" android:background="@android:color/transparent" android:layout_weight="@integer/dialpad_layout_weight_digits" android:gravity="center" > <com.android.contacts.dialpad.DigitsEditText android:id="@+id/digits" android:layout_width="0px" android:layout_height="72dip" android:layout_marginLeft="10dip" android:layout_weight="1" android:layout_marginTop="10dip" android:background="@android:color/transparent" android:gravity="center" android:maxLength="@integer/dialpad_max_number_length" android:nextFocusRight="@+id/overflow_menu" android:textAppearance="@style/DialtactsDigitsTextAppearance_new_ui" android:textColor="@android:color/black" /> <ImageButton android:id="@+id/deleteButton" android:layout_width="50dip" android:layout_height="72dip" android:layout_marginLeft="5dip" android:layout_marginTop="3dip" android:layout_marginBottom="-7dip" android:layout_marginRight="10dip" android:background="@android:color/transparent" android:focusable="false" android:src="@drawable/delete_button_pressed_new_ui"/> <ImageButton android:id="@+id/overflow_menu" android:layout_width="54dip" android:layout_height="match_parent" android:layout_alignParentRight="true" android:background="?android:attr/selectableItemBackground" android:contentDescription="@*android:string/action_menu_overflow_description" android:nextFocusLeft="@id/digits" android:src="@drawable/ic_menu_overflow" /> </LinearLayout> </LinearLayout> <TableLayout android:layout_width="match_parent" android:layout_height="223dip" android:layout_gravity="center_horizontal" android:layout_marginTop="@dimen/dialpad_vertical_margin" android:background="@android:color/transparent" android:layout_marginRight="4dip" android:layout_marginLeft="4dip" > <TableRow android:layout_height="54dip" android:layout_marginBottom="2dip" android:layout_weight="1" > <ImageButton android:id="@+id/one" style="@style/DialtactsDialpadButtonStyleNewUI" android:contentDescription="@string/description_image_button_one" android:background="@drawable/dial_num_pressed_new_ui" android:layout_marginRight="2dip" android:src="@drawable/dial_num_1_wht" /> <ImageButton android:id="@+id/two" style="@style/DialtactsDialpadButtonStyleNewUI" android:contentDescription="@string/description_image_button_two" android:background="@drawable/dial_num_pressed_new_ui" android:layout_marginRight="2dip" android:src="@drawable/dial_num_2_wht" /> <ImageButton android:id="@+id/three" style="@style/DialtactsDialpadButtonStyleNewUI" android:contentDescription="@string/description_image_button_three" android:background="@drawable/dial_num_pressed_new_ui" android:src="@drawable/dial_num_3_wht" /> </TableRow> <TableRow android:layout_height="54dip" android:layout_marginBottom="2dip" android:layout_weight="1" > <ImageButton android:id="@+id/four" style="@style/DialtactsDialpadButtonStyleNewUI" android:contentDescription="@string/description_image_button_four" android:background="@drawable/dial_num_pressed_new_ui" android:layout_marginRight="2dip" android:src="@drawable/dial_num_4_wht" /> <ImageButton android:id="@+id/five" style="@style/DialtactsDialpadButtonStyleNewUI" android:background="@drawable/dial_num_pressed_new_ui" android:contentDescription="@string/description_image_button_five" android:layout_marginRight="2dip" android:src="@drawable/dial_num_5_wht" /> <ImageButton android:id="@+id/six" style="@style/DialtactsDialpadButtonStyleNewUI" android:paddingLeft="4dip" android:contentDescription="@string/description_image_button_six" android:background="@drawable/dial_num_pressed_new_ui" android:src="@drawable/dial_num_6_wht" /> </TableRow> <TableRow android:layout_height="54dip" android:layout_marginBottom="2dip" android:layout_weight="1" > <ImageButton android:id="@+id/seven" style="@style/DialtactsDialpadButtonStyleNewUI" android:background="@drawable/dial_num_pressed_new_ui" android:contentDescription="@string/description_image_button_seven" android:layout_marginRight="2dip" android:src="@drawable/dial_num_7_wht" /> <ImageButton android:id="@+id/eight" style="@style/DialtactsDialpadButtonStyleNewUI" android:background="@drawable/dial_num_pressed_new_ui" android:contentDescription="@string/description_image_button_eight" android:layout_marginRight="2dip" android:src="@drawable/dial_num_8_wht" /> <ImageButton android:id="@+id/nine" style="@style/DialtactsDialpadButtonStyleNewUI" android:background="@drawable/dial_num_pressed_new_ui" android:contentDescription="@string/description_image_button_nine" android:src="@drawable/dial_num_9_wht" /> </TableRow> <TableRow android:layout_height="54dip" android:layout_marginBottom="1dip" android:layout_weight="1" > <ImageButton android:id="@+id/star" style="@style/DialtactsDialpadButtonStyleNewUI" android:background="@drawable/dial_num_pressed_new_ui" android:contentDescription="@string/description_image_button_star" android:layout_marginRight="2dip" android:src="@drawable/dial_num_star_wht" /> <ImageButton android:id="@+id/zero" style="@style/DialtactsDialpadButtonStyleNewUI" android:background="@drawable/dial_num_pressed_new_ui" android:contentDescription="@string/description_image_button_zero" android:layout_marginRight="2dip" android:src="@drawable/dial_num_0_wht"/> <ImageButton android:id="@+id/pound" style="@style/DialtactsDialpadButtonStyleNewUI" android:background="@drawable/dial_num_pressed_new_ui" android:contentDescription="@string/description_image_button_pound" android:src="@drawable/dial_num_pound_wht" /> </TableRow> </TableLayout> </LinearLayout> </SlidingDrawer> </RelativeLayout>
dialpad_additional_buttons_dial.xml