Drag And Drop in ListView similar native Android Music App

Tutorials with advanced 'difficulty' and more Lines of Code.

Drag And Drop in ListView similar native Android Music App

Postby McArthur » Thu Jun 10, 2010 3:11 pm

Hi to all

Let me introduce my solution to DnD in ListView

1. Create any class that describe anything:

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. public class Entry {
  2.        
  3.         private String name = "Empty entry";
  4.        
  5.         public String getName() {
  6.                 return name;
  7.         }
  8.        
  9.         public void setName(String name) {
  10.                 this.name = name;
  11.         }
  12.  
  13. }
  14.  
Parsed in 0.031 seconds, using GeSHi 1.0.8.4


2. Create custom ListView

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. import java.util.ArrayList;
  2.  
  3.  
  4. import android.content.Context;
  5. import android.graphics.Color;
  6. import android.util.AttributeSet;
  7. import android.util.Log;
  8. import android.view.LayoutInflater;
  9. import android.view.MotionEvent;
  10. import android.view.View;
  11. import android.widget.AbsListView;
  12. import android.widget.AbsoluteLayout;
  13. import android.widget.AdapterView;
  14. import android.widget.ImageView;
  15. import android.widget.ListView;
  16. import android.widget.ScrollView;
  17. import android.widget.TextView;
  18. import android.widget.AbsListView.LayoutParams;
  19.  
  20. public class DnDListView extends ListView {
  21.        
  22.         public View moveView = null;
  23.         private Context context = null;
  24.         public int movedPosition = 0;
  25.         public Entry moveEntry = null;
  26.        
  27.         public boolean isMoveFlag = false;
  28.         private int firstPosition;
  29.         private int lasPosition;
  30.         private ArrayList<com.epam.dnd.DnDListView.Coordinates> listCoordinates; // list for top/bottom coordinates of visible list items
  31.        
  32.         public DnDListView(Context context) {
  33.                 super(context);
  34.                 // TODO Auto-generated constructor stub
  35.                 this.context = context;
  36.                 setVerticalScrollBarEnabled(false);  // scroll bar doesn't shown in view
  37.         }
  38.  
  39.         public DnDListView(Context context, AttributeSet attrs) {
  40.                 super(context, attrs);
  41.                 // TODO Auto-generated constructor stub
  42.                 this.context = context;
  43.                 setVerticalScrollBarEnabled(false);
  44.  
  45.         }
  46.        
  47.        
  48.  
  49.        
  50.         @Override
  51.         public boolean onTouchEvent(MotionEvent ev) {
  52.                 // TODO Auto-generated method stub
  53.                 if (isMoveFlag) {
  54.                         switch (ev.getAction()) {
  55.                         case MotionEvent.ACTION_DOWN:
  56.                                 Log.v(getClass().toString(),"action_dowm");
  57.                                 int y = (int)ev.getY();
  58.                                 if (getParent() instanceof AbsoluteLayout) {
  59.                                         AbsoluteLayout parent = (AbsoluteLayout)getParent();
  60.                                         if (moveView != null) {
  61.                                                 parent.removeView(DnDAdapter.emptyView);
  62.                                                 parent.addView(DnDAdapter.emptyView, new AbsoluteLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, 0, y - 22)); // 22 - you can set any number
  63.                                                
  64.                                         }
  65.                                 }
  66.                                 break;
  67.                         case MotionEvent.ACTION_MOVE:
  68.                                 Log.v(getClass().toString(),"action_move");
  69.                                 int yMove = (int)ev.getY();
  70.                                 if (getParent() instanceof AbsoluteLayout) {
  71.                                         AbsoluteLayout parent = (AbsoluteLayout)getParent();
  72.                                         if (moveView != null) {
  73.                                                 parent.removeView(DnDAdapter.emptyView);
  74.                                                 parent.addView(DnDAdapter.emptyView, new AbsoluteLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, 0, yMove - 22));
  75.                                                 inChild(MotionEvent.ACTION_MOVE);
  76.                                         }
  77.                                 }
  78.                                 break;
  79.                         case MotionEvent.ACTION_UP:
  80.                                 if (getParent() instanceof AbsoluteLayout) {
  81.                                         AbsoluteLayout parent = (AbsoluteLayout)getParent();
  82.                                         if (moveView != null) {
  83.                                                 parent.removeView(DnDAdapter.emptyView);
  84.                                                 inChild(MotionEvent.ACTION_UP);
  85. //                                              DnDAdapter.addEntry(movedPosition);
  86.                                         }
  87.                                 }
  88.                                 isMoveFlag = false;
  89.                                 setEnabled(true);
  90.                                 Log.v(getClass().toString(),"action_up: " + isMoveFlag);
  91.                                 break;
  92.                         default:
  93.                                 break;
  94.                 }
  95.                 }
  96.                 return super.onTouchEvent(ev);
  97.         }
  98.        
  99.         @Override
  100.         public void setOnScrollListener(OnScrollListener l) {
  101.                 // TODO Auto-generated method stub
  102.                 l = new OnScrollListener() {
  103.                        
  104.                         @Override
  105.                         public void onScrollStateChanged(AbsListView view, int scrollState) {
  106.                                 // TODO Auto-generated method stub
  107.                                         firstPosition = getFirstVisiblePosition();
  108.                                         lasPosition = getLastVisiblePosition();
  109.                         }
  110.                        
  111.                         @Override
  112.                         public void onScroll(AbsListView view, int firstVisibleItem,
  113.                                         int visibleItemCount, int totalItemCount) {
  114.                                 // TODO Auto-generated method stub
  115.                                
  116.                         }
  117.                 };
  118.                 super.setOnScrollListener(l);
  119.         }
  120.        
  121.         private void inChild(int action) {
  122.                 setCoordinates();
  123.                 for (int i = 0; i < listCoordinates.size(); i++) {
  124.                         Coordinates coordinates = listCoordinates.get(i);
  125.                         int topPosition = coordinates.getTop();
  126.                         int bottomPosition = coordinates.getBottom();
  127.                         int bottomMoveViewPosition = DnDAdapter.emptyView.getBottom();
  128.                         if (i != 0) {
  129.                                 if (bottomMoveViewPosition > topPosition && bottomMoveViewPosition < bottomPosition) {
  130.                                         Log.v(getClass().toString(),"Move view in position: " + i);
  131.                                         DnDAdapter.removeEmptyEntry();
  132.                                         DnDAdapter.addEmptyEntry(getFirstVisiblePosition() + i);
  133.                                         if (action == MotionEvent.ACTION_UP) {
  134.                                                 DnDAdapter.removeEmptyEntry();
  135.                                                 DnDAdapter.addEntry(getFirstVisiblePosition() + i);
  136.                                         }
  137.                                 }
  138.                         }
  139.                 }
  140.         }
  141.        
  142.         private void setCoordinates() {
  143.                 listCoordinates = new ArrayList<Coordinates>();
  144.                 int count = getChildCount();
  145.                 for (int i = 0; i < count; i++) {
  146.                         View child = getChildAt(i);
  147.                         if (child != null) {
  148.                                 Coordinates coord = new Coordinates();
  149.                                 coord.setTop(child.getTop());
  150.                                 coord.setBottom(child.getBottom());
  151.                                 listCoordinates.add(coord);
  152.                         }
  153.                 }
  154.         }
  155.        
  156.        
  157.        
  158.         class Coordinates {
  159.                
  160.                 private int top = 0;
  161.                 private int bottom = 0;
  162.                
  163.                 public int getTop() {
  164.                         return top;
  165.                 }
  166.                 public void setTop(int top) {
  167.                         this.top = top;
  168.                 }
  169.                 public int getBottom() {
  170.                         return bottom;
  171.                 }
  172.                 public void setBottom(int bottom) {
  173.                         this.bottom = bottom;
  174.                 }
  175.                
  176.                
  177.         }
  178.  
  179. }
  180.  
Parsed in 0.051 seconds, using GeSHi 1.0.8.4


3. Create custom adapter for your ListView

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. package com.myself.dnd;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5.  
  6. import com.myself.dnd.R;
  7.  
  8. import android.content.Context;
  9. import android.graphics.Color;
  10. import android.util.Log;
  11. import android.view.LayoutInflater;
  12. import android.view.MotionEvent;
  13. import android.view.View;
  14. import android.view.ViewGroup;
  15. import android.view.View.OnTouchListener;
  16. import android.widget.BaseAdapter;
  17. import android.widget.ImageView;
  18. import android.widget.LinearLayout;
  19. import android.widget.TextView;
  20.  
  21. public class DnDAdapter extends BaseAdapter {
  22.        
  23.         private static List<Entry> items = null;
  24.         private Context context = null;
  25.        
  26.         public static View emptyView = null;
  27.        
  28.         private static Entry emptyEntry = new Entry();
  29.        
  30.         public DnDAdapter(Context context) {
  31.                 // TODO Auto-generated constructor stub
  32.                 this.context = context;
  33. //              buildList();
  34.         }
  35.        
  36.        
  37.        
  38.         public List<Entry> getItems() {
  39.                 return items;
  40.         }
  41.        
  42.         public void setList(List<Entry> items) {
  43.                 this.items = items;
  44.         }
  45.  
  46.         @Override
  47.         public int getCount() {
  48.                 // TODO Auto-generated method stub
  49.                 return items.size();
  50.         }
  51.  
  52.         @Override
  53.         public Object getItem(int position) {
  54.                 // TODO Auto-generated method stub
  55.                 return items.get(position);
  56.         }
  57.  
  58.         @Override
  59.         public long getItemId(int position) {
  60.                 // TODO Auto-generated method stub
  61.                 return 0;
  62.         }
  63.  
  64.         @Override
  65.         public View getView(final int position, View convertView, ViewGroup parent) {
  66.                 // TODO Auto-generated method stub
  67.                 Entry entry = items.get(position);
  68.                 LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  69.                 final View view = inflater.inflate(R.layout.listitem, parent, false);
  70.                 TextView txt = (TextView)view.findViewById(R.id.TextView01);
  71.                 txt.setText(entry.getName());
  72.                 txt.setTextColor(Color.WHITE);
  73.                 final ImageView img = (ImageView)view.findViewById(R.id.entryIcon);
  74.                 img.setOnTouchListener(new OnTouchListener() {
  75.                        
  76.                         @Override
  77.                         public boolean onTouch(View v, MotionEvent event) {
  78.                                 // TODO Auto-generated method stub
  79.                                 Log.v(getClass().toString(),"Icon onTouch. Selected position: " + position);
  80.                                
  81.                                 DragAndDrop.listView.moveEntry = items.get(position);
  82.                                 buildEmptyView(DragAndDrop.listView.moveEntry);
  83.                                 items.remove(position);
  84.                                 items.add(position, emptyEntry);
  85.                                 DragAndDrop.listView.invalidateViews();
  86.                                 DragAndDrop.listView.setEnabled(false);
  87.                                 DragAndDrop.listView.isMoveFlag = true;
  88.                                 DragAndDrop.listView.moveView = view;
  89.                                 DragAndDrop.listView.movedPosition = position;
  90.                                 return false;
  91.                         }
  92.                 });
  93.                 if (entry.getName().equals("Empty entry")) {
  94.                         img.setVisibility(View.INVISIBLE);
  95.                         txt.setVisibility(View.INVISIBLE);
  96.                 }
  97.                 return view;
  98.         }
  99.  
  100.         private void buildEmptyView(Entry moveentry) {
  101.                 LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  102.                 emptyView = inflater.inflate(R.layout.emptyview, null, false);
  103.                 TextView txt = (TextView)emptyView.findViewById(R.id.TextView01);
  104.                 txt.setText(moveentry.getName());
  105.                 txt.setTextColor(Color.WHITE);
  106.         }
  107.        
  108.         public static void addEntry(int pos) {
  109.                 items.add(pos, DragAndDrop.listView.moveEntry);
  110.                 DragAndDrop.listView.invalidateViews();
  111.         }
  112.        
  113.         public static void addEmptyEntry(int pos) {
  114.                 items.add(pos, emptyEntry);
  115.                 DragAndDrop.listView.invalidateViews();
  116.         }
  117.        
  118.         public static void removeEmptyEntry() {
  119.                 items.remove(emptyEntry);
  120.                 DragAndDrop.listView.invalidateViews();
  121.         }
  122. }
  123.  
Parsed in 0.047 seconds, using GeSHi 1.0.8.4


4. Main activity

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. package com.myself.dnd;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5.  
  6. import com.myself.dnd.R;
  7.  
  8.  
  9. import android.app.Activity;
  10. import android.app.ListActivity;
  11. import android.content.Context;
  12. import android.os.Bundle;
  13. import android.view.LayoutInflater;
  14. import android.view.View;
  15. import android.widget.Button;
  16. import android.widget.LinearLayout;
  17. import android.widget.ScrollView;
  18. import android.widget.TextView;
  19.  
  20.  
  21. public class DragAndDrop extends ListActivity {
  22.     /** Called when the activity is first created. */
  23.        
  24.        
  25.         public static LinearLayout layout = null;
  26.         public static ScrollView scrollView = null;
  27.         public static DnDListView listView = null;
  28.     @Override
  29.     public void onCreate(Bundle savedInstanceState) {
  30.         super.onCreate(savedInstanceState);
  31.         setContentView(R.layout.main);
  32.        
  33.         DnDAdapter adapter = new DnDAdapter(this);
  34.         adapter.setList(buildList());
  35.         listView = (DnDListView)getListView();
  36.         listView.setAdapter(adapter);
  37.        
  38.     }
  39.    
  40.     private List<Entry> buildList() {
  41.                 List<Entry> items = new ArrayList<Entry>();
  42.                 for (int i = 0; i < 30; i++) {
  43.                         Entry entry = new Entry();
  44.                         entry.setName("Demo entry " + i);
  45.                         items.add(entry);
  46.                 }
  47.                 return items;
  48.         }
  49.    
  50.    
  51. }
  52.  
Parsed in 0.040 seconds, using GeSHi 1.0.8.4


4. Add to main.xml tags of your custom class

Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <AbsoluteLayout android:id="@+id/mainAbsoluteLayout" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android">
  3. <com.myself.dnd.DnDListView
  4.         android:id="@+id/android:list"
  5.         android:layout_width="fill_parent"
  6.    android:layout_height="fill_parent">
  7. </com.myself.dnd.DnDListView>
  8.  
  9. </AbsoluteLayout>
  10.  
Parsed in 0.002 seconds, using GeSHi 1.0.8.4


P.S. Sorry for my English =) If you have any questions, do not hesitate to ask =)
Attachments
DnDList.zip
(64.82 KiB) Downloaded 2238 times
McArthur
Once Poster
Once Poster
 
Posts: 1
Joined: Tue Apr 27, 2010 4:04 pm

Top

Re: Drag And Drop in ListView similar native Android Music A

Postby sunkillen » Sat Jun 12, 2010 8:16 am

This is very helpful. Thank you :)
sunkillen
Freshman
Freshman
 
Posts: 3
Joined: Tue Jun 24, 2008 8:58 am

Re: Drag And Drop in ListView similar native Android Music A

Postby alexandrefett » Sat Jul 24, 2010 5:56 am

Hi,

I have some problems. Some times when move listitem is not created, is blank.
when I move out off listview bounds, item moved is removed and fill blank.

Any solution?

thanks
Alexandre
alexandrefett
Freshman
Freshman
 
Posts: 2
Joined: Fri Apr 03, 2009 3:05 pm

Re: Drag And Drop in ListView similar native Android Music A

Postby amIT29 » Wed Aug 11, 2010 12:01 pm

hi i have tried to implement this on emulator but is it crashing every time..im using version 1.6

any suggestion??
amIT29
Freshman
Freshman
 
Posts: 6
Joined: Wed Aug 11, 2010 12:01 pm

Re: Drag And Drop in ListView similar native Android Music A

Postby amIT29 » Wed Aug 11, 2010 1:00 pm

they app crashes while trying to setcontentview in DragAndDrop.java file ...apprantely i think @id/android:list is the culprit for this as R.id as no entry for this ..hence it crashes..i think
"McArthur" has forgot to include some xml probably...

I may be wrong but this what i think the problem is with this .....any help to fix this problem wud be very much appreciatated. :)

thank you
amIT29
amIT29
Freshman
Freshman
 
Posts: 6
Joined: Wed Aug 11, 2010 12:01 pm

Re: Drag And Drop in ListView similar native Android Music A

Postby amIT29 » Wed Aug 11, 2010 3:07 pm

there were some nulls check errors and listitem.xml had to changed ..mostly all null pointer errors...now it is working just fine..

thanks..

i will now move the code to phone .
thanks a lot
amIT29
Freshman
Freshman
 
Posts: 6
Joined: Wed Aug 11, 2010 12:01 pm

Top

Re: Drag And Drop in ListView similar native Android Music A

Postby amIT29 » Mon Aug 16, 2010 9:39 am

the "inChild" method of dndlistview has a flaw which doesn't work if we drag a entry beyond the list view and release...

in such case the if case doesnt get hit and " move entry" is not added...
to over come this we shud a check that if bottom of the emptyiew is more than that of last entry then add entry explictly ..same can be done for drag to the top of list which doesnt work in the current code.
amIT29
Freshman
Freshman
 
Posts: 6
Joined: Wed Aug 11, 2010 12:01 pm

Re: Drag And Drop in ListView similar native Android Music A

Postby Mr_Tremor » Thu Sep 02, 2010 5:17 pm

Thanks for the Tutorial I will check it out when I get a chance. But just as an FYI when you are coding your custom list adapter you should be using the convertView if it is non-null. Otherwise you are not efficiently using a ListView.

public View getView(final int position, View convertView, ViewGroup parent)
ImagemyExpensePal
Great tool for managing your budget, tracks expenses and accounts.
Mr_Tremor
Developer
Developer
 
Posts: 26
Joined: Tue Jun 02, 2009 6:35 pm

Re: Drag And Drop in ListView similar native Android Music A

Postby ericharlow » Mon Oct 11, 2010 8:03 pm

I downloaded the source. Fixed compile errors. Ran the app on a device, and i can't drag-n-drop items in the list. Has anyone else ran into this?
ericharlow
Freshman
Freshman
 
Posts: 4
Joined: Fri Sep 24, 2010 5:05 pm

Re: Drag And Drop in ListView similar native Android Music A

Postby ericharlow » Fri Oct 29, 2010 9:48 pm

I created a simple Drag and Drop List that should be easy to extend. Check it out here.
ericharlow
Freshman
Freshman
 
Posts: 4
Joined: Fri Sep 24, 2010 5:05 pm

Top

Return to Advanced Tutorials

Who is online

Users browsing this forum: No registered users and 6 guests