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
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

G. Blake Meike 214 Nov 25, 2022
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

G. Blake Meike 165 Nov 11, 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

#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

Mike Penz 1.8k Nov 10, 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

#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

Mike Penz 1.8k Nov 10, 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

Kaushik Gopal 7.6k Dec 30, 2022
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

Fernando Cejas 422 Nov 25, 2022
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

Ilya Fomenko 922 Nov 23, 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

Kaushik Gopal 7.6k Dec 29, 2022
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

Pamir Cevikogullari 334 Nov 29, 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

null 0 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 │ └

Rob Moore 2 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

Mohamed Dekow 1 Nov 18, 2021
Viacheslav Veselov 0 Jul 8, 2022
🧸 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

Jaewoong Eum 791 Dec 30, 2022
📚 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

Madalin Valceleanu 2.3k Dec 30, 2022
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

Irsyad Abdillah 25 Dec 9, 2022
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

Clint Paul 38 Nov 28, 2022
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

null 0 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.

Ismail Oguzhan Ay 13 Dec 4, 2022