UI tweaks to ImportDialogFragment
It's now able to show the number of contacts on the SIM card for the
SIM options if the counts are passed as arguments.
Test
manual: verify that ImportDialogFragment UI reflects changes
Bug 31781331
Change-Id: I5b20287ae504470866af2ad83c61794876fdbf7e
diff --git a/res/layout/select_dialog_item.xml b/res/layout/select_dialog_item.xml
index 0c524fd..1215aa9 100644
--- a/res/layout/select_dialog_item.xml
+++ b/res/layout/select_dialog_item.xml
@@ -19,14 +19,35 @@
in the contact editor. This is similar to the framework's select_dialog_item_material.xml layout
except the text appearance is medium and the padding is set to match the material spec.
-->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@android:id/text1"
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="48dp"
- android:textAlignment="viewStart"
- android:textColor="@color/contacts_text_color"
- android:textSize="16sp"
- android:gravity="center_vertical"
- android:paddingStart="24dip"
- android:paddingEnd="24dip"
- android:ellipsize="marquee" />
\ No newline at end of file
+ android:layout_height="56dp"
+ android:orientation="vertical"
+ android:paddingBottom="8dp"
+ android:paddingEnd="24dp"
+ android:paddingStart="24dp"
+ android:paddingTop="8dp">
+
+ <TextView
+ android:id="@+id/primary_text"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:ellipsize="marquee"
+ android:gravity="start|center_vertical"
+ android:textAlignment="viewStart"
+ android:textAppearance="?android:textAppearanceListItem"
+ android:textSize="16sp"/>
+
+ <TextView
+ android:id="@+id/secondary_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ellipsize="marquee"
+ android:gravity="center_vertical|start"
+ android:textAlignment="viewStart"
+ android:textAppearance="?android:textAppearanceListItemSecondary"
+ android:textColor="?android:textColorSecondary"
+ />
+</LinearLayout>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 36315a2..d8f3362 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1370,13 +1370,35 @@
<string name="dialog_new_contact_account">Save imported contacts to:</string>
<!-- Action string for selecting SIM for importing contacts -->
- <string name="import_from_sim">Import from SIM card</string>
+ <string name="import_from_sim">SIM card</string>
<!-- Action string for selecting a SIM subscription for importing contacts -->
- <string name="import_from_sim_summary_fmt">Import from SIM <xliff:g id="sim_name">%1$s</xliff:g></string>
+ <string name="import_from_sim_summary_fmt">SIM <xliff:g id="sim_name">%1$s</xliff:g></string>
+
+ <!-- Secondary string showing the number of SIM contacts for the SIM card on the action for
+ importing from that SIM. Only shown if there is no phone number available for the SIM card
+ [CHAR LIMIT=25] -->
+ <plurals name="import_from_sim_secondary_contact_count_fmt">
+ <item quantity="one">1 contact</item>
+ <item quantity="other">%1$d contacts</item>
+ </plurals>
+
+ <!-- Secondary string showing the number of SIM contacts and phone number for the SIM card
+ on the action for importing that SIM. Note that the bullet character is purely a visual
+ separator between the contact count and phone number; it has no grammatical meaning in
+ this string [CHAR LIMIT=35]-->
+ <plurals name="import_from_sim_secondary_template">
+ <item quantity="one"><xliff:g id="count">^1</xliff:g> contact • <xliff:g id="phone_number">^2</xliff:g></item>
+ <item quantity="other"><xliff:g id="count">^1</xliff:g> contacts • <xliff:g id="phone_number">^2</xliff:g></item>
+ </plurals>
+
+
<!-- Action string for selecting a .vcf file to import contacts from [CHAR LIMIT=30] -->
- <string name="import_from_vcf_file" product="default">Import from .vcf file</string>
+ <string name="import_from_vcf_file" product="default">.vcf file</string>
+
+ <!-- Message shown on Import from dialog when there is nothing available to import (no .vcf option or SIM cards) [CHAR LIMIT=NONE] -->
+ <string name="nothing_to_import_message">Nothing to import</string>
<!-- Dialog message asking the user for confirmation before starting to import contacts from a .vcf file. [CHAR LIMIT=NONE] -->
<string name="import_from_vcf_file_confirmation_message" product="default">Import contacts from vCard?</string>
@@ -1622,7 +1644,7 @@
<string name="dialog_export">Export contacts</string>
<!-- Dialog title when importing contacts from an external source. [CHAR LIMIT=36] -->
- <string name="dialog_import">Import contacts</string>
+ <string name="dialog_import">Import contacts from</string>
<!-- Toast indicating that sharing a contact has failed. [CHAR LIMIT=NONE] -->
<string name="share_error">This contact can\'t be shared.</string>
@@ -1864,4 +1886,5 @@
<!-- Generic label for the SIM card when there is only a single SIM in the device [CHAR LIMIT=10]-->
<string name="single_sim_display_label">SIM</string>
+
</resources>
diff --git a/src/com/android/contacts/common/interactions/ExportDialogFragment.java b/src/com/android/contacts/common/interactions/ExportDialogFragment.java
index 84a43dd..3925833 100644
--- a/src/com/android/contacts/common/interactions/ExportDialogFragment.java
+++ b/src/com/android/contacts/common/interactions/ExportDialogFragment.java
@@ -97,10 +97,14 @@
R.layout.select_dialog_item) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
- final TextView result = (TextView)(convertView != null ? convertView :
- dialogInflater.inflate(R.layout.select_dialog_item, parent, false));
+ final View result = convertView != null ? convertView :
+ dialogInflater.inflate(R.layout.select_dialog_item, parent, false);
- result.setText(getItem(position).mLabel);
+ final TextView text = (TextView) result.findViewById(R.id.primary_text);
+ final View secondaryText = result.findViewById(R.id.secondary_text);
+ secondaryText.setVisibility(View.GONE);
+
+ text.setText(getItem(position).mLabel);
return result;
}
};
diff --git a/src/com/android/contacts/common/interactions/ImportDialogFragment.java b/src/com/android/contacts/common/interactions/ImportDialogFragment.java
index 2268854..f3ce748 100644
--- a/src/com/android/contacts/common/interactions/ImportDialogFragment.java
+++ b/src/com/android/contacts/common/interactions/ImportDialogFragment.java
@@ -25,8 +25,8 @@
import android.content.DialogInterface;
import android.content.res.Resources;
import android.os.Bundle;
-import android.provider.ContactsContract.Contacts;
-import android.telephony.SubscriptionManager;
+import android.support.v4.text.TextUtilsCompat;
+import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.util.Log;
@@ -43,6 +43,7 @@
import com.android.contacts.common.database.SimContactDao;
import com.android.contacts.common.model.AccountTypeManager;
import com.android.contacts.common.model.SimCard;
+import com.android.contacts.common.model.SimContact;
import com.android.contacts.common.model.account.AccountWithDataSet;
import com.android.contacts.common.util.AccountSelectionUtil;
import com.android.contacts.common.util.AccountsListAdapter.AccountListFilter;
@@ -62,28 +63,30 @@
public static final String EXTRA_SIM_ONLY = "extraSimOnly";
+ public static final String EXTRA_SIM_CONTACT_COUNT_PREFIX = "simContactCount_";
+
private boolean mSimOnly = false;
private SimContactDao mSimDao;
- private final String[] LOOKUP_PROJECTION = new String[] {
- Contacts.LOOKUP_KEY
- };
-
- private SubscriptionManager mSubscriptionManager;
-
/** Preferred way to show this dialog */
public static void show(FragmentManager fragmentManager) {
final ImportDialogFragment fragment = new ImportDialogFragment();
fragment.show(fragmentManager, TAG);
}
- /**
- * Create an instance that will only have items for the SIM cards (VCF will not be included).
- */
- public static void showForSimOnly(FragmentManager fragmentManager) {
+ public static void show(FragmentManager fragmentManager, List<SimCard> sims,
+ boolean includeVcf) {
final ImportDialogFragment fragment = new ImportDialogFragment();
- Bundle args = new Bundle();
- args.putBoolean(EXTRA_SIM_ONLY, true);
+ final Bundle args = new Bundle();
+ args.putBoolean(EXTRA_SIM_ONLY, !includeVcf);
+ for (SimCard sim : sims) {
+ final List<SimContact> contacts = sim.getContacts();
+ if (contacts == null) {
+ continue;
+ }
+ args.putInt(EXTRA_SIM_CONTACT_COUNT_PREFIX + sim.getSimId(), contacts.size());
+ }
+
fragment.setArguments(args);
fragment.show(fragmentManager, TAG);
}
@@ -92,6 +95,8 @@
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ setStyle(STYLE_NORMAL, R.style.ContactsAlertDialogThemeAppCompat);
+
final Bundle args = getArguments();
mSimOnly = args != null && args.getBoolean(EXTRA_SIM_ONLY, false);
mSimDao = SimContactDao.create(getContext());
@@ -109,21 +114,62 @@
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
- // Wrap our context to inflate list items using the correct theme
- final LayoutInflater dialogInflater = (LayoutInflater)getActivity()
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ final LayoutInflater dialogInflater = (LayoutInflater)
+ getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// Adapter that shows a list of string resources
final ArrayAdapter<AdapterEntry> adapter = new ArrayAdapter<AdapterEntry>(getActivity(),
R.layout.select_dialog_item) {
+
@Override
public View getView(int position, View convertView, ViewGroup parent) {
- final TextView result = (TextView)(convertView != null ? convertView :
- dialogInflater.inflate(R.layout.select_dialog_item, parent, false));
-
- result.setText(getItem(position).mLabel);
+ final View result = convertView != null ? convertView :
+ dialogInflater.inflate(R.layout.select_dialog_item, parent, false);
+ final TextView primaryText = (TextView) result.findViewById(R.id.primary_text);
+ final TextView secondaryText = (TextView) result.findViewById(R.id.secondary_text);
+ final AdapterEntry entry = getItem(position);
+ secondaryText.setVisibility(View.GONE);
+ if (entry.mChoiceResourceId == R.string.import_from_sim) {
+ final CharSequence secondary = getSimSecondaryText(entry.mSim);
+ if (TextUtils.isEmpty(secondary)) {
+ secondaryText.setVisibility(View.GONE);
+ } else {
+ secondaryText.setText(secondary);
+ secondaryText.setVisibility(View.VISIBLE);
+ }
+ }
+ primaryText.setText(entry.mLabel);
return result;
}
+
+ CharSequence getSimSecondaryText(SimCard sim) {
+ int count = getSimContactCount(sim);
+
+ CharSequence phone = sim.getFormattedPhone();
+ if (phone == null) {
+ phone = sim.getPhone();
+ }
+ if (phone != null) {
+ phone = PhoneNumberUtilsCompat.createTtsSpannable(phone);
+ }
+
+ if (count != -1 && phone != null) {
+ // We use a template instead of format string so that the TTS span is preserved
+ final CharSequence template = getResources()
+ .getQuantityString(R.plurals.import_from_sim_secondary_template, count);
+ return TextUtils.expandTemplate(template, String.valueOf(count), phone);
+ } else if (phone != null) {
+ return phone;
+ } else if (count != -1) {
+ // count != -1
+ return getResources()
+ .getQuantityString(
+ R.plurals.import_from_sim_secondary_contact_count_fmt, count,
+ count);
+ } else {
+ return null;
+ }
+ }
};
addItems(adapter);
@@ -135,10 +181,9 @@
boolean dismissDialog;
final int resId = adapter.getItem(which).mChoiceResourceId;
if (resId == R.string.import_from_sim) {
- dismissDialog = handleSimImportRequest(adapter.getItem(which).mSubscriptionId);
+ dismissDialog = handleSimImportRequest(adapter.getItem(which).mSim);
} else if (resId == R.string.import_from_vcf_file) {
- dismissDialog = handleImportRequest(resId,
- adapter.getItem(which).mSubscriptionId);
+ dismissDialog = handleImportRequest(resId, SimCard.NO_SUBSCRIPTION_ID);
} else {
dismissDialog = true;
Log.e(TAG, "Unexpected resource: "
@@ -149,12 +194,29 @@
}
}
};
- final TextView title = (TextView) View.inflate(getActivity(), R.layout.dialog_title, null);
- title.setText(R.string.dialog_import);
- return new AlertDialog.Builder(getActivity())
- .setCustomTitle(title)
- .setSingleChoiceItems(adapter, -1, clickListener)
- .create();
+
+ final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), getTheme())
+ .setTitle(R.string.dialog_import)
+ .setNegativeButton(android.R.string.cancel, null);
+ if (adapter.isEmpty()) {
+ // Handle edge case; e.g. SIM card was removed.
+ builder.setMessage(R.string.nothing_to_import_message);
+ } else {
+ builder.setSingleChoiceItems(adapter, -1, clickListener);
+ }
+
+ return builder.create();
+ }
+
+ private int getSimContactCount(SimCard sim) {
+ if (sim.getContacts() != null) {
+ return sim.getContacts().size();
+ }
+ final Bundle args = getArguments();
+ if (args == null) {
+ return -1;
+ }
+ return args.getInt(EXTRA_SIM_CONTACT_COUNT_PREFIX + sim.getSimId(), -1);
}
private void addItems(ArrayAdapter<AdapterEntry> adapter) {
@@ -167,17 +229,18 @@
if (sims.size() == 1) {
adapter.add(new AdapterEntry(getString(R.string.import_from_sim),
- R.string.import_from_sim, SimCard.NO_SUBSCRIPTION_ID));
+ R.string.import_from_sim, sims.get(0)));
return;
}
- for (SimCard sim : sims) {
- adapter.add(new AdapterEntry(getSimDescription(sim), R.string.import_from_sim,
- sim.getSubscriptionId()));
+ for (int i = 0; i < sims.size(); i++) {
+ final SimCard sim = sims.get(i);
+ adapter.add(new AdapterEntry(getSimDescription(sim, i), R.string.import_from_sim, sim));
}
}
- private boolean handleSimImportRequest(int subscriptionId) {
- SimImportFragment.newInstance(subscriptionId).show(getFragmentManager(), "SimImport");
+ private boolean handleSimImportRequest(SimCard sim) {
+ SimImportFragment.newInstance(sim.getSubscriptionId()).show(getFragmentManager(),
+ "SimImport");
return true;
}
@@ -235,38 +298,30 @@
dismiss();
}
- private CharSequence getSimDescription(SimCard sim) {
+ private CharSequence getSimDescription(SimCard sim, int index) {
final CharSequence name = sim.getDisplayName();
- CharSequence number = sim.getFormattedPhone();
- // If formatting fails use the raw phone number
- if (number == null) {
- number = sim.getPhone();
- }
- if (number != null) {
- number = PhoneNumberUtilsCompat.createTtsSpannable(number);
- }
- if (TextUtils.isEmpty(number)) {
+ if (name != null) {
return getString(R.string.import_from_sim_summary_fmt, name);
+ } else {
+ return getString(R.string.import_from_sim_summary_fmt, String.valueOf(index));
}
- return new SpannableStringBuilder(getString(R.string.import_from_sim_summary_fmt, name))
- .append('\n').append(number);
}
private static class AdapterEntry {
public final CharSequence mLabel;
public final int mChoiceResourceId;
- public final int mSubscriptionId;
+ public final SimCard mSim;
- public AdapterEntry(CharSequence label, int resId, int subId) {
+ public AdapterEntry(CharSequence label, int resId, SimCard sim) {
mLabel = label;
mChoiceResourceId = resId;
- mSubscriptionId = subId;
+ mSim = sim;
}
public AdapterEntry(String label, int resId) {
// Store a nonsense value for mSubscriptionId. If this constructor is used,
// the mSubscriptionId value should not be read later.
- this(label, resId, /* subId = */ -1);
+ this(label, resId, /* sim= */ null);
}
}
}
diff --git a/src/com/android/contacts/common/model/SimCard.java b/src/com/android/contacts/common/model/SimCard.java
index 3c27cfe..c316ec4 100644
--- a/src/com/android/contacts/common/model/SimCard.java
+++ b/src/com/android/contacts/common/model/SimCard.java
@@ -110,6 +110,10 @@
return PhoneNumberUtils.formatNumber(mPhoneNumber, mCountryCode);
}
+ public boolean hasPhone() {
+ return mPhoneNumber != null;
+ }
+
public String getCountryCode() {
return mCountryCode;
}