Scroll ListView item Right to left show delete button

I have a custom ListView showing a list of words fetched from a database. When I scroll through this list item, I want to show the Delete button, as shown below. And when I click this button, it is removed from the database and updates the list. t Swipe listview item

I already look in this example here . But it still does not work.

+68
android android-listview swipe-gesture
Dec 27 '13 at 8:02
source share
10 answers

EDIT: between the other options there is a good library that could solve your problem: https://github.com/daimajia/AndroidSwipeLayout

+36
Dec 27 '13 at 8:15
source share

I searched google many times and found a suitable project - swipmenulistview https://github.com/baoyongzhang/SwipeMenuListView on github.

+15
Dec 29 '15 at 6:10
source share

I had the same problem as finding a good library. In the end, I created a library that can do this: SwipeRevealLayout

In the gradle file:

dependencies { compile 'com.chauthai.swipereveallayout:swipe-reveal-layout:1.4.0' } 

In your xml file:

 <com.chauthai.swipereveallayout.SwipeRevealLayout android:layout_width="match_parent" android:layout_height="match_parent" app:mode="same_level" app:dragEdge="left"> <!-- Your secondary layout here --> <FrameLayout android:layout_width="wrap_content" android:layout_height="match_parent" /> <!-- Your main layout here --> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" /> </com.chauthai.swipereveallayout.SwipeRevealLayout> 

Then in the adapter file:

 public class Adapter extends RecyclerView.Adapter { // This object helps you save/restore the open/close state of each view private final ViewBinderHelper viewBinderHelper = new ViewBinderHelper(); @Override public void onBindViewHolder(ViewHolder holder, int position) { // get your data object first. YourDataObject dataObject = mDataSet.get(position); // Save/restore the open/close state. // You need to provide a String id which uniquely defines the data object. viewBinderHelper.bind(holder.swipeRevealLayout, dataObject.getId()); // do your regular binding stuff here } } 
+15
Apr 17 '16 at 13:22
source share

I created a demo on my github that includes scrolling from right to left, a delete button will appear, and you can remove your item from the ListView and update your ListView.

+10
Jan 17 '14 at 7:59
source share

I just got it working using ViewSwitcher in ListItem.

list_item.xml:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <ViewSwitcher android:id="@+id/list_switcher" android:layout_width="match_parent" android:layout_height="fill_parent" android:inAnimation="@android:anim/slide_in_left" android:outAnimation="@android:anim/slide_out_right" android:measureAllChildren="false" > <TextView android:id="@+id/tv_item_name" android:layout_width="match_parent" android:layout_height="50dp" android:layout_gravity="center_vertical" android:maxHeight="50dp" android:paddingLeft="10dp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:clickable="false" android:gravity="center" > <Button android:id="@+id/b_edit_in_list" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Edit" android:paddingLeft="20dp" android:paddingRight="20dp" /> <Button android:id="@+id/b_delete_in_list" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Delete" android:paddingLeft="20dp" android:paddingRight="20dp" android:background="@android:color/holo_red_dark" /> </LinearLayout> </ViewSwitcher> 

In the ListAdapter: Deploy OnclickListeners for the Edit and Delete button in the getView () method. The catch here is to get the ListItem position by clicking inside the onClick methods. For this, the setTag () and getTag () methods are used.

 @Override public View getView(final int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub final ViewHolder viewHolder; if (convertView == null) { viewHolder = new ViewHolder(); convertView = mInflater.inflate(R.layout.list_item, null); viewHolder.viewSwitcher=(ViewSwitcher)convertView.findViewById(R.id.list_switcher); viewHolder.itemName = (TextView) convertView .findViewById(R.id.tv_item_name); viewHolder.deleteitem=(Button)convertView.findViewById(R.id.b_delete_in_list); viewHolder.deleteItem.setTag(position); viewHolder.editItem=(Button)convertView.findViewById(R.id.b_edit_in_list); viewHolder.editItem.setTag(position); viewHolder.deleteItem.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub fragment.deleteItemList((Integer)v.getTag()); } }); viewHolder.editItem.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub fragment.editItemList(position); } }); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.itemName.setText(itemlist[position]); return convertView; } 

In the snippet, Add a gesture listener to detect Fling gestures:

 public class MyGestureListener extends SimpleOnGestureListener { private ListView list; public MyGestureListener(ListView list) { this.list = list; } // CONDITIONS ARE TYPICALLY VELOCITY OR DISTANCE @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // if (INSERT_CONDITIONS_HERE) ltor=(e2.getX()-e1.getX()>DELTA_X); if (showDeleteButton(e1)) { return true; } return super.onFling(e1, e2, velocityX, velocityY); } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // TODO Auto-generated method stub return super.onScroll(e1, e2, distanceX, distanceY); } private boolean showDeleteButton(MotionEvent e1) { int pos = list.pointToPosition((int) e1.getX(), (int) e1.getY()); return showDeleteButton(pos); } private boolean showDeleteButton(int pos) { View child = list.getChildAt(pos); if (child != null) { Button delete = (Button) child .findViewById(R.id.b_edit_in_list); ViewSwitcher viewSwitcher = (ViewSwitcher) child .findViewById(R.id.host_list_switcher); TextView hostName = (TextView) child .findViewById(R.id.tv_host_name); if (delete != null) { viewSwitcher.setInAnimation(AnimationUtils.loadAnimation(getActivity(), R.anim.slide_in_left)); viewSwitcher.setOutAnimation(AnimationUtils.loadAnimation(getActivity(), R.anim.slide_out_right)); } viewSwitcher.showNext(); // frameLayout.setVisibility(View.VISIBLE); } return true; } return false; } } 

In the onCreateView method of the fragment

 GestureDetector gestureDetector = new GestureDetector(getActivity(), new MyGestureListener(hostList)); hostList.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub if (gestureDetector.onTouchEvent(event)) { return true; } else { return false; } } }); 

It worked for me. Must clarify it more.

+5
Jun 18 '15 at 13:39 on
source share

See that the link was very nice and simple. its working fine ... u don't want any library working fine. click here

 OnTouchListener gestureListener = new View.OnTouchListener() { private int padding = 0; private int initialx = 0; private int currentx = 0; private ViewHolder viewHolder; public boolean onTouch(View v, MotionEvent event) { if ( event.getAction() == MotionEvent.ACTION_DOWN) { padding = 0; initialx = (int) event.getX(); currentx = (int) event.getX(); viewHolder = ((ViewHolder) v.getTag()); } if ( event.getAction() == MotionEvent.ACTION_MOVE) { currentx = (int) event.getX(); padding = currentx - initialx; } if ( event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { padding = 0; initialx = 0; currentx = 0; } if(viewHolder != null) { if(padding == 0) { v.setBackgroundColor(0xFF000000 ); if(viewHolder.running) v.setBackgroundColor(0xFF058805); } if(padding > 75) { viewHolder.running = true; v.setBackgroundColor(0xFF00FF00 ); viewHolder.icon.setImageResource(R.drawable.clock_running); } if(padding < -75) { viewHolder.running = false; v.setBackgroundColor(0xFFFF0000 ); } v.setPadding(padding, 0,0, 0); } return true; } }; 
+3
Jan 17 '14 at 7:49
source share

An application is available that demonstrates a list that combines both drag and drop and reordering items. The code is based on the Chet Haase code for scrolling to delete and the Daniel Olshansky code for dragging in order.

Even code removes the item immediately. I improved this by making it look more like Gmail, where swiping shows a bottom view that indicates that the item has been deleted, but provides a cancel button where the user has the option to cancel the deletion. Even code also has an error. If there are fewer items in the list than the height of the list, and you delete the last item, the last item is not deleted. This has been fixed in my code.

Daniel code requires a long press on an item Many users find this unintuitive as it tends to be a hidden feature. Instead, I changed the code to enable the Move button. You just click on the button and drag the item. This is more consistent with how the Google News application works when you reorder the news.

The source code along with the demo application is available at: https://github.com/JohannBlake/ListViewOrderAndSwipe

Chet and Daniel are both from Google.

An even video on deleting items can be viewed at: https://www.youtube.com/watch?v=YCHNAi9kJI4

Daniel’s reordering video can be viewed at: https://www.youtube.com/watch?v=_BZIvjMgH-Q

Much of the work went into gluing all this together to provide a quiet user interface experience, so I will be grateful for the “Like” or “Up Vote”. Please also run the project on Github.

+2
Jul 10 '15 at 1:28
source share

Define ViewPager in your .xml layout:

 <android.support.v4.view.ViewPager android:id="@+id/example_pager" android:layout_width="fill_parent" android:layout_height="@dimen/abc_action_bar_default_height" /> 

And then in your activity / snippet install a custom pager adapter:

In action:

 protected void onCreate(Bundle savedInstanceState) { PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager()); ViewPager pager = (ViewPager) findViewById(R.id.example_pager); pager.setAdapter(adapter); // pager.setOnPageChangeListener(this); // You can set a page listener here pager.setCurrentItem(0); } 

In the fragment:

 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_layout, container, false); if (view != null) { PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager()); ViewPager pager = (ViewPager) view.findViewById(R.id.example_pager); pager.setAdapter(adapter); // pager.setOnPageChangeListener(this); // You can set a page listener here pager.setCurrentItem(0); } return view; } 

Create our custom pager class:

 // setup your PagerAdapter which extends FragmentPagerAdapter class PagerAdapter extends FragmentPagerAdapter { public static final int NUM_PAGES = 2; private CustomFragment[] mFragments = new CustomFragment[NUM_PAGES]; public PagerAdapter(FragmentManager fragmentManager) { super(fragmentManager); } @ Override public int getCount() { return NUM_PAGES; } @ Override public Fragment getItem(int position) { if (mFragments[position] == null) { // this calls the newInstance from when you setup the ListFragment mFragments[position] = new CustomFragment(); } return mFragments[position]; } } 
+1
May 26 '14 at 7:40
source share

It is a waste of time to implement this functionality from scratch. I have implemented the library recommended by SalutonMondo and I am very satisfied. It is very easy to use and very fast. I improved the source library and I added a new click for the click element. I also added the awesome library font ( http://fortawesome.imtqy.com/Font-Awesome/ ), and now you can simply add a new element title and specify the icon name from the awesome font.

Here is the github link

+1
Jan 23 '15 at 10:18
source share

I spent tons of third-party libraries to try and achieve this. But none of them demonstrate the smoothness and usability that I wanted. Then I decided to write it myself. And the result was, well, I liked it. I will share the code here. Perhaps I will write it as a library that can be built into any kind of recycler in the future. But now here is the code.

Note. I have a view recycler and ViewHolder. Some values ​​are hardcoded, so modify them to suit your requirements.

  • row_layout.xml

     <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:orientation="horizontal"> <Button android:id="@+id/slide_button_2" android:text="Button2" android:layout_width="80dp" android:layout_height="80dp" /> <Button android:id="@+id/slide_button_1" android:text="Button1" android:layout_width="80dp" android:layout_height="80dp" /> </LinearLayout> <LinearLayout android:id="@+id/chat_row_cell" android:layout_width="match_parent" android:layout_height="80dp" android:orientation="horizontal" android:background="@color/white"> <ImageView android:id="@+id/chat_image" android:layout_width="60dp" android:layout_height="60dp" android:layout_marginLeft="10dp" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:layout_marginRight="10dp" android:layout_gravity="center"/> <LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/chat_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@color/md_grey_800" android:textSize="18sp"/> <TextView android:id="@+id/chat_subtitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@color/md_grey_600"/> </LinearLayout> </LinearLayout> </LinearLayout> 

  • ChatAdaptor.java

    Public class ChatAdaptor extends RecyclerView.Adapter {

     List<MXGroupChatSession> sessions; Context context; ChatAdaptorInterface listener; public interface ChatAdaptorInterface{ void cellClicked(MXGroupChatSession session); void utilityButton1Clicked(MXGroupChatSession session); void utilityButton2Clicked(MXGroupChatSession session); } public ChatAdaptor(List<MXGroupChatSession> sessions, ChatAdaptorInterface listener, Context context){ this.sessions=sessions; this.context=context; this.listener=listener; } @Override public ChatViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view=(View)LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_row,null); ChatViewHolder chatViewHolder=new ChatViewHolder(view); return chatViewHolder; } @Override public void onBindViewHolder(ChatViewHolder holder, final int position) { MXGroupChatSession session=this.sessions.get(position); holder.selectedSession=session; holder.titleView.setText(session.getTopic()); holder.subtitleView.setText(session.getLastFeedContent()); Picasso.with(context).load(new File(session.getCoverImagePath())).transform(new CircleTransformPicasso()).into(holder.imageView); } @Override public int getItemCount() { return sessions.size(); } public class ChatViewHolder extends RecyclerView.ViewHolder{ ImageView imageView; TextView titleView; TextView subtitleView; ViewGroup cell; ViewGroup cellContainer; Button button1; Button button2; MXGroupChatSession selectedSession; private GestureDetectorCompat gestureDetector; float totalx; float buttonTotalWidth; Boolean open=false; Boolean isScrolling=false; public ChatViewHolder(View itemView) { super(itemView); cell=(ViewGroup) itemView.findViewById(R.id.chat_row_cell); cellContainer=(ViewGroup) itemView.findViewById(R.id.chat_row_container); button1=(Button) itemView.findViewById(R.id.slide_button_1); button2=(Button) itemView.findViewById(R.id.slide_button_2); button1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { listener.utilityButton1Clicked(selectedSession); } }); button2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { listener.utilityButton2Clicked(selectedSession); } }); ViewTreeObserver vto = cellContainer.getViewTreeObserver(); vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { buttonTotalWidth = button1.getWidth()+button2.getWidth(); } }); this.titleView=(TextView)itemView.findViewById(R.id.chat_title); subtitleView=(TextView)itemView.findViewById(R.id.chat_subtitle); imageView=(ImageView)itemView.findViewById(R.id.chat_image); gestureDetector=new GestureDetectorCompat(context,new ChatRowGesture()); cell.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if(gestureDetector.onTouchEvent(event)){ return true; } if(event.getAction() == MotionEvent.ACTION_UP) { if(isScrolling ) { isScrolling = false; handleScrollFinished(); }; } else if(event.getAction() == MotionEvent.ACTION_CANCEL){ if(isScrolling ) { isScrolling = false; handleScrollFinished(); }; } return false; } }); } public class ChatRowGesture extends GestureDetector.SimpleOnGestureListener { @Override public boolean onSingleTapUp(MotionEvent e) { if (!open){ listener.cellClicked(selectedSession); } return true; } @Override public boolean onDown(MotionEvent e) { return true; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { isScrolling=true; totalx=totalx+distanceX; freescroll(totalx); return true; } } void handleScrollFinished(){ if (open){ if (totalx>2*buttonTotalWidth/3){ slideLeft(); totalx=buttonTotalWidth; }else{ slideRight(); totalx=0; } }else{ if (totalx>buttonTotalWidth/3){ slideLeft(); totalx=buttonTotalWidth; }else{ slideRight(); totalx=0; } } } void slideRight(){ TransitionManager.beginDelayedTransition(cellContainer); ViewGroup.MarginLayoutParams params; params=(ViewGroup.MarginLayoutParams) cell.getLayoutParams(); params.setMargins(0,0,0,0); cell.setLayoutParams(params); open=false; } void slideLeft(){ TransitionManager.beginDelayedTransition(cellContainer); ViewGroup.MarginLayoutParams params; params=(ViewGroup.MarginLayoutParams) cell.getLayoutParams(); params.setMargins(((int)buttonTotalWidth*-1),0,(int)buttonTotalWidth,0); cell.setLayoutParams(params); open=true; } void freescroll(float x){ if (x<buttonTotalWidth && x>0){ int xint=(int)x; ViewGroup.MarginLayoutParams params; params=(ViewGroup.MarginLayoutParams) cell.getLayoutParams(); params.setMargins(params.leftMargin,0,xint,0); cell.setLayoutParams(params); } } } 

Hope this helps someone!

+1
Feb 02 '17 at 12:06 on
source share



All Articles