1 /* 2 * Copyright 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 package com.example.androidx.widget.selection.fancy; 17 18 import android.content.Context; 19 import android.graphics.Rect; 20 import android.net.Uri; 21 import android.util.Log; 22 import android.view.MotionEvent; 23 import android.view.View; 24 import android.view.ViewGroup; 25 import android.widget.LinearLayout; 26 import android.widget.TextView; 27 28 import androidx.annotation.Dimension; 29 import androidx.recyclerview.selection.ItemDetailsLookup.ItemDetails; 30 31 import com.example.androidx.R; 32 33 import org.jspecify.annotations.NonNull; 34 import org.jspecify.annotations.Nullable; 35 36 final class DemoItemHolder extends DemoHolder { 37 38 private static final String TAG = "SelectionDemos"; 39 private final LinearLayout mContainer; 40 private final TextView mSelector; 41 private final TextView mLabel; 42 private final ItemDetails<Uri> mDetails; 43 44 private @Nullable Uri mKey; 45 DemoItemHolder(@onNull Context context, @NonNull ViewGroup parent)46 DemoItemHolder(@NonNull Context context, @NonNull ViewGroup parent) { 47 this(inflateLayout(context, parent, R.layout.selection_demo_list_item)); 48 } 49 DemoItemHolder(LinearLayout layout)50 private DemoItemHolder(LinearLayout layout) { 51 super(layout); 52 53 mContainer = layout.findViewById(R.id.container); 54 mSelector = layout.findViewById(R.id.selector); 55 mLabel = layout.findViewById(R.id.label); 56 mDetails = new ItemDetails<Uri>() { 57 @Override 58 public int getPosition() { 59 return DemoItemHolder.this.getAbsoluteAdapterPosition(); 60 } 61 62 @Override 63 public Uri getSelectionKey() { 64 return DemoItemHolder.this.mKey; 65 } 66 67 @Override 68 public boolean inDragRegion(@NonNull MotionEvent e) { 69 return DemoItemHolder.this.inDragRegion(e); 70 } 71 72 @Override 73 public boolean inSelectionHotspot(@NonNull MotionEvent e) { 74 return DemoItemHolder.this.inSelectRegion(e); 75 } 76 77 @Override 78 public @NonNull String toString() { 79 return DemoItemHolder.this.toString(); 80 } 81 }; 82 83 mLabel.setOnClickListener(new View.OnClickListener() { 84 @Override 85 public void onClick(View view) { 86 view.setBackgroundColor(0xAA000000); 87 Log.d(TAG, "Unexpected click received on item: " + mDetails.getSelectionKey()); 88 } 89 }); 90 } 91 92 @Override update(@onNull Uri uri)93 void update(@NonNull Uri uri) { 94 mKey = uri; 95 mLabel.setText(Uris.getCheese(uri)); 96 } 97 setSmallLayoutMode(boolean small)98 void setSmallLayoutMode(boolean small) { 99 mSelector.setVisibility(small ? View.GONE : View.VISIBLE); 100 mLabel.setTextSize(Dimension.SP, small ? 14f : 20f); 101 } 102 setSelected(boolean selected)103 void setSelected(boolean selected) { 104 mContainer.setActivated(selected); 105 mSelector.setActivated(selected); 106 } 107 inDragRegion(MotionEvent event)108 boolean inDragRegion(MotionEvent event) { 109 // If itemView is activated = selected, then whole region is interactive 110 if (itemView.isActivated()) { 111 return true; 112 } 113 114 // Do everything in global coordinates - it makes things simpler. 115 int[] coords = new int[2]; 116 mSelector.getLocationOnScreen(coords); 117 118 Rect textBounds = new Rect(); 119 mLabel.getPaint().getTextBounds( 120 mLabel.getText().toString(), 0, mLabel.getText().length(), textBounds); 121 122 Rect rect = new Rect( 123 coords[0], 124 coords[1], 125 coords[0] + mSelector.getWidth() + textBounds.width(), 126 coords[1] + Math.max(mSelector.getHeight(), textBounds.height())); 127 128 // If the tap occurred inside icon or the text, these are interactive spots. 129 return rect.contains((int) event.getRawX(), (int) event.getRawY()); 130 } 131 inSelectRegion(MotionEvent e)132 boolean inSelectRegion(MotionEvent e) { 133 Rect iconRect = new Rect(); 134 return mSelector.getGlobalVisibleRect(iconRect) 135 && iconRect.contains((int) e.getRawX(), (int) e.getRawY()); 136 } 137 getItemDetails()138 ItemDetails<Uri> getItemDetails() { 139 return mDetails; 140 } 141 142 @Override toString()143 public String toString() { 144 return "Item{name:" + mLabel.getText() + ", url:" + mKey + "}"; 145 } 146 } 147