Skip to content

Instantly share code, notes, and snippets.

@iPaulPro
Last active December 9, 2022 05:18
Show Gist options
  • Star 38 You must be signed in to star a gist
  • Fork 13 You must be signed in to fork a gist
  • Save iPaulPro/2216ea5e14818056cfcc to your computer and use it in GitHub Desktop.
Save iPaulPro/2216ea5e14818056cfcc to your computer and use it in GitHub Desktop.
"Drag and swipe with RecyclerView" files
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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.
-->
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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.
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="?listPreferredItemHeight"
android:layout_gravity="center_vertical"
android:paddingLeft="16dp"
android:textAppearance="?android:attr/textAppearanceMedium" />
/*
* 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.
*/
import android.support.v7.widget.RecyclerView;
import android.widget.TextView;
public class ItemViewHolder extends RecyclerView.ViewHolder {
public final TextView textView;
public ItemViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView;
}
}
/*
* 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.
*/
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class MainFragment extends Fragment {
public MainFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
RecyclerListAdapter adapter = new RecyclerListAdapter();
recyclerView.setAdapter(adapter);
}
}
/*
* 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.
*/
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class RecyclerListAdapter extends RecyclerView.Adapter<ItemViewHolder> {
private static final String[] STRINGS = new String[]{
"One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"
};
private final List<String> mItems = new ArrayList<>();
public RecyclerListAdapter() {
mItems.addAll(Arrays.asList(STRINGS));
}
@Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_main, parent, false);
return new ItemViewHolder(view);
}
@Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
holder.textView.setText(mItems.get(position));
}
@Override
public int getItemCount() {
return mItems.size();
}
}
@iPaulPro
Copy link
Author

These are the starting point for the article Drag and Swipe with RecyclerView. A finished example can be found at Android-ItemTouchHelper-Demo.

@mtychyna
Copy link

ItemViewHolder.java
textView = (TextView) itemView.findViewById(R.id.text); ?

@kevinjam
Copy link

Implement it but getting java.lang.NullPointerException onTouch ... mDragStartListener.onStartDrag(holder);

@tejalshah84
Copy link

HI Paul - Thank you for the awesome tutorial. Is there anyway I can customize the "swipe to dismiss" to create "swipe to reveal a delete button" and then once delete button is clicked the view is removed from the recycler view. If so, please enlighten. I have been looking for this everywhere. Even checked out a few libraries but those libraries don't allow me to click on the list item to drill into the detail page then. So it only supports swipe and not click to go to detail page.

@erawhctim
Copy link

@mtychyna That's not necessary because the TextView is the root element of the layout (so its passed into theViewHolder constructor)

@shreyan007
Copy link

Long press to drag not working in activity is used instead of fragment

@ewrfedf
Copy link

ewrfedf commented Jul 20, 2017

        textView = (TextView) itemView.findViewById(R.id.hint);

@McSpooder
Copy link

in activity is used instead of fragment

Its doesn't work in a fragment either. Its possible to scroll but not to drag the items around... Anyone know a solution?

@rafagan
Copy link

rafagan commented Aug 10, 2020

<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

@rafagan
Copy link

rafagan commented Aug 10, 2020

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/text"
    android:layout_width="wrap_content"
    android:layout_height="?listPreferredItemHeight"
    android:layout_gravity="center_vertical"
    android:paddingStart="16dp"
    android:textAppearance="?android:attr/textAppearanceMedium" />

@rafagan
Copy link

rafagan commented Aug 10, 2020

package com.example.dragndropgrid

import android.view.View
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView.ViewHolder


class ItemViewHolder(itemView: View) : ViewHolder(itemView) {
    val textView: TextView? = itemView as? TextView

}

@rafagan
Copy link

rafagan commented Aug 10, 2020

package com.example.dragndropgrid

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView


class MainFragment : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        return inflater.inflate(R.layout.fragment_main, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val recyclerView =
            view.findViewById<View>(R.id.recycler_view) as RecyclerView
        recyclerView.setHasFixedSize(true)
        recyclerView.layoutManager = LinearLayoutManager(activity)
        val adapter = RecyclerListAdapter()
        recyclerView.adapter = adapter

        val callback: ItemTouchHelper.Callback = SimpleItemTouchHelperCallback(adapter)
        val touchHelper = ItemTouchHelper(callback)
        touchHelper.attachToRecyclerView(recyclerView)
    }
}

@rafagan
Copy link

rafagan commented Aug 10, 2020

package com.example.dragndropgrid

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import java.util.*


class RecyclerListAdapter : RecyclerView.Adapter<ItemViewHolder>(), ItemTouchHelperAdapter {
    private val mItems: MutableList<String> =
        ArrayList()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
        val view =
            LayoutInflater.from(parent.context).inflate(R.layout.item_main, parent, false)
        return ItemViewHolder(view)
    }

    override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
        holder.textView!!.text = mItems[position]
    }

    override fun getItemCount(): Int {
        return mItems.size
    }

    companion object {
        private val STRINGS = arrayOf(
            "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"
        )
    }

    init {
        mItems.addAll(listOf(*STRINGS))
    }

    override fun onItemMove(fromPosition: Int, toPosition: Int) {
        if (fromPosition < toPosition) {
            for (i in fromPosition until toPosition) {
                Collections.swap(mItems, i, i + 1)
            }
        } else {
            for (i in fromPosition downTo toPosition + 1) {
                Collections.swap(mItems, i, i - 1)
            }
        }
        notifyItemMoved(fromPosition, toPosition)
    }

    override fun onItemDismiss(position: Int) {
        mItems.removeAt(position)
        notifyItemRemoved(position)
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment