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 17 package com.example.androidx.widget.touch; 18 19 import android.app.Activity; 20 import android.graphics.Canvas; 21 import android.os.Bundle; 22 import android.view.LayoutInflater; 23 import android.view.View; 24 import android.view.ViewGroup; 25 import android.widget.Button; 26 import android.widget.TextView; 27 28 import androidx.cardview.widget.CardView; 29 import androidx.recyclerview.widget.ItemTouchHelper; 30 import androidx.recyclerview.widget.LinearLayoutManager; 31 import androidx.recyclerview.widget.RecyclerView; 32 33 import com.example.androidx.Cheeses; 34 import com.example.androidx.R; 35 import com.example.androidx.widget.util.ConfigToggle; 36 import com.example.androidx.widget.util.ConfigViewHolder; 37 38 import org.jspecify.annotations.NonNull; 39 import org.jspecify.annotations.Nullable; 40 41 import java.util.ArrayList; 42 import java.util.Arrays; 43 import java.util.List; 44 45 /** 46 * Sample activity from which ItemTouchHelper demo activities inherit. 47 */ 48 abstract public class ItemTouchHelperActivity extends Activity { 49 50 public RecyclerView mRecyclerView; 51 52 public ItemTouchAdapter mAdapter; 53 54 public ItemTouchHelper mItemTouchHelper; 55 56 public ItemTouchHelper.Callback mCallback; 57 58 private ConfigToggle[] mConfigToggles; 59 60 @Override onCreate(Bundle savedInstanceState)61 public void onCreate(Bundle savedInstanceState) { 62 super.onCreate(savedInstanceState); 63 setContentView(R.layout.activity_item_touch); 64 mRecyclerView = findViewById(R.id.recycler_view); 65 mRecyclerView.setHasFixedSize(true); 66 mAdapter = createAdapter(); 67 mRecyclerView.setAdapter(mAdapter); 68 mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); 69 mItemTouchHelper = createItemTouchHelper(); 70 mItemTouchHelper.attachToRecyclerView(mRecyclerView); 71 initToggles(); 72 } 73 initToggles()74 private void initToggles() { 75 mConfigToggles = createConfigToggles(); 76 RecyclerView configView = findViewById(R.id.config_recycler_view); 77 configView.setAdapter(new RecyclerView.Adapter<ConfigViewHolder>() { 78 @Override 79 public ConfigViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 80 return new ConfigViewHolder(LayoutInflater.from(parent.getContext()) 81 .inflate(R.layout.config_view_toggle, parent, false)); 82 } 83 84 @Override 85 public void onBindViewHolder(ConfigViewHolder holder, int position) { 86 ConfigToggle toggle = mConfigToggles[position]; 87 holder.bind(toggle); 88 } 89 90 @Override 91 public int getItemCount() { 92 return mConfigToggles.length; 93 } 94 }); 95 configView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, 96 false)); 97 configView.setHasFixedSize(true); 98 } 99 createConfigToggles()100 abstract ConfigToggle[] createConfigToggles(); 101 createItemTouchHelper()102 public ItemTouchHelper createItemTouchHelper() { 103 mCallback = createCallback(); 104 return new ItemTouchHelper(mCallback); 105 } 106 createCallback()107 public ItemTouchHelper.Callback createCallback() { 108 return new ItemTouchHelper.Callback() { 109 @Override 110 public int getMovementFlags(@NonNull RecyclerView recyclerView, 111 RecyclerView.@NonNull ViewHolder viewHolder) { 112 return ItemTouchHelperActivity.this.getMovementFlags(recyclerView, viewHolder); 113 } 114 115 @Override 116 public boolean onMove(@NonNull RecyclerView recyclerView, 117 RecyclerView.@NonNull ViewHolder viewHolder, 118 RecyclerView.@NonNull ViewHolder target) { 119 mAdapter.move(viewHolder.getBindingAdapterPosition(), 120 target.getBindingAdapterPosition()); 121 return true; 122 } 123 124 @Override 125 public void onSwiped(RecyclerView.@NonNull ViewHolder viewHolder, int direction) { 126 mAdapter.delete(viewHolder.getAdapterPosition()); 127 } 128 129 @Override 130 public void onSelectedChanged(RecyclerView.@Nullable ViewHolder viewHolder, 131 int actionState) { 132 super.onSelectedChanged(viewHolder, actionState); 133 ItemTouchHelperActivity.this.onSelectedChanged(viewHolder, actionState); 134 } 135 136 @Override 137 public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, 138 RecyclerView.@NonNull ViewHolder viewHolder, 139 float dX, float dY, int actionState, boolean isCurrentlyActive) { 140 if (ItemTouchHelperActivity.this.onChildDraw(c, recyclerView, viewHolder, 141 dX, dY, actionState, isCurrentlyActive)) { 142 return; 143 } 144 super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, 145 isCurrentlyActive); 146 } 147 148 @Override 149 public void onChildDrawOver(@NonNull Canvas c, @NonNull RecyclerView recyclerView, 150 RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, 151 boolean isCurrentlyActive) { 152 if (ItemTouchHelperActivity.this.onChildDrawOver(c, recyclerView, viewHolder, 153 dX, dY, actionState, isCurrentlyActive)) { 154 return; 155 } 156 super.onChildDrawOver(c, recyclerView, viewHolder, dX, dY, actionState, 157 isCurrentlyActive); 158 } 159 160 @Override 161 public boolean isLongPressDragEnabled() { 162 return ItemTouchHelperActivity.this.isLongPressDragEnabled(); 163 } 164 165 @Override 166 public boolean isItemViewSwipeEnabled() { 167 return ItemTouchHelperActivity.this.isPointerSwipeEnabled(); 168 } 169 170 @Override 171 public void clearView(@NonNull RecyclerView recyclerView, 172 RecyclerView.@NonNull ViewHolder viewHolder) { 173 super.clearView(recyclerView, viewHolder); 174 ItemTouchHelperActivity.this.clearView(viewHolder); 175 } 176 }; 177 } 178 179 /** 180 * @return True if we should NOT call parent 181 */ 182 public boolean onChildDraw(Canvas c, RecyclerView recyclerView, 183 RecyclerView.ViewHolder viewHolder, 184 float dX, float dY, int actionState, boolean isCurrentlyActive) { 185 return false; 186 } 187 188 /** 189 * @return True if we should NOT call parent 190 */ 191 public boolean onChildDrawOver(Canvas c, RecyclerView recyclerView, 192 RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, 193 boolean isCurrentlyActive) { 194 return false; 195 } 196 197 public void clearView(RecyclerView.ViewHolder viewHolder) { 198 199 } 200 201 public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { 202 203 } 204 205 public boolean isLongPressDragEnabled() { 206 return true; 207 } 208 209 public boolean isPointerSwipeEnabled() { 210 return true; 211 } 212 213 public ItemTouchViewHolder onCreateViewHolder(ViewGroup parent) { 214 return new ItemTouchViewHolder( 215 LayoutInflater.from(parent.getContext()) 216 .inflate(R.layout.touch_item, parent, false)); 217 } 218 219 abstract public int getMovementFlags(RecyclerView recyclerView, 220 RecyclerView.ViewHolder viewHolder); 221 222 public ItemTouchAdapter createAdapter() { 223 return new ItemTouchAdapter(); 224 } 225 226 public void onBind(ItemTouchViewHolder viewHolder) { 227 228 } 229 230 public void onCreateViewHolder(ItemTouchViewHolder viewHolder) { 231 232 } 233 234 public static class ItemTouchViewHolder extends RecyclerView.ViewHolder { 235 236 public final TextView textView; 237 238 public final Button actionButton; 239 240 public final CardView cardView; 241 242 public final View overlay; 243 244 public ItemTouchViewHolder(View itemView) { 245 super(itemView); 246 cardView = (CardView) itemView; 247 textView = (TextView) itemView.findViewById(R.id.text_view); 248 actionButton = (Button) itemView.findViewById(R.id.action_button); 249 overlay = itemView.findViewById(R.id.overlay); 250 } 251 } 252 253 public class ItemTouchAdapter extends RecyclerView.Adapter<ItemTouchViewHolder> { 254 255 private List<String> mItems = new ArrayList<String>(); 256 257 public ItemTouchAdapter() { 258 mItems.addAll(Arrays.asList(Cheeses.sCheeseStrings)); 259 } 260 261 @Override 262 public ItemTouchViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 263 return ItemTouchHelperActivity.this.onCreateViewHolder(parent); 264 } 265 266 @Override 267 public void onBindViewHolder(ItemTouchViewHolder holder, int position) { 268 holder.textView.setText(mItems.get(position)); 269 onBind(holder); 270 } 271 272 public void delete(int position) { 273 mItems.remove(position); 274 notifyItemRemoved(position); 275 } 276 277 public void move(int from, int to) { 278 String prev = mItems.remove(from); 279 mItems.add(to > from ? to - 1 : to, prev); 280 notifyItemMoved(from, to); 281 } 282 283 @Override 284 public int getItemCount() { 285 return mItems.size(); 286 } 287 } 288 289 290 } 291