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

Overview

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.
Comments
  • Drop event listener

    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?

    opened by Gnzlt 8
  • Supplementing a custom animation for the default animation

    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.

    enhancement 
    opened by KMaragh 6
  • Breaks with different viewTypes

    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?

    question 
    opened by scriptacus 5
  • disable dragging for some cells

    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?

    question 
    opened by pixelbendr 3
  • not working in navigation drawer

    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.

    opened by niraj-prajapati 1
  • Closing a spinner within a list row causes that row to be draggable

    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.

    wontfix 
    opened by allonmj 1
  • Sorts are not equal

    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);
    
    opened by Bender42 0
  • Position of item not getting changed when its moved

    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

    opened by TonyHaddad91 0
  • Able to drag (not drop) outside of Recyclerview or add DragShadow

    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

    opened by JKorsten 0
  • How to get below item at the time of dragging ? not UP or Down

    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 ?

    opened by Tejpandya 0
  • How to do drag and drop with different view types?

    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.

    opened by kokilaw 3
  • Cannot Update the position of the dragged file

    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.
    opened by aloklearning 1
Releases(v1.1)
Owner
Paul Burke
Senior Android Developer @Majestykapps
Paul Burke
Simple to use swipe gestures for an Android RecyclerView

Android-RecyclerView-Swipe-Gestures Contribution Contributions / PRs are welcome. 1. Introduction An easy to use and highly customizable implementatio

Willi Bölke 9 Aug 8, 2022
An Open Source App which enables users to drop all their professional handles and projects at one place.

An Open Source App which enables users to drop all their professional handles and projects at one place. This is a Beginner Friendly Repository made for Open Source Enthusiasts who can contribute to the App during HacktoberFest 2021.

GDSC JSS Noida 32 May 26, 2022
Github-Api-Pagination-Example - Pagination 3 Example using Github Api

Github-Api-Pagination Pagination 3 Example using Github Api Tech Stack 100% Kotl

Anggoro Beno Lukito 2 Aug 22, 2022
SimpleToDo is an android app that allows building a todo list and basic todo items management functionality including adding new items, editing and deleting an existing item.

SimpleToDo is an android app that allows building a todo list and basic todo items management functionality including adding new items, editing and deleting an existing item.

null 0 Jan 3, 2022
Todo List Application is an android app that allows building a todo list and basic todo items management functionality including adding new items, editing and deleting an existing item

Todo List Application is an android app that allows building a todo list and basic todo items management functionality including adding new items, editing and deleting an existing item

null 0 Jan 22, 2022
An app created for Code Lousiville in order to learn the in-and-outs of basic Android development

Tea House is an app created for Code Lousiville in order to learn the in-and-outs of basic Android development.

Chauncey Harlan 0 Nov 19, 2021
SimpleTodo - An android app that allows building a todo list and basic todo items management functionality

Pre-work - SimpleTodo SimpleTodo is an android app that allows building a todo l

null 0 Dec 31, 2021
App made using Kotlin to retrieve data from an API and show in a recyclerview with Login and SignUp features

App made using Kotlin to retrieve data from an API and show in a recyclerview with Login and SignUp features.

Altair Wallace 1 Feb 17, 2022
A small RPG example for a YouTube tutorial series using Kotlin, LibGDX, LibKTX and GDX-AI.

Mystic Woods A libGDX project generated with gdx-liftoff. This project was generated with a Kotlin project template that includes Kotlin application l

Simon 15 Dec 19, 2022
Ojo is a basic RTSP IP Camera surveillance wall for Android

Ojo: the FLOSS RTSP Surveillance camera viewer for Android (Always prefer F-Droid build, when possible). Ojo is a basic IP Camera surveillance wall. I

Daniele Verducci 24 Nov 9, 2022
An android app that can perform basic arithmetic calculations on the go.

An android app that can perform basic arithmetic calculations on the go. App uses constraintLayout to map out the UI, MxParser for handling mathematical calculations

Uzodike Oguejiofor 2 Mar 4, 2022
Quiz-App - An Android app which have some basic questions

Quiz-App An Android app which have some basic questions Start page Questions pag

Gururaj KL 3 Apr 21, 2022
A news application through which you can learn and browse all the news that interests you by choosing the country and type of news with the ability to browse and add some news to your favorites

MY-NEWS-Android A news application through which you can learn and browse all the news that interests you by choosing the country and type of news wit

Mahmoud ELramady 0 Nov 11, 2021
Slack app example for Heroku deployment, written in Kotlin, using Bolt framework.

slack-kotlin-heroku-example Slack app example for Heroku deployment, written in Kotlin, using Bolt framework. You need to configure your Slack app to

null 0 Dec 25, 2021
This is an example for running a Python library (mishkal) in Android using chaquopy

chaquopy-mishkal This is an example for running a Python library (mishkal) in Android using chaquopy Code All the code that has been added to run the

Mehdi Nassim KHODJA 2 Oct 10, 2022
Money Manager app that helps you to add your daily small incomes and expenses and track them easily.

Simple Money Manager This app is a simple money manager app which helps you to add your daily small incomes and expenses and track them easily. Screen

Yash Bansal 2 Nov 21, 2021
Application that allows to search some products and display them in a list, also allows to add some product to the shopping cart and remove it

Application that allows to search some products and display them in a list, also allows to add some product to the shopping cart and remove it

Victor 3 Aug 18, 2022
Extensible Android mobile voice framework: wakeword, ASR, NLU, and TTS. Easily add voice to any Android app!

Spokestack is an all-in-one solution for mobile voice interfaces on Android. It provides every piece of the speech processing puzzle, including voice

Spokestack 57 Nov 20, 2022
An android app that show us nike products and user can buy them or add to shopping cart.

Nike Store-Android-App An android app that show us nike products and user can buy them or add to shopping cart. Screenshots Libraries included Materia

mojtaba joshaghani 9 Aug 13, 2022