Basic example of using ItemTouchHelper to add drag & drop and swipe-to-dismiss to RecyclerView.

Last update: May 15, 2022

Another drag and swipe library?

This project is an example of basic drag & drop and swipe-to-dismiss with RecyclerView using ItemTouchHelper. It corresponds with an article series found here:

Drag and swipe with RecyclerView

The classes in co.paulburke.android.itemtouchhelperdemo.helper can easily be used in other projects.

Download the apk from releases.

Credits

Developed by Paul Burke (iPaulPro) - paulburke.co

License

Copyright (C) 2015 Paul Burke

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

GitHub

https://github.com/iPaulPro/Android-ItemTouchHelper-Demo
Comments
  • 1. Drop event listener

    As you said at your Medium post, we’re changing the position of the item every time the view is shifted to a new index, and not at the end of a “drop” event.

    So, would it be possible to add a listener or to be notified at the end of a drop event in order to make changes to the layout or to store those changes in a DB?

    Reviewed by Gnzlt at 2015-08-03 08:10
  • 2. Supplementing a custom animation for the default animation

    I noticed your medium post and I think it was a great tutorial on how to use the Android supported ItemTouchHelper for a recyclerview. I'm not sure if you have this planned in the future, but if you can demonstrate how to replace the default swipe animation that comes with an ItemTouchHelper with your own custom view animation, I feel this tutorial will be even more complete.

    Reviewed by KMaragh at 2015-06-23 20:17
  • 3. Breaks with different viewTypes

    Unfortunately, I've been unable to make this work with multiple viewTypes. It appears that the RecyclerView scraps differing viewTypes when they are dragged over each other, which cancels the re-ordering process. Any ideas on how to fix this?

    Reviewed by scriptacus at 2015-07-19 08:26
  • 4. disable dragging for some cells

    Hello Paul,

    so in my app I want users to be able to delete cells that they created. so for example in a group chat you can only delete a message you create. so swipe to dismiss should be disabled for messages which the user didn't create.

    Whats the best way to approach this?

    Reviewed by pixelbendr at 2015-07-02 13:29
  • 5. not working in navigation drawer

    It doesn't work in the navigation drawer. I need to rearrange items in the navigation drawer. it works with onTouchListener but disables onClick of items. I need to use it with onLongClickListener so click can also work.

    Please help me to do this. Thanks.

    Reviewed by niraj-prajapati at 2020-07-07 11:24
  • 6. Closing a spinner within a list row causes that row to be draggable

    If you add a spinner to each list row, opening and closing that spinner puts the row as the 'selected' row. Now scrolling the list will drag that row.

    Reviewed by allonmj at 2015-07-19 22:32
  • 7. Sorts are not equal

    https://github.com/iPaulPro/Android-ItemTouchHelper-Demo/blob/d164fba0f27c8aa38cfa7dbd4bc74d53dea44605/app/src/main/java/co/paulburke/android/itemtouchhelperdemo/RecyclerListAdapter.java#L90

    Сhanges in lists Collections.swap(mItems, fromPosition, toPosition) and notifyItemMoved(fromPosition, toPosition) not the same.

    You can check it by calling recyclerView.getAdapter().notifyDataSetChanged(); in SimpleItemTouchHelperCallback#clearView()

    My simple solution is:

    String item = mItems.get(fromPosition);
    expenditures.remove(fromPosition);
    expenditures.add(toPosition, item);
    
    Reviewed by Bender42 at 2018-03-14 21:08
  • 8. Position of item not getting changed when its moved

    Thanks for this great demo

    I have an issue while i'm using it with GridLayout manager that the item keeps there old positions e.g. if i moved an item from position 0 to position 3 when i click on it and print out the position it will give me 0 also

    even tho i added this snippet which is can be related to this issue

    public boolean onItemMove(int fromPosition, int toPosition) { if (fromPosition < toPosition) { for (int i = fromPosition; i < toPosition; i++) { Collections.swap(mItems, i, i + 1); } } else { for (int i = fromPosition; i > toPosition; i--) { Collections.swap(mItems, i, i - 1); } } notifyItemMoved(fromPosition, toPosition); return true; }

    Thanks

    Reviewed by TonyHaddad91 at 2017-04-21 02:48
  • 9. Able to drag (not drop) outside of Recyclerview or add DragShadow

    Hey Paul,

    Great demo (although it doesn't compile for me, I could use the classes and get it to work in my app). But I have a question. Is it possible to see the selected item (the one which you are dragging) also outside the RecyclerView. I don't want to drop it there but it is possible that with dragging I will pass my recyclerview bounds and then the item will be cut off or even become invisible.

    Is this possible using the ItemTouchHandler or should I do this in another way?

    Another solution can be to use a DrawShadow which can be moved around the screen and use the ItemTouchHandler to do the reordering.

    Kind regards,

    JKorsten

    Reviewed by JKorsten at 2019-10-08 10:02
  • 10. How to get below item at the time of dragging ? not UP or Down

    I want to store item into folder on dropping that item onto folder . so Is there any way around to get my background view at the time of dragging ? If there is a folder i want to store that item into folder . So i have to detect what is in the background at the time of dragging .. Is it possible by ItemTouchHelper ?

    Reviewed by Tejpandya at 2018-03-28 06:55
  • 11. How to do drag and drop with different view types?

    I need to implement the drag and drop for items with different view types. I tried with following code

    override fun onMove(recyclerView: RecyclerView, source: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
            // Notify the adapter of the move
            mAdapter.onItemMove(source.adapterPosition, target.adapterPosition)
            return true
    }
    

    without

    if (source.itemViewType != target.itemViewType) {
                return false
    }
    

    but it doesn't work as I expected. I'm using a grid layout by the way.

    Reviewed by kokilaw at 2017-12-05 05:08
  • 12. Cannot Update the position of the dragged file

    Since my drag and drop is working fine but still the item which has been moved is not updating its position. The code is like this :

    public class EditVideoActivity extends AppCompatActivity implements OnStartDragListener{

    private ImageButton filterButton,cutButton;
    //audioButton;
    
    ArrayList<File> mList;
    ArrayList<File> files;
    private static int position = 0;
    
    RecyclerView recyclerView;
    private String selectedVideo;
    
    private int selectedPos;
    
    ViewAdapter viewAdapter;
    
    RecyclerView.LayoutManager layoutManager;
    
    private VideoView mVideoView;
    
    private MediaController mController;
    
    private Project project;
    
    private ItemTouchHelper itemTouchHelper;
    
    //private static final int CustomizeAudio = 1;
    private static final int CustomizeFilter = 2;
    private static final int CustomCutvideo = 3;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        setContentView(R.layout.activity_edit_video);
    
        getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
        getSupportActionBar().setCustomView(R.layout.edit_header_layout);
        getSupportActionBar().setHomeAsUpIndicator(R.mipmap.ic_keyboard_arrow_left_black_24dp);
        getSupportActionBar().setDisplayShowHomeEnabled(true);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    
        mVideoView = (VideoView) findViewById(R.id.editVideoPlayer);
    
        filterButton = (ImageButton) findViewById(R.id.filterVideo);
        cutButton = (ImageButton) findViewById(R.id.cutVideo);
        //audioButton = (ImageButton) findViewById(R.id.musicalNotes);
    
        //change the color of the imagebutton explicitely
        filterButton.setColorFilter(Color.BLACK);
        cutButton.setColorFilter(Color.BLACK);
        //audioButton.setColorFilter(Color.BLACK);
    
        recyclerView = (RecyclerView) findViewById(R.id.videoGallery);
        recyclerView.setHasFixedSize(true);
    
        mList = new ArrayList<>();
    
        int view = getIntent().getIntExtra("view", 0);
    
        //this is for admin activity else addfragment
        if(view == 1){
            project = (Project) getIntent().getSerializableExtra("groupVideoData");
            Log.e("PROJECT_ID", String.valueOf(project.getId()));
            Log.e("PROJECT_DATA", String.valueOf(project.getVideoData().size()));
    
            for(String adminPath : project.getVideoData()){
                File files = new File(adminPath);
                mList.add(files);
            }
    
    
            //inflating the layout horizontally
            layoutManager = new LinearLayoutManager(getParent(), LinearLayoutManager.HORIZONTAL, false);
            recyclerView.setLayoutManager(layoutManager);
            viewAdapter = new ViewAdapter(mList);
            Log.e("LIST====", mList.toString());
            recyclerView.setAdapter(viewAdapter);
            recyclerView.setVisibility(View.VISIBLE);
    
            ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallBack(viewAdapter);
            itemTouchHelper = new ItemTouchHelper(callback);
            itemTouchHelper.attachToRecyclerView(recyclerView);
    
        }else {
            //getting the value from project class object
            project = (Project) getIntent().getSerializableExtra("passedData");
            Log.e("project id====", String.valueOf(project.getId()));
            Log.e("project data =====", String.valueOf(project.getVideoData().size()));
            //Log.e("RECEIVED DATA=====", receivedData.toString());
    
            for (String path : project.getVideoData()) {
                //initialising path with file
                File file = new File(path);
                Log.e("FILENAME===", path);
                mList.add(file); //adding file in array list<file> object
            }
    
            //inflating the layout horizontally
            layoutManager = new LinearLayoutManager(getParent(), LinearLayoutManager.HORIZONTAL, false);
            recyclerView.setLayoutManager(layoutManager);
            viewAdapter = new ViewAdapter(mList);
            Log.e("LIST====", mList.toString());
            recyclerView.setAdapter(viewAdapter);
            recyclerView.setVisibility(View.VISIBLE);
    
            ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallBack(viewAdapter);
            itemTouchHelper = new ItemTouchHelper(callback);
            itemTouchHelper.attachToRecyclerView(recyclerView);
        }
    
    }
    //just for a change
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        getMenuInflater().inflate(R.menu.edit_video, menu);
        return true;
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                finish();
                return true;
    
            case R.id.moveNext:
                Intent intent = new Intent(EditVideoActivity.this,PreviewActivity.class);
                //sending the file in string array list form to avoid mismatch of the file to string
                //conversion
                ArrayList<String> files = new ArrayList<>();
                for(File file : mList){
                    files.add(file.getAbsolutePath());
                }
                intent.putStringArrayListExtra("videosList",files);
                intent.putExtra("videos", project);
                startActivity(intent);
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
    
    @Override
    public void onBackPressed() {
        moveTaskToBack(false);
    }
    
    @Override
    public void onDragStart(RecyclerView.ViewHolder viewHolder) {
        itemTouchHelper.startDrag(viewHolder);
    }`
    

    and my RecyclerViewAdapter is here . :

    public class ViewAdapter extends RecyclerView.Adapter<ViewAdapter.ViewHolder> implements 
      ItemTouchHelperAdapter{
    ```
    
    
            private View rootView;
    
            private Bitmap bitmap;
    
            //calling the mList in constructor's argument item
            public ViewAdapter(ArrayList<File> items) {
                files = items;
                Log.e("ITEMS====",items.toString());
            }
    
    
            @Override
            public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                    Log.e("ADAPTER","VIEW HOLDER CREATED");
                Context context = parent.getContext();
                LayoutInflater inflater = LayoutInflater.from(context);
    
                rootView = inflater.inflate(R.layout.custom_listview,parent,false);
                ViewHolder viewholder =  new ViewHolder(rootView);
                return viewholder;
            }
    
            @Override
            public void onBindViewHolder( ViewHolder holder, final int position) {
                Log.e("ADAPTER",files.get(position).toString());
                EditVideoActivity.position = position;
                if (files != null) {
    
                    bitmap = ThumbnailUtils.createVideoThumbnail(files.get(position).toString(),1);
                    holder.mImageView.setImageBitmap(bitmap);
                    //click event from the holder
                    holder.mImageView.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            //getting the details of the selected video
                            updatedVideo();
                            Log.e("POS_SELECTED", String.valueOf(files.indexOf(files.get(position))));
                        }
                    });
    
                }
    
            }
    
            @Override
            public int getItemCount() {
                return files.size();
            }
    
    
            @Override
            public boolean onItemMove(int fromPosition, int toPosition) {
                if (fromPosition < toPosition) {
                    for (int i = fromPosition; i < toPosition; i++) {
                        Collections.swap(files, i, i + 1);
                    }
                } else {
                    for (int i = fromPosition; i > toPosition; i--) {
                        Collections.swap(files, i, i - 1);
                    }
                }
                notifyItemMoved(fromPosition, toPosition);
                return true;
            }
    
            @Override
            public void onItemDismiss(int position) {
    
            }
    
    
            //holder holding the image object from the custom listView
              class ViewHolder extends RecyclerView.ViewHolder {
                public ImageView mImageView;
                public String videoPosition;
                public int videoPos;
    
                  public ViewHolder(View view) {
                      super(view);
    
                      mImageView = (ImageView) view.findViewById(R.id.imageView);
    
                     //  -----------  FILTER EDITING   -----------------
                      filterButton.setOnClickListener(new View.OnClickListener() {
                          @Override
                          public void onClick(View view) {
                              videoPosition = selectedVideo;
                              videoPos = selectedPos;
    
                              if(videoPosition != null){
                                  Intent intent = new Intent(EditVideoActivity.this, FilterActivity.class);
                                  intent.putExtra("videoData",videoPosition);
                                  intent.putExtra("position",selectedPos); //sending the data of the position
                                  Log.e("VIDEO_SENT_DATA=======", videoPosition);
                                  Log.e("POSITION===",String.valueOf(selectedPos));
                                  startActivityForResult(intent,CustomizeFilter);
                              }else
                                  Toast.makeText(EditVideoActivity.this,"You have not selected any video",Toast.LENGTH_LONG)
                                          .show();
                          }
                      });
    
                      // --------------- CUT VIDEO  ----------------
                      cutButton.setOnClickListener(new View.OnClickListener() {
                          @Override
                          public void onClick(View view) {
                              videoPosition = selectedVideo;
                              videoPos = selectedPos;
    
                              if(videoPosition != null){
                                  Intent intent = new Intent(EditVideoActivity.this,CutVideoActivity.class);
                                  intent.putExtra("videoData",videoPosition);
                                  intent.putExtra("position",selectedPos); //sending the data of the position
                                  Log.e("VIDEO_SENT_DATA=======", videoPosition);
                                  Log.e("POSITION===",String.valueOf(selectedPos));
                                  startActivityForResult(intent,CustomCutvideo);
                              }else
                                  Toast.makeText(EditVideoActivity.this,"You have not selected any video",Toast.LENGTH_LONG)
                                          .show();
                          }
                      });
                  }
    
            }
        }
    
        private void updatedVideo() {
    
            //getting video position for passing the data
            selectedVideo = files.get(position).toString();
    
            //getting the position of the selected one
            selectedPos = files.indexOf(files.get(position));
    
            //for starting the video activity
            mVideoView.setVideoPath(files.get(position).toString());
            mController = new MediaController(EditVideoActivity.this);
            mController.setMediaPlayer(mVideoView);
            mVideoView.setMediaController(mController);
            mVideoView.requestFocus();
            mVideoView.start();
        }`
    
    In my logcat if I select the first one that is at pos = 0 then after dragging to pos = 1 and selecting the same again it will give the selected pos = 0 only.
    Reviewed by aloklearning at 2017-11-02 08:02
This repo contains example code for O'Reilly's "Programming Android" by Zigured Mednieks, Laird Dornin, Blake Meike and Masumi Nakamura

This repo contains working code for the example in O'Reilly's _Programming Android, 2nd Edition_; Mednieks, Dornin, Meike, Nakamura (http://shop.orei

Nov 4, 2021
This repo contains example code for O'Reilly's "Programming Android" by Zigured Mednieks, Laird Dornin, Blake Meike and Masumi Nakamura

This repo contains working code for the example in O'Reilly's _Programming Android, 2nd Edition_; Mednieks, Dornin, Meike, Nakamura (http://shop.orei

Apr 15, 2022
A simple app to showcase Androids Material Design and some of the cool new cool stuff in Android Lollipop. RecyclerView, CardView, ActionBarDrawerToggle, DrawerLayout, Animations, Android Compat Design, Toolbar
A simple app to showcase Androids Material Design and some of the cool new cool stuff in Android Lollipop. RecyclerView, CardView, ActionBarDrawerToggle, DrawerLayout, Animations, Android Compat Design, Toolbar

#Android-LollipopShowcase This is a simple showcase to show off Android's all new Material Design and some other cool new stuff which is (new) in Andr

Apr 17, 2022
A simple app to showcase Androids Material Design and some of the cool new cool stuff in Android Lollipop. RecyclerView, CardView, ActionBarDrawerToggle, DrawerLayout, Animations, Android Compat Design, Toolbar
A simple app to showcase Androids Material Design and some of the cool new cool stuff in Android Lollipop. RecyclerView, CardView, ActionBarDrawerToggle, DrawerLayout, Animations, Android Compat Design, Toolbar

#Android-LollipopShowcase This is a simple showcase to show off Android's all new Material Design and some other cool new stuff which is (new) in Andr

Apr 17, 2022
Learning RxJava for Android by example

Learning RxJava for Android by example This is a repository with real-world useful examples of using RxJava with Android. It usually will be in a cons

May 19, 2022
This is a simple example of Aspect Oriented Programming in Android
This is a simple example of Aspect Oriented Programming in Android

Android-AOPExample This is a simple example of Aspect Oriented Programming in Android as part of a blog post I have written. The idea was to measure h

Apr 18, 2022
The example Android project of animated menu items in toolbar
The example Android project of animated menu items in toolbar

Android Animated Menu Items The example Android project of animated menu items in toolbar. Thanks Srikant Shetty for idea of this animation. Cut: Copy

May 12, 2022
Learning RxJava for Android by example

Learning RxJava for Android by example This is a repository with real-world useful examples of using RxJava with Android. It usually will be in a cons

May 16, 2022
Example app for shortcuts
Example app for shortcuts

Android Shortcuts Example app for shortcuts in design library v25 Demo Manifest Add meta-data before </activity> tag in Manifest.xml <meta-data androi

May 17, 2022
An example that demonstrates how to integrate a learning app with the EIDU platform

EIDU Sample Learning App This app is an example of how to create a learning app that integrates with the EIDU platform. Please consult dev.eidu.com fo

Dec 17, 2021
Minimal example of how to safely share a file produced by a task in one project, with a task in another project.

How to share files across Gradle subprojects: A minimal example This is the Gradle project: . ├── producer │ └── build.gradle.kts ├── consumer │ └

Dec 17, 2021
A demonstration on how to Create Multiple ViewType RecyclerView

Multiple_View_Recyclerview The app fetches a damy data from an API to display on different view on Clients side A demonstration on how to Create Multi

Nov 18, 2021
Mar 9, 2022
🧸 A demo Disney app using Jetpack Compose and Hilt based on modern Android tech stacks and MVVM architecture.
🧸 A demo Disney app using Jetpack Compose and Hilt based on modern Android tech stacks and MVVM architecture.

DisneyCompose A demo Disney app using compose and Hilt based on modern Android tech-stacks and MVVM architecture. Fetching data from the network and i

May 20, 2022
📚 Sample Android Components Architecture on a modular word focused on the scalability, testability and maintainability written in Kotlin, following best practices using Jetpack.
📚  Sample Android Components Architecture on a modular word focused on the scalability, testability and maintainability written in Kotlin, following best practices using Jetpack.

Android Components Architecture in a Modular Word Android Components Architecture in a Modular Word is a sample project that presents modern, 2020 app

May 22, 2022
A sample Grocery Store app built using the Room, MVVM, Live Data, Rx Java, Dependency Injection (Kotlin Injection) and support Dark Mode
A sample Grocery Store app built using the Room, MVVM, Live Data, Rx Java, Dependency Injection (Kotlin Injection) and support Dark Mode

Apps Intro A sample Grocery Store app built using the Room, MVVM, Live Data, Rx Java, Dependency Injection (Kotlin Injection) and support Dark Mode In

Mar 27, 2022
A demo application that uses TMDB APIs to fetch the movie details and cache it using the Room DB.
A demo application that uses TMDB APIs to fetch the movie details and cache it using the Room DB.

TMDB App Tmdb sample project is a demo application that is based on modern Android architectures. It will fetch the data from the network and cache it

Dec 25, 2021
simple android grocery app using kotlin and android studio
simple android grocery app using kotlin and android studio

Project Idea The idea of this project is to make a grocery android app that users can use to order the groceries they want. It doesn't contain any bac

Nov 29, 2021
👨‍💻 A demonstration modern Android development project with Jetpack(Compose, Room, ViewModel, Navigation), Hilt and based on MVVM by using Open Sky API. ✈️ 🌍
👨‍💻 A demonstration modern Android development project with Jetpack(Compose, Room, ViewModel, Navigation), Hilt and based on MVVM by using Open Sky API. ✈️ 🌍

A demonstration modern Android development project with Jetpack(Compose, Room, ViewModel, Navigation), Hilt and based on MVVM by using Open Sky API.

Apr 26, 2022