1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.dialer.speeddial; 18 19 import android.content.Context; 20 import android.support.annotation.VisibleForTesting; 21 import android.support.v7.widget.GridLayoutManager; 22 import android.support.v7.widget.GridLayoutManager.SpanSizeLookup; 23 import android.support.v7.widget.RecyclerView; 24 import android.support.v7.widget.RecyclerView.LayoutManager; 25 import android.view.LayoutInflater; 26 import android.view.ViewGroup; 27 import com.android.dialer.common.Assert; 28 import com.android.dialer.speeddial.FavoritesViewHolder.FavoriteContactsListener; 29 import com.android.dialer.speeddial.HeaderViewHolder.SpeedDialHeaderListener; 30 import com.android.dialer.speeddial.SpeedDialCursor.RowType; 31 import com.android.dialer.speeddial.SuggestionViewHolder.SuggestedContactsListener; 32 33 /** 34 * RecyclerView adapter for {@link SpeedDialFragment}. 35 * 36 * <p>Displays a list in the following order: 37 * 38 * <ol> 39 * <li>Favorite contacts header (with add button) 40 * <li>Favorite contacts 41 * <li>Suggested contacts header 42 * <li>Suggested contacts 43 * </ol> 44 */ 45 final class SpeedDialAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { 46 47 private final Context context; 48 private final FavoriteContactsListener favoritesListener; 49 private final SuggestedContactsListener suggestedListener; 50 private final SpeedDialHeaderListener headerListener; 51 52 private SpeedDialCursor cursor; 53 54 public SpeedDialAdapter( 55 Context context, 56 FavoriteContactsListener favoritesListener, 57 SuggestedContactsListener suggestedListener, 58 SpeedDialHeaderListener headerListener) { 59 this.context = context; 60 this.favoritesListener = favoritesListener; 61 this.suggestedListener = suggestedListener; 62 this.headerListener = headerListener; 63 } 64 65 @Override 66 public int getItemViewType(int position) { 67 return cursor.getRowType(position); 68 } 69 70 @Override 71 public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 72 LayoutInflater inflater = LayoutInflater.from(context); 73 if (viewType == RowType.STARRED) { 74 return new FavoritesViewHolder( 75 inflater.inflate(R.layout.favorite_item_layout, parent, false), favoritesListener); 76 } else if (viewType == RowType.SUGGESTION) { 77 return new SuggestionViewHolder( 78 inflater.inflate(R.layout.suggestion_row_layout, parent, false), suggestedListener); 79 } else if (viewType == RowType.HEADER) { 80 return new HeaderViewHolder( 81 inflater.inflate(R.layout.speed_dial_header_layout, parent, false), headerListener); 82 } else { 83 throw Assert.createIllegalStateFailException("Invalid viewType: " + viewType); 84 } 85 } 86 87 @Override 88 public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 89 cursor.moveToPosition(position); 90 switch (cursor.getRowType(position)) { 91 case RowType.HEADER: 92 ((HeaderViewHolder) holder).setHeaderText(cursor.getHeader()); 93 ((HeaderViewHolder) holder).showAddButton(cursor.hasFavorites() && position == 0); 94 break; 95 case RowType.STARRED: 96 ((FavoritesViewHolder) holder).bind(context, cursor); 97 break; 98 case RowType.SUGGESTION: 99 ((SuggestionViewHolder) holder).bind(context, cursor); 100 break; 101 default: 102 throw Assert.createIllegalStateFailException("Invalid view holder: " + holder); 103 } 104 } 105 106 @Override 107 public int getItemCount() { 108 return cursor == null || cursor.isClosed() ? 0 : cursor.getCount(); 109 } 110 111 public void setCursor(SpeedDialCursor cursor) { 112 this.cursor = cursor; 113 notifyDataSetChanged(); 114 } 115 116 LayoutManager getLayoutManager(Context context) { 117 GridLayoutManager layoutManager = new GridLayoutManager(context, 3 /* spanCount */); 118 layoutManager.setSpanSizeLookup( 119 new SpanSizeLookup() { 120 @Override 121 public int getSpanSize(int position) { 122 return SpeedDialAdapter.this.getSpanSize(position); 123 } 124 }); 125 return layoutManager; 126 } 127 128 @VisibleForTesting 129 int getSpanSize(int position) { 130 switch (cursor.getRowType(position)) { 131 case RowType.SUGGESTION: 132 case RowType.HEADER: 133 return 3; // span the whole screen 134 case RowType.STARRED: 135 return 1; // span 1/3 of the screen 136 default: 137 throw Assert.createIllegalStateFailException( 138 "Invalid row type: " + cursor.getRowType(position)); 139 } 140 } 141 } 142