diff options
8 files changed, 264 insertions, 12 deletions
diff --git a/res/layout/phone_number_favorite_list_item.xml b/res/layout/phone_number_favorite_list_item.xml new file mode 100644 index 00000000..94cb81ee --- /dev/null +++ b/res/layout/phone_number_favorite_list_item.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2019 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. +--> +<androidx.constraintlayout.widget.ConstraintLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingStart="?android:listPreferredItemPaddingStart" + android:paddingEnd="?android:listPreferredItemPaddingEnd" + android:paddingTop="@dimen/phone_number_favorite_list_item_vertical_padding" + android:paddingBottom="@dimen/phone_number_favorite_list_item_vertical_padding"> + + <TextView + android:id="@+id/phone_number" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_toEndOf="@id/phone_number_checkbox" + android:textAppearance="?android:attr/textAppearanceMedium" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toTopOf="@id/phone_number_description" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintVertical_chainStyle="packed"/> + <TextView + android:id="@+id/phone_number_description" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@id/phone_number" + android:layout_toEndOf="@id/phone_number_checkbox" + android:textAppearance="?android:attr/textAppearanceSmall" + app:layout_constraintTop_toBottomOf="@id/phone_number" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent"/> + <ImageView + android:id="@+id/phone_number_checkbox" + android:src="@drawable/ic_favorite_activatable" + android:layout_width="@dimen/primary_icon_size" + android:layout_height="@dimen/primary_icon_size" + android:tint="@color/primary_icon_color" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent"/> + +</androidx.constraintlayout.widget.ConstraintLayout> diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 2a9f5c42..20a8ed40 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -139,6 +139,7 @@ <dimen name="contact_avatar_corner_radius_percent" format="float">0.5</dimen> <dimen name="touch_target_width">156dp</dimen> <dimen name="phone_number_radio_list_padding">@*android:dimen/car_padding_2</dimen> + <dimen name="phone_number_favorite_list_item_vertical_padding">@*android:dimen/car_padding_2</dimen> <!-- Toolbar --> <!-- Half of the difference between car_margin and touch_target_size--> diff --git a/res/values/strings.xml b/res/values/strings.xml index bc7996ab..4b48392e 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -69,6 +69,10 @@ <string name="add_favorite_button">Add a favorite</string> <!-- Error message shown when on the favorites page without any favorites added [CHAR_LIMIT=80] --> <string name="favorites_empty">You haven\'t added any favorites yet</string> + <!-- Button to cancel the dialog where you pick a phone number to add as a favorite [CHAR_LIMIT=30] --> + <string name="cancel_add_favorites_dialog">@android:string/cancel</string> + <!-- Button to confirm the dialog where you pick a phone number to add as a favorite [CHAR_LIMIT=30] --> + <string name="confirm_add_favorites_dialog">@android:string/ok</string> <!-- Keypad strings--> <string name="one" translatable="false">1</string> diff --git a/src/com/android/car/dialer/ui/common/FavoritePhoneNumberListAdapter.java b/src/com/android/car/dialer/ui/common/FavoritePhoneNumberListAdapter.java new file mode 100644 index 00000000..aeb609bf --- /dev/null +++ b/src/com/android/car/dialer/ui/common/FavoritePhoneNumberListAdapter.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2019 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.car.dialer.ui.common; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.android.car.dialer.R; +import com.android.car.telephony.common.PhoneNumber; + +import java.util.ArrayList; +import java.util.List; + +/** + * {@link ArrayAdapter} that presents the {@link PhoneNumber} and its type as two line list + * item with stars to indicate selection. + */ +public class FavoritePhoneNumberListAdapter extends ArrayAdapter<PhoneNumber> { + private final Context mContext; + + public FavoritePhoneNumberListAdapter(Context context) { + super(context, R.layout.phone_number_favorite_list_item, + R.id.phone_number, new ArrayList<>()); + mContext = context; + } + + /** Sets the phone numbers to display */ + public void setPhoneNumbers(List<PhoneNumber> phoneNumbers) { + clear(); + addAll(phoneNumbers); + } + + @Override + public View getView(int position, @Nullable View convertView, + @NonNull ViewGroup parent) { + View view = super.getView(position, convertView, parent); + PhoneNumber phoneNumber = getItem(position); + if (phoneNumber == null) { + return view; + } + TextView phoneNumberView = view.findViewById(R.id.phone_number); + phoneNumberView.setText(phoneNumber.getRawNumber()); + TextView phoneNumberDescriptionView = view.findViewById(R.id.phone_number_description); + CharSequence readableLabel = phoneNumber.getReadableLabel(mContext.getResources()); + if (phoneNumber.isPrimary()) { + phoneNumberDescriptionView.setText( + mContext.getString(R.string.primary_number_description, readableLabel)); + } else { + phoneNumberDescriptionView.setText(readableLabel); + } + return view; + } +} diff --git a/src/com/android/car/dialer/ui/favorite/AddFavoriteFragment.java b/src/com/android/car/dialer/ui/favorite/AddFavoriteFragment.java new file mode 100644 index 00000000..5c965bbb --- /dev/null +++ b/src/com/android/car/dialer/ui/favorite/AddFavoriteFragment.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2019 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.car.dialer.ui.favorite; + +import android.app.AlertDialog; +import android.net.Uri; +import android.os.Bundle; +import android.widget.ListView; +import android.widget.Toast; + +import com.android.car.dialer.R; +import com.android.car.dialer.livedata.ContactDetailsLiveData; +import com.android.car.dialer.ui.common.FavoritePhoneNumberListAdapter; +import com.android.car.dialer.ui.search.ContactResultsFragment; +import com.android.car.telephony.common.PhoneNumber; + +import java.util.HashSet; +import java.util.Set; + +/** A fragment that allows the user to search for and select favorite phone numbers */ +public class AddFavoriteFragment extends ContactResultsFragment { + + /** Creates a new instance of AddFavoriteFragment */ + public static AddFavoriteFragment newInstance() { + return new AddFavoriteFragment(); + } + + private ContactDetailsLiveData mContactDetails; + private AlertDialog mCurrentDialog; + private FavoritePhoneNumberListAdapter mDialogAdapter; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mDialogAdapter = new FavoritePhoneNumberListAdapter(getContext()); + + Set<PhoneNumber> selectedNumbers = new HashSet<>(); + mCurrentDialog = new AlertDialog.Builder(getContext()) + .setTitle(R.string.select_number_dialog_title) + .setAdapter(mDialogAdapter, + null) + .setNegativeButton(R.string.cancel_add_favorites_dialog, + null) + .setPositiveButton(R.string.confirm_add_favorites_dialog, + (d, which) -> { + String result = "Not yet implemented, but you picked "; + for (PhoneNumber number : selectedNumbers) { + result += number.getNumber() + ", "; + } + Toast.makeText(getContext(), result, Toast.LENGTH_LONG).show(); + getFragmentManager().popBackStackImmediate(); + }) + .create(); + + mCurrentDialog.getListView().setItemsCanFocus(false); + mCurrentDialog.getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); + mCurrentDialog.getListView().setOnItemClickListener((parent, view2, position, id) -> { + PhoneNumber number = mDialogAdapter.getItem(position); + if (view2.isActivated()) { + selectedNumbers.add(number); + } else { + selectedNumbers.remove(number); + } + }); + } + + @Override + public void onShowContactDetail(Uri contactLookupUri) { + if (mContactDetails != null) { + mContactDetails.removeObservers(this); + } + + mContactDetails = new ContactDetailsLiveData(getContext(), contactLookupUri); + mContactDetails.observe(this, (contact) -> { + if (contact == null) { + mCurrentDialog.dismiss(); + return; + } + + mDialogAdapter.setPhoneNumbers(contact.getNumbers()); + mCurrentDialog.show(); + }); + } +} diff --git a/src/com/android/car/dialer/ui/favorite/FavoriteAdapter.java b/src/com/android/car/dialer/ui/favorite/FavoriteAdapter.java index ae051217..16ffd2de 100644 --- a/src/com/android/car/dialer/ui/favorite/FavoriteAdapter.java +++ b/src/com/android/car/dialer/ui/favorite/FavoriteAdapter.java @@ -20,7 +20,6 @@ import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.Toast; import androidx.recyclerview.widget.RecyclerView; @@ -38,8 +37,15 @@ import java.util.List; public class FavoriteAdapter extends RecyclerView.Adapter<FavoriteContactViewHolder> { private static final String TAG = "CD.FavoriteAdapter"; + /** Listener interface for when the add favorite button is clicked */ + public interface OnAddFavoriteClickedListener { + /** Called when the add favorite button is clicked */ + void onAddFavoriteClicked(); + } + private List<Contact> mFavoriteContacts = Collections.emptyList(); private OnItemClickedListener<Contact> mListener; + private OnAddFavoriteClickedListener mAddFavoriteListener; /** Sets the favorite contact list. */ public void setFavoriteContacts(List<Contact> favoriteContacts) { @@ -67,18 +73,19 @@ public class FavoriteAdapter extends RecyclerView.Adapter<FavoriteContactViewHol if (position >= mFavoriteContacts.size()) { viewHolder.onBindAddFavorite(context); - viewHolder.itemView.setOnClickListener((v) -> - Toast.makeText(context, "Not yet implemented", Toast.LENGTH_LONG).show()); + viewHolder.itemView.setOnClickListener((v) -> { + if (mAddFavoriteListener != null) { + mAddFavoriteListener.onAddFavoriteClicked(); + } + }); } else { Contact contact = mFavoriteContacts.get(position); viewHolder.onBind(context, contact); - viewHolder.itemView.setOnClickListener((v) -> onItemViewClicked(contact)); - } - } - - private void onItemViewClicked(Contact contact) { - if (mListener != null) { - mListener.onItemClicked(contact); + viewHolder.itemView.setOnClickListener((v) -> { + if (mListener != null) { + mListener.onItemClicked(contact); + } + }); } } @@ -88,4 +95,12 @@ public class FavoriteAdapter extends RecyclerView.Adapter<FavoriteContactViewHol public void setOnListItemClickedListener(OnItemClickedListener<Contact> listener) { mListener = listener; } + + /** + * Sets a {@link OnAddFavoriteClickedListener listener} which will be called when the + * "Add favorite" button is clicked. + */ + public void setOnAddFavoriteClickedListener(OnAddFavoriteClickedListener listener) { + mAddFavoriteListener = listener; + } } diff --git a/src/com/android/car/dialer/ui/favorite/FavoriteFragment.java b/src/com/android/car/dialer/ui/favorite/FavoriteFragment.java index 7e3573de..61b3ff46 100644 --- a/src/com/android/car/dialer/ui/favorite/FavoriteFragment.java +++ b/src/com/android/car/dialer/ui/favorite/FavoriteFragment.java @@ -20,7 +20,6 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.Toast; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProviders; @@ -60,7 +59,7 @@ public class FavoriteFragment extends DialerBaseFragment { }); emptyPage.findViewById(R.id.add_favorite_button).setOnClickListener(v -> - Toast.makeText(getContext(), "Not yet implemented", Toast.LENGTH_LONG).show()); + pushContentFragment(AddFavoriteFragment.newInstance(), null)); return view; } diff --git a/src/com/android/car/dialer/ui/favorite/FavoriteListFragment.java b/src/com/android/car/dialer/ui/favorite/FavoriteListFragment.java index 41583727..4379fa7e 100644 --- a/src/com/android/car/dialer/ui/favorite/FavoriteListFragment.java +++ b/src/com/android/car/dialer/ui/favorite/FavoriteListFragment.java @@ -50,6 +50,7 @@ public class FavoriteListFragment extends DialerListBaseFragment { getRecyclerView().setItemAnimator(null); FavoriteAdapter adapter = new FavoriteAdapter(); + adapter.setOnAddFavoriteClickedListener(this::onAddFavoriteClicked); FavoriteViewModel favoriteViewModel = ViewModelProviders.of(getActivity()).get( FavoriteViewModel.class); @@ -73,6 +74,10 @@ public class FavoriteListFragment extends DialerListBaseFragment { UiCallManager.get().placeCall(phoneNumber.getRawNumber())); } + private void onAddFavoriteClicked() { + pushContentFragment(AddFavoriteFragment.newInstance(), null); + } + private class ItemSpacingDecoration extends RecyclerView.ItemDecoration { @Override |