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