DocumentHolder.java revision e3dfebf8464e8608ff790cca67609aff7d8c2820
1/* 2 * Copyright (C) 2015 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 17package com.android.documentsui.dirlist; 18 19import static com.android.internal.util.Preconditions.checkNotNull; 20import static com.android.internal.util.Preconditions.checkState; 21 22import android.content.Context; 23import android.database.Cursor; 24import android.graphics.Rect; 25import android.support.annotation.Nullable; 26import android.support.v7.widget.RecyclerView; 27import android.view.KeyEvent; 28import android.view.LayoutInflater; 29import android.view.MotionEvent; 30import android.view.View; 31import android.view.ViewGroup; 32 33import com.android.documentsui.Events; 34import com.android.documentsui.R; 35import com.android.documentsui.State; 36 37public abstract class DocumentHolder 38 extends RecyclerView.ViewHolder 39 implements View.OnKeyListener { 40 41 public @Nullable String modelId; 42 43 final int mSelectedItemColor; 44 final int mDefaultItemColor; 45 final boolean mAlwaysShowSummary; 46 final Context mContext; 47 48 DocumentHolder.EventListener mEventListener; 49 private View.OnKeyListener mKeyListener; 50 private View mSelectionHotspot; 51 52 public DocumentHolder(Context context, ViewGroup parent, int layout) { 53 this(context, inflateLayout(context, parent, layout)); 54 } 55 56 public DocumentHolder(Context context, View item) { 57 super(item); 58 59 itemView.setOnKeyListener(this); 60 61 mContext = context; 62 63 mDefaultItemColor = context.getColor(R.color.item_doc_background); 64 mSelectedItemColor = context.getColor(R.color.item_doc_background_selected); 65 mAlwaysShowSummary = context.getResources().getBoolean(R.bool.always_show_summary); 66 67 mSelectionHotspot = itemView.findViewById(R.id.icon_check); 68 } 69 70 /** 71 * Binds the view to the given item data. 72 * @param cursor 73 * @param modelId 74 * @param state 75 */ 76 public abstract void bind(Cursor cursor, String modelId, State state); 77 78 /** 79 * Makes the associated item view appear selected. Note that this merely affects the appearance 80 * of the view, it doesn't actually select the item. 81 * 82 * @param selected 83 */ 84 public void setSelected(boolean selected) { 85 itemView.setActivated(selected); 86 itemView.setBackgroundColor(selected ? mSelectedItemColor : mDefaultItemColor); 87 } 88 89 /** 90 * Highlights the associated item view. 91 * @param highlighted 92 */ 93 public void setHighlighted(boolean highlighted) { 94 itemView.setBackgroundColor(highlighted ? mSelectedItemColor : mDefaultItemColor); 95 } 96 97 @Override 98 public boolean onKey(View v, int keyCode, KeyEvent event) { 99 // Event listener should always be set. 100 checkNotNull(mEventListener); 101 return mEventListener.onKey(this, keyCode, event); 102 } 103 104 public void addEventListener(DocumentHolder.EventListener listener) { 105 // Just handle one for now; switch to a list if necessary. 106 checkState(mEventListener == null); 107 mEventListener = listener; 108 } 109 110 public void addOnKeyListener(View.OnKeyListener listener) { 111 // Just handle one for now; switch to a list if necessary. 112 checkState(mKeyListener == null); 113 mKeyListener = listener; 114 } 115 116 public void setEnabled(boolean enabled) { 117 setEnabledRecursive(itemView, enabled); 118 } 119 120 public boolean onSingleTapUp(MotionEvent event) { 121 if (Events.isMouseEvent(event)) { 122 // Mouse clicks select. 123 // TODO: && input.isPrimaryButtonPressed(), but it is returning false. 124 if (mEventListener != null) { 125 return mEventListener.onSelect(this); 126 } 127 } else if (Events.isTouchEvent(event)) { 128 // Touch events select if they occur in the selection hotspot, otherwise they activate. 129 if (mEventListener == null) { 130 return false; 131 } 132 133 // Do everything in global coordinates - it makes things simpler. 134 Rect rect = new Rect(); 135 mSelectionHotspot.getGlobalVisibleRect(rect); 136 137 // If the tap occurred within the icon rect, consider it a selection. 138 if (rect.contains((int)event.getRawX(), (int)event.getRawY())) { 139 return mEventListener.onSelect(this); 140 } else { 141 return mEventListener.onActivate(this); 142 } 143 } 144 return false; 145 } 146 147 static void setEnabledRecursive(View itemView, boolean enabled) { 148 if (itemView == null) return; 149 if (itemView.isEnabled() == enabled) return; 150 itemView.setEnabled(enabled); 151 152 if (itemView instanceof ViewGroup) { 153 final ViewGroup vg = (ViewGroup) itemView; 154 for (int i = vg.getChildCount() - 1; i >= 0; i--) { 155 setEnabledRecursive(vg.getChildAt(i), enabled); 156 } 157 } 158 } 159 160 private static View inflateLayout(Context context, ViewGroup parent, int layout) { 161 final LayoutInflater inflater = LayoutInflater.from(context); 162 return inflater.inflate(layout, parent, false); 163 } 164 165 /** 166 * Implement this in order to be able to respond to events coming from DocumentHolders. 167 */ 168 interface EventListener { 169 /** 170 * Handles activation events on the document holder. 171 * 172 * @param doc The target DocumentHolder 173 * @return Whether the event was handled. 174 */ 175 public boolean onActivate(DocumentHolder doc); 176 177 /** 178 * Handles selection events on the document holder. 179 * 180 * @param doc The target DocumentHolder 181 * @return Whether the event was handled. 182 */ 183 public boolean onSelect(DocumentHolder doc); 184 185 /** 186 * Handles key events on the document holder. 187 * 188 * @param doc The target DocumentHolder. 189 * @param keyCode Key code for the event. 190 * @param event KeyEvent for the event. 191 * @return Whether the event was handled. 192 */ 193 public boolean onKey(DocumentHolder doc, int keyCode, KeyEvent event); 194 } 195} 196