Merge "Fix contentDescription in dialpad."
diff --git a/res/layout/carousel_about_tab.xml b/res/layout/carousel_about_tab.xml
index bf67ee2..7f70eab 100644
--- a/res/layout/carousel_about_tab.xml
+++ b/res/layout/carousel_about_tab.xml
@@ -16,8 +16,9 @@
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="@dimen/detail_tab_carousel_tab_width"
- android:layout_height="@dimen/detail_tab_carousel_height"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
android:background="@color/detail_tab_background">
<ImageView android:id="@+id/photo"
diff --git a/res/layout/carousel_updates_tab.xml b/res/layout/carousel_updates_tab.xml
index 9da2272..d235280 100644
--- a/res/layout/carousel_updates_tab.xml
+++ b/res/layout/carousel_updates_tab.xml
@@ -16,8 +16,9 @@
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="@dimen/detail_tab_carousel_tab_width"
- android:layout_height="@dimen/detail_tab_carousel_height"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
android:background="@color/detail_tab_background">
<!-- Transparent view to overlay on the contact's photo
diff --git a/res/layout/contact_detail_container_with_updates.xml b/res/layout/contact_detail_container_with_updates.xml
index de7d145..48f1800 100644
--- a/res/layout/contact_detail_container_with_updates.xml
+++ b/res/layout/contact_detail_container_with_updates.xml
@@ -26,8 +26,9 @@
android:layout_width="match_parent"
android:layout_height="match_parent" />
- <com.android.contacts.detail.ContactDetailTabCarousel
+ <include
android:id="@+id/tab_carousel"
+ layout="@layout/contact_detail_tab_carousel"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_width="match_parent"
diff --git a/res/layout/contact_detail_tab_carousel.xml b/res/layout/contact_detail_tab_carousel.xml
index a7321ee..175194c 100644
--- a/res/layout/contact_detail_tab_carousel.xml
+++ b/res/layout/contact_detail_tab_carousel.xml
@@ -14,16 +14,18 @@
limitations under the License.
-->
-<HorizontalScrollView
+<view
xmlns:android="http://schemas.android.com/apk/res/android"
+ class="com.android.contacts.detail.ContactDetailTabCarousel"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:scrollbars="none">
+ android:layout_height="@dimen/detail_tab_carousel_height"
+ android:scrollbars="none"
+ android:fadingEdge="none">
<LinearLayout
android:id="@+id/tab_container"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/detail_tab_carousel_height"
android:orientation="horizontal">
<include
@@ -36,4 +38,4 @@
</LinearLayout>
-</HorizontalScrollView>
\ No newline at end of file
+</view>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index b0624cb..a0c4845 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -91,9 +91,6 @@
<!-- Height of the tab carousel on the contact detail page -->
<dimen name="detail_tab_carousel_height">150dip</dimen>
- <!-- Width of a tab in the tab carousel on the contact detail page -->
- <dimen name="detail_tab_carousel_tab_width">240dip</dimen>
-
<!-- Height of the tab text label in the tab carousel on the contact detail page -->
<dimen name="detail_tab_carousel_tab_label_height">40dip</dimen>
diff --git a/src/com/android/contacts/ContactOptionsActivity.java b/src/com/android/contacts/ContactOptionsActivity.java
index 2c6142a..9ae8fe9 100644
--- a/src/com/android/contacts/ContactOptionsActivity.java
+++ b/src/com/android/contacts/ContactOptionsActivity.java
@@ -16,6 +16,7 @@
package com.android.contacts;
+import android.app.ActionBar;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Intent;
@@ -26,6 +27,7 @@
import android.os.Bundle;
import android.provider.ContactsContract.Contacts;
import android.util.Log;
+import android.view.MenuItem;
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;
@@ -75,6 +77,11 @@
label = (TextView)sendToVoicemailLayout.findViewById(R.id.label);
label.setText(getString(R.string.actionIncomingCall));
+ ActionBar actionBar = getActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ }
+
mSendToVoicemailCheckbox = (CheckBox)sendToVoicemailLayout.findViewById(R.id.checkbox);
}
@@ -208,6 +215,19 @@
ContactsSearchManager.startSearch(this, initialQuery);
}
}
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ finish();
+ return true;
+ default:
+ break;
+ }
+ return super.onOptionsItemSelected(item);
+ }
}
diff --git a/src/com/android/contacts/activities/ContactDetailActivity.java b/src/com/android/contacts/activities/ContactDetailActivity.java
index 9c403b3..b45ba39 100644
--- a/src/com/android/contacts/activities/ContactDetailActivity.java
+++ b/src/com/android/contacts/activities/ContactDetailActivity.java
@@ -33,7 +33,6 @@
import android.accounts.Account;
import android.app.ActionBar;
-import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
@@ -49,12 +48,12 @@
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.Log;
import android.view.KeyEvent;
+import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
-import android.view.View.OnClickListener;
-import android.view.LayoutInflater;
import android.view.View;
+import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
@@ -141,6 +140,11 @@
}
}
+ ActionBar actionBar = getActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ }
+
Log.i(TAG, getIntent().getData().toString());
}
@@ -466,10 +470,10 @@
if (mTabCarousel == null) {
return;
}
- // Only re-position the tab carousel vertically if the FIRST item is still visible on
- // the screen, otherwise the carousel should be in the correct place (pinned at the
- // top).
+ // If the FIRST item is not visible on the screen, then the carousel must be pinned
+ // at the top of the screen.
if (firstVisibleItem != 0) {
+ mTabCarousel.setY(-mTabCarousel.getAllowedVerticalScrollLength());
return;
}
View topView = view.getChildAt(firstVisibleItem);
@@ -477,7 +481,7 @@
return;
}
int amtToScroll = Math.max((int) view.getChildAt(firstVisibleItem).getY(),
- -mTabCarousel.getAllowedVerticalScrollLength());
+ - mTabCarousel.getAllowedVerticalScrollLength());
mTabCarousel.setY(amtToScroll);
}
@@ -498,4 +502,17 @@
*/
public boolean handleKeyDown(int keyCode);
}
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ finish();
+ return true;
+ default:
+ break;
+ }
+ return super.onOptionsItemSelected(item);
+ }
}
diff --git a/src/com/android/contacts/activities/GroupDetailActivity.java b/src/com/android/contacts/activities/GroupDetailActivity.java
index 5d50efc..21900c6 100644
--- a/src/com/android/contacts/activities/GroupDetailActivity.java
+++ b/src/com/android/contacts/activities/GroupDetailActivity.java
@@ -20,9 +20,11 @@
import com.android.contacts.R;
import com.android.contacts.group.GroupDetailFragment;
+import android.app.ActionBar;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
+import android.view.MenuItem;
public class GroupDetailActivity extends ContactsActivity {
@@ -37,12 +39,15 @@
setContentView(R.layout.group_detail_activity);
- getActionBar().setDisplayHomeAsUpEnabled(true);
-
GroupDetailFragment fragment = (GroupDetailFragment) getFragmentManager().findFragmentById(
R.id.group_detail_fragment);
fragment.setListener(mFragmentListener);
fragment.loadGroup(getIntent().getData());
+
+ ActionBar actionBar = getActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ }
}
private final GroupDetailFragment.Listener mFragmentListener =
@@ -66,4 +71,17 @@
startActivity(intent);
}
};
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ finish();
+ return true;
+ default:
+ break;
+ }
+ return super.onOptionsItemSelected(item);
+ }
}
diff --git a/src/com/android/contacts/detail/ContactDetailTabCarousel.java b/src/com/android/contacts/detail/ContactDetailTabCarousel.java
index 2ce26c6..6e1b199 100644
--- a/src/com/android/contacts/detail/ContactDetailTabCarousel.java
+++ b/src/com/android/contacts/detail/ContactDetailTabCarousel.java
@@ -20,8 +20,8 @@
import com.android.contacts.R;
import android.content.Context;
+import android.content.res.Resources;
import android.util.AttributeSet;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
@@ -32,18 +32,27 @@
/**
* This is a horizontally scrolling carousel with 2 tabs: one to see info about the contact and
* one to see updates from the contact.
- * TODO: Create custom views for the tabs so their width can be programatically set as 2/3 of the
- * screen width.
*/
public class ContactDetailTabCarousel extends HorizontalScrollView implements OnTouchListener {
- private static final String TAG = "ContactDetailTabCarousel";
+
+ private static final String TAG = ContactDetailTabCarousel.class.getSimpleName();
+
+ private static final int TAB_INDEX_ABOUT = 0;
+ private static final int TAB_INDEX_UPDATES = 1;
+ private static final int TAB_COUNT = 2;
+
+ private static final double TAB_WIDTH_SCREEN_PERCENTAGE = 0.75;
private ImageView mPhotoView;
private TextView mStatusView;
private Listener mListener;
- private View[] mTabs = new View[2];
+ private final View[] mTabs = new View[TAB_COUNT];
+
+ private int mTabWidth;
+ private int mTabHeight;
+ private int mTabDisplayLabelHeight;
private int mAllowedHorizontalScrollLength = Integer.MIN_VALUE;
private int mAllowedVerticalScrollLength = Integer.MIN_VALUE;
@@ -58,22 +67,78 @@
public void onTabSelected(int position);
}
- public ContactDetailTabCarousel(Context context) {
- this(context, null);
- }
-
public ContactDetailTabCarousel(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public ContactDetailTabCarousel(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- final LayoutInflater inflater =
- (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- inflater.inflate(R.layout.contact_detail_tab_carousel, this);
+ super(context, attrs);
setOnTouchListener(this);
+
+ Resources resources = mContext.getResources();
+ mTabHeight = resources.getDimensionPixelSize(R.dimen.detail_tab_carousel_height);
+ mTabDisplayLabelHeight = resources.getDimensionPixelSize(
+ R.dimen.detail_tab_carousel_tab_label_height);
+ mAllowedVerticalScrollLength = mTabHeight - mTabDisplayLabelHeight;
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ View aboutView = findViewById(R.id.tab_about);
+ View updateView = findViewById(R.id.tab_update);
+
+ TextView aboutTab = (TextView) aboutView.findViewById(R.id.label);
+ aboutTab.setText(mContext.getString(R.string.contactDetailAbout));
+ aboutTab.setClickable(true);
+ aboutTab.setSelected(true);
+
+ TextView updatesTab = (TextView) updateView.findViewById(R.id.label);
+ updatesTab.setText(mContext.getString(R.string.contactDetailUpdates));
+ updatesTab.setClickable(true);
+
+ aboutTab.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mListener.onTabSelected(TAB_INDEX_ABOUT);
+ }
+ });
+ updatesTab.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mListener.onTabSelected(TAB_INDEX_ABOUT);
+ }
+ });
+
+ mTabs[TAB_INDEX_ABOUT] = aboutTab;
+ mTabs[TAB_INDEX_UPDATES] = updatesTab;
+
+ // Retrieve the photo view for the "about" tab
+ mPhotoView = (ImageView) aboutView.findViewById(R.id.photo);
+
+ // Retrieve the social update views for the "updates" tab
+ mStatusView = (TextView) updateView.findViewById(R.id.status);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ measureChildren(widthMeasureSpec);
+ }
+
+ private void measureChildren(int widthMeasureSpec) {
+ int screenWidth = MeasureSpec.getSize(widthMeasureSpec);
+ // Compute the width of a tab as a fraction of the screen width
+ mTabWidth = (int) (TAB_WIDTH_SCREEN_PERCENTAGE * screenWidth);
+
+ // Find the allowed scrolling length by subtracting the current visible screen width
+ // from the total length of the tabs.
+ mAllowedHorizontalScrollLength = mTabWidth * TAB_COUNT - screenWidth;
+
+ // Set the child {@link LinearLayout} to be TAB_COUNT * the computed tab width so that the
+ // {@link LinearLayout}'s children (which are the tabs) will evenly split that width.
+ if (getChildCount() > 0) {
+ View child = getChildAt(0);
+ child.measure(MeasureSpec.makeMeasureSpec(TAB_COUNT * mTabWidth, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(mTabHeight, MeasureSpec.EXACTLY));
+ }
}
@Override
@@ -86,19 +151,6 @@
* Returns the number of pixels that this view can be scrolled horizontally.
*/
public int getAllowedHorizontalScrollLength() {
- // We can't compute this in the constructor because the view widths are 0, so do the
- // calculation only when this getter method is called (all the views should be created
- // by this time).
- if (mAllowedHorizontalScrollLength == Integer.MIN_VALUE) {
- // Find the total length of two tabs side-by-side
- int totalLength = 0;
- for (int i=0; i < mTabs.length; i++) {
- totalLength += mTabs[i].getWidth();
- }
- // Find the allowed scrolling length by subtracting the current visible screen width
- // from the total length of the tabs.
- mAllowedHorizontalScrollLength = totalLength - getWidth();
- }
return mAllowedHorizontalScrollLength;
}
@@ -107,16 +159,6 @@
* the tab labels to still show.
*/
public int getAllowedVerticalScrollLength() {
- if (mAllowedVerticalScrollLength == Integer.MIN_VALUE) {
- // Find the total height of a tab
- View aboutView = findViewById(R.id.tab_about);
- int totalHeight = aboutView.getHeight();
- // Find the height of a tab label
- TextView aboutTab = (TextView) aboutView.findViewById(R.id.label);
- int labelHeight = aboutTab.getHeight();
- // Find the allowed scrolling length by subtracting the two values
- mAllowedVerticalScrollLength = totalHeight - labelHeight;
- }
return mAllowedVerticalScrollLength;
}
@@ -153,40 +195,6 @@
return;
}
- View aboutView = findViewById(R.id.tab_about);
- View updateView = findViewById(R.id.tab_update);
-
- TextView aboutTab = (TextView) aboutView.findViewById(R.id.label);
- aboutTab.setText(mContext.getString(R.string.contactDetailAbout));
- aboutTab.setClickable(true);
- aboutTab.setSelected(true);
-
- TextView updatesTab = (TextView) updateView.findViewById(R.id.label);
- updatesTab.setText(mContext.getString(R.string.contactDetailUpdates));
- updatesTab.setClickable(true);
-
- aboutTab.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mListener.onTabSelected(0);
- }
- });
- updatesTab.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mListener.onTabSelected(1);
- }
- });
-
- mTabs[0] = aboutTab;
- mTabs[1] = updatesTab;
-
- // Retrieve the photo view for the "about" tab
- mPhotoView = (ImageView) aboutView.findViewById(R.id.photo);
-
- // Retrieve the social update view for the "updates" tab
- mStatusView = (TextView) updateView.findViewById(R.id.status);
-
ContactDetailDisplayUtils.setPhoto(mContext, contactData, mPhotoView);
ContactDetailDisplayUtils.setSocialSnippet(mContext, contactData, mStatusView);
}
@@ -203,10 +211,10 @@
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mListener.onTouchDown();
- return true;
+ return false;
case MotionEvent.ACTION_UP:
mListener.onTouchUp();
- return true;
+ return false;
}
return super.onTouchEvent(event);
}
diff --git a/src/com/android/contacts/dialpad/DialpadFragment.java b/src/com/android/contacts/dialpad/DialpadFragment.java
index 347d705..af706b8 100644
--- a/src/com/android/contacts/dialpad/DialpadFragment.java
+++ b/src/com/android/contacts/dialpad/DialpadFragment.java
@@ -24,6 +24,7 @@
import com.android.internal.telephony.ITelephony;
import com.android.phone.CallLogAsync;
import com.android.phone.HapticFeedback;
+import com.google.i18n.phonenumbers.PhoneNumberUtil;
import android.app.Activity;
import android.app.Fragment;
@@ -37,6 +38,7 @@
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -146,7 +148,34 @@
private String mCurrentCountryIso;
- PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+ /**
+ * May be null for a moment and filled by AsyncTask. Must not be touched outside UI thread.
+ */
+ private PhoneNumberFormattingTextWatcher mTextWatcher;
+
+ /**
+ * Delays {@link PhoneNumberFormattingTextWatcher} creation as it may cause disk read operation.
+ */
+ private final AsyncTask<Void, Void, Void> mTextWatcherLoadAsyncTask =
+ new AsyncTask<Void, Void, Void>() {
+
+ private PhoneNumberFormattingTextWatcher mTemporaryWatcher;
+
+ @Override
+ protected Void doInBackground(Void... params) {
+ mTemporaryWatcher = new PhoneNumberFormattingTextWatcher(mCurrentCountryIso);
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
+ // Should be in UI thread.
+ mTextWatcher = mTemporaryWatcher;
+ mDigits.addTextChangedListener(mTextWatcher);
+ }
+ };
+
+ private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
/**
* Listen for phone state changes so that we can take down the
* "dialpad chooser" if the phone becomes idle while the
@@ -228,7 +257,14 @@
mDigits.setOnKeyListener(this);
mDigits.addTextChangedListener(this);
- maybeAddNumberFormatting();
+ if (mTextWatcher == null) {
+ if (mTextWatcherLoadAsyncTask.getStatus() == AsyncTask.Status.PENDING) {
+ // Start loading text watcher for phone number, which requires disk read.
+ mTextWatcherLoadAsyncTask.execute();
+ }
+ } else {
+ mDigits.addTextChangedListener(mTextWatcher);
+ }
// Check for the presence of the keypad
View oneButton = fragmentView.findViewById(R.id.one);
@@ -283,10 +319,6 @@
return mDigits;
}
- private void maybeAddNumberFormatting() {
- mDigits.addTextChangedListener(new PhoneNumberFormattingTextWatcher(mCurrentCountryIso));
- }
-
/**
* Handles the intent that launched us.
*