/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.contacts.common.widget; import android.annotation.SuppressLint; import android.app.AlertDialog; import android.app.Dialog; import android.app.DialogFragment; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.os.Handler; import android.os.ResultReceiver; import android.support.annotation.Nullable; import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListAdapter; import android.widget.TextView; import com.android.contacts.common.R; import com.android.contacts.common.compat.PhoneAccountCompat; import com.android.contacts.common.compat.PhoneNumberUtilsCompat; import java.util.ArrayList; import java.util.List; /** * Dialog that allows the user to select a phone accounts for a given action. Optionally provides * the choice to set the phone account as default. */ public class SelectPhoneAccountDialogFragment extends DialogFragment { private static final String ARG_TITLE_RES_ID = "title_res_id"; private static final String ARG_CAN_SET_DEFAULT = "can_set_default"; private static final String ARG_ACCOUNT_HANDLES = "account_handles"; private static final String ARG_IS_DEFAULT_CHECKED = "is_default_checked"; private static final String ARG_LISTENER = "listener"; private static final String ARG_CALL_ID = "call_id"; private List mAccountHandles; private boolean mIsSelected; private boolean mIsDefaultChecked; private SelectPhoneAccountListener mListener; public SelectPhoneAccountDialogFragment() {} /** * Create new fragment instance with default title and no option to set as default. * * @param accountHandles The {@code PhoneAccountHandle}s available to select from. * @param listener The listener for the results of the account selection. */ public static SelectPhoneAccountDialogFragment newInstance( List accountHandles, SelectPhoneAccountListener listener, @Nullable String callId) { return newInstance( R.string.select_account_dialog_title, false, accountHandles, listener, callId); } /** * Create new fragment instance. This method also allows specifying a custom title and "set * default" checkbox. * * @param titleResId The resource ID for the string to use in the title of the dialog. * @param canSetDefault {@code true} if the dialog should include an option to set the selection * as the default. False otherwise. * @param accountHandles The {@code PhoneAccountHandle}s available to select from. * @param listener The listener for the results of the account selection. */ public static SelectPhoneAccountDialogFragment newInstance( int titleResId, boolean canSetDefault, List accountHandles, SelectPhoneAccountListener listener, @Nullable String callId) { ArrayList accountHandlesCopy = new ArrayList<>(); if (accountHandles != null) { accountHandlesCopy.addAll(accountHandles); } SelectPhoneAccountDialogFragment fragment = new SelectPhoneAccountDialogFragment(); final Bundle args = new Bundle(); args.putInt(ARG_TITLE_RES_ID, titleResId); args.putBoolean(ARG_CAN_SET_DEFAULT, canSetDefault); args.putParcelableArrayList(ARG_ACCOUNT_HANDLES, accountHandlesCopy); args.putParcelable(ARG_LISTENER, listener); args.putString(ARG_CALL_ID, callId); fragment.setArguments(args); fragment.setListener(listener); return fragment; } public void setListener(SelectPhoneAccountListener listener) { mListener = listener; } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putBoolean(ARG_IS_DEFAULT_CHECKED, mIsDefaultChecked); } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { int titleResId = getArguments().getInt(ARG_TITLE_RES_ID); boolean canSetDefault = getArguments().getBoolean(ARG_CAN_SET_DEFAULT); mAccountHandles = getArguments().getParcelableArrayList(ARG_ACCOUNT_HANDLES); mListener = getArguments().getParcelable(ARG_LISTENER); if (savedInstanceState != null) { mIsDefaultChecked = savedInstanceState.getBoolean(ARG_IS_DEFAULT_CHECKED); } mIsSelected = false; final DialogInterface.OnClickListener selectionListener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { mIsSelected = true; PhoneAccountHandle selectedAccountHandle = mAccountHandles.get(which); Bundle result = new Bundle(); result.putParcelable( SelectPhoneAccountListener.EXTRA_SELECTED_ACCOUNT_HANDLE, selectedAccountHandle); result.putBoolean(SelectPhoneAccountListener.EXTRA_SET_DEFAULT, mIsDefaultChecked); result.putString(SelectPhoneAccountListener.EXTRA_CALL_ID, getCallId()); if (mListener != null) { mListener.onReceiveResult(SelectPhoneAccountListener.RESULT_SELECTED, result); } } }; final CompoundButton.OnCheckedChangeListener checkListener = new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton check, boolean isChecked) { mIsDefaultChecked = isChecked; } }; AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); ListAdapter selectAccountListAdapter = new SelectAccountListAdapter( builder.getContext(), R.layout.select_account_list_item, mAccountHandles); AlertDialog dialog = builder .setTitle(titleResId) .setAdapter(selectAccountListAdapter, selectionListener) .create(); if (canSetDefault) { // Generate custom checkbox view, lint suppressed since no appropriate parent (is dialog) @SuppressLint("InflateParams") LinearLayout checkboxLayout = (LinearLayout) LayoutInflater.from(builder.getContext()) .inflate(R.layout.default_account_checkbox, null); CheckBox cb = (CheckBox) checkboxLayout.findViewById(R.id.default_account_checkbox_view); cb.setOnCheckedChangeListener(checkListener); cb.setChecked(mIsDefaultChecked); dialog.getListView().addFooterView(checkboxLayout); } return dialog; } @Override public void onCancel(DialogInterface dialog) { if (!mIsSelected && mListener != null) { Bundle result = new Bundle(); result.putString(SelectPhoneAccountListener.EXTRA_CALL_ID, getCallId()); mListener.onReceiveResult(SelectPhoneAccountListener.RESULT_DISMISSED, result); } super.onCancel(dialog); } @Nullable private String getCallId() { return getArguments().getString(ARG_CALL_ID); } public static class SelectPhoneAccountListener extends ResultReceiver { static final int RESULT_SELECTED = 1; static final int RESULT_DISMISSED = 2; static final String EXTRA_SELECTED_ACCOUNT_HANDLE = "extra_selected_account_handle"; static final String EXTRA_SET_DEFAULT = "extra_set_default"; static final String EXTRA_CALL_ID = "extra_call_id"; protected SelectPhoneAccountListener() { super(new Handler()); } @Override protected void onReceiveResult(int resultCode, Bundle resultData) { if (resultCode == RESULT_SELECTED) { onPhoneAccountSelected( resultData.getParcelable(EXTRA_SELECTED_ACCOUNT_HANDLE), resultData.getBoolean(EXTRA_SET_DEFAULT), resultData.getString(EXTRA_CALL_ID)); } else if (resultCode == RESULT_DISMISSED) { onDialogDismissed(resultData.getString(EXTRA_CALL_ID)); } } public void onPhoneAccountSelected( PhoneAccountHandle selectedAccountHandle, boolean setDefault, @Nullable String callId) {} public void onDialogDismissed(@Nullable String callId) {} } private static class SelectAccountListAdapter extends ArrayAdapter { private int mResId; SelectAccountListAdapter( Context context, int resource, List accountHandles) { super(context, resource, accountHandles); mResId = resource; } @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); View rowView; final ViewHolder holder; if (convertView == null) { // Cache views for faster scrolling rowView = inflater.inflate(mResId, null); holder = new ViewHolder(); holder.labelTextView = (TextView) rowView.findViewById(R.id.label); holder.numberTextView = (TextView) rowView.findViewById(R.id.number); holder.imageView = (ImageView) rowView.findViewById(R.id.icon); rowView.setTag(holder); } else { rowView = convertView; holder = (ViewHolder) rowView.getTag(); } PhoneAccountHandle accountHandle = getItem(position); PhoneAccount account = getContext().getSystemService(TelecomManager.class).getPhoneAccount(accountHandle); if (account == null) { return rowView; } holder.labelTextView.setText(account.getLabel()); if (account.getAddress() == null || TextUtils.isEmpty(account.getAddress().getSchemeSpecificPart())) { holder.numberTextView.setVisibility(View.GONE); } else { holder.numberTextView.setVisibility(View.VISIBLE); holder.numberTextView.setText( PhoneNumberUtilsCompat.createTtsSpannable( account.getAddress().getSchemeSpecificPart())); } holder.imageView.setImageDrawable( PhoneAccountCompat.createIconDrawable(account, getContext())); return rowView; } private static final class ViewHolder { TextView labelTextView; TextView numberTextView; ImageView imageView; } } }