1

My goal is to delete an item of a listView by sliding it with my finger on the side. I've tried to put onTouchListener on layout which is on the ViewHolder class. I have several problems :

  1. When i slide down or top with my finger, the list scroll, and the item keep his new position (it doesn't return to inital position)
  2. If the first problem occurs, when i scroll down the list, several items have the same position as the first one.
  3. If i succeed to slide the item to the limit i had defined, then the deleted item is not the good one all the time. In addition i have any alpha animation.
  4. With onTouchListener, my onItemClick listener not working anymore. (I want to color the background of selected list item).

Here is the overview of what I am trying to do :

list preview

Please see my code below :

My Custom List Adapter

public class VisiteAdapter extends ArrayAdapter<Visite> {

private Visite visite = null;
private float _xDelta;
private float initialXPos;
private float initialTouchXPos;
private boolean haveAlreadyCheckXPos = false;
private List listeVisite = null;

public VisiteAdapter(Context context, List<Visite> items) {
    super(context, R.layout.item_visite, items);
    listeVisite = items;
}



@Override
public View getView(final int position, View convertView, ViewGroup parent) {

    final ViewHolder viewHolder;
    visite = getItem(position);


    final View result;

    if (convertView == null) {
        viewHolder = new ViewHolder();
        LayoutInflater vi = LayoutInflater.from(getContext());
        convertView = vi.inflate(R.layout.item_visite, null);
        viewHolder.nomCopro = (TextView) convertView.findViewById(R.id.listeNomCopro);
        viewHolder.dateVisite = (TextView) convertView.findViewById(R.id.listDateVisite);
        viewHolder.itemLayout = (LinearLayout) convertView.findViewById(R.id.itemLayout);
        viewHolder.globalItem = (FrameLayout) convertView.findViewById(R.id.globalItem);

        //OnTouchListener on the first layer of my item
        viewHolder.itemLayout.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {

                int slideLimit = 150;

                switch (event.getAction()) {

                    case MotionEvent.ACTION_DOWN:

                        if(!haveAlreadyCheckXPos){
                            //get Initial X position of view.
                            initialXPos = v.getX();

                            haveAlreadyCheckXPos=true;
                        }

                        //initial X position of my finger when i touch the view
                        initialTouchXPos = event.getRawX();

                        //usefull value for translation
                        _xDelta = v.getX() - event.getRawX();

                        break;

                    case MotionEvent.ACTION_MOVE:

                        //Allow the view to slide to the left only. The view is blocked at a certain distance of the initial pos with the "slideLimit".
                        if(initialTouchXPos - event.getRawX() >= 0 && initialTouchXPos - event.getRawX() <= slideLimit){

                            //The sliding effect
                            v.animate()
                                    .x(event.getRawX() + _xDelta)
                                    .setDuration(0)
                                    .start();
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        //if the view is near to the slideLimit
                        if(initialXPos - v.getX() >= slideLimit-20){
                            //item is remove from the list with an alpha animation (alpha animation doesn't work)
                            viewHolder.globalItem.animate().alpha(0.0f).setDuration(350).start();
                            Log.e("ListeVisite.adapter"," ITEM DELETE");
                            listeVisite.remove(position);
                            notifyDataSetChanged();
                        }else{
                            //View return to the initial position
                            TranslateAnimation returnToInitialPos = new TranslateAnimation(0, initialXPos - v.getX(), 0, 0);
                            returnToInitialPos.setDuration(500);
                            returnToInitialPos.setFillAfter(true);
                            v.startAnimation(returnToInitialPos);
                        }

                        break;
                    default:
                        return false;
                }

                return true;
            }
        });

        result=convertView;
        convertView.setTag(viewHolder);
    }else{
        viewHolder = (ViewHolder) convertView.getTag();
        result=convertView;
    }


    if (viewHolder.nomCopro != null) {
        viewHolder.nomCopro.setText("CoproID : "+visite.getCOPRO_REF());
    }

    if (viewHolder.dateVisite != null) {
        viewHolder.dateVisite.setText(UsefulMethods.dateToString(visite.getV_DATE_VISITE(),"dd/MM/yyyy"));
    }

    //Selection of the item work with a boolean in the model. Look at the MainActivity class
    if(visite.isSelected){
        viewHolder.itemLayout.setBackgroundColor(ResourcesCompat.getColor(getContext().getResources(), R.color.colorPrimaryLight, null));
    }else{
        viewHolder.itemLayout.setBackgroundColor(ResourcesCompat.getColor(getContext().getResources(), R.color.white, null));
    }





    return convertView;
}
private static class ViewHolder {
    TextView nomCopro;
    TextView dateVisite;
    LinearLayout itemLayout;
    FrameLayout globalItem;
}

}

The listView in MainActivity

final ListView listViewVisite = (ListView) findViewById(R.id.visiteList);

    for(int i =0; i<25;i++ ){
        Visite visite1 = new Visite();
        visite1.setCOPRO_REF(i);
        visite1.setV_DATE_VISITE(UsefulMethods.stringToDate("15/06/2017", "dd/MM/yyyy"));
        listVisite.add(visite1);
    }

    visiteAdapter = new VisiteAdapter(MainActivity.this, listVisite);

    listViewVisite.setAdapter(visiteAdapter);

    listViewVisite.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            Log.e("ListeVisite","OnClick");



            for(Visite visiteTemp : listVisite){
                visiteTemp.isSelected=false;
            }
            Visite visite = (Visite) parent.getItemAtPosition(position);
            visite.isSelected = true;
            listVisite.set(position, visite);
            visiteAdapter.notifyDataSetChanged();

        }
    });

My list item Layout

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:animateLayoutChanges="true"
    android:id="@+id/globalItem"
    >
<!-- Red layer below the white layer -->
<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorAccent3"
    android:layout_marginTop="20dp"
    android:layout_marginLeft="20dp"
    android:layout_marginRight="20dp"
    android:gravity="center_vertical"
    >

    <View
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentRight="true"
        android:layout_marginRight="20dp"
        android:background="@drawable/ic_delete"
        />

</RelativeLayout>
<!-- Exposed layer -->
<LinearLayout
    android:id="@+id/itemLayout"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    android:padding="20dp"
    android:layout_marginTop="20dp"
    android:layout_marginLeft="20dp"
    android:layout_marginRight="20dp"
    android:focusableInTouchMode="true"
    android:focusable="true"
    android:clickable="true"
    >

    <TextView
        android:id="@+id/listeNomCopro"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Nom de la copropriété"
        android:textSize="20sp"
        />

    <TextView
        android:id="@+id/listDateVisite"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="15/06/2017"
        android:textSize="20sp"
        android:layout_marginTop="20dp"
        />

</LinearLayout>
</FrameLayout>

The listView

<ListView
        android:id="@+id/visiteList"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/lightGrey3"
        android:divider="@null"
        android:dividerHeight="0dp"
        android:listSelector="@android:color/transparent"
        android:animateLayoutChanges="true"

        >
</ListView>

Thanks for the help in advance !

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115

1 Answers1

0

try this code

   float historicX = Float.NaN, historicY = Float.NaN;
    static final int DELTA = 50;
    enum Direction {LEFT, RIGHT;}
   final ListView listViewVisite = (ListView) findViewById(R.id.visiteList);

    for(int i =0; i<25;i++ ){
        Visite visite1 = new Visite();
        visite1.setCOPRO_REF(i);
        visite1.setV_DATE_VISITE(UsefulMethods.stringToDate("15/06/2017", "dd/MM/yyyy"));
        listVisite.add(visite1);
    }

    visiteAdapter = new VisiteAdapter(MainActivity.this, listVisite);
    listViewVisite.setAdapter(visiteAdapter); 
    listViewVisite.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {

            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    historicX = event.getX();
                    historicY = event.getY();
                    break;

                case MotionEvent.ACTION_UP:
                    if (event.getX() - historicX < -DELTA) {

                      int pos = listViewVisite.pointToPosition((int) event.getX(), (int)event.getY());
                      listVisite.remove(pos);
                      visiteAdapter.notifyDataSetChanged();
                       // FunctionDeleteRowWhenSlidingLeft();
                        return true;
                    }
                    else if (event.getX() - historicX > DELTA) {
                      //  FunctionDeleteRowWhenSlidingRight();
                        return true;
                    }
                    break;

                default:
                    return false;
            }
            return false;
        }
    });
Jai Khambhayta
  • 4,198
  • 2
  • 22
  • 29