Android ListView Swipe Right and Left to Accept and Reject

前端 未结 6 1152
遥遥无期
遥遥无期 2020-12-05 11:37

I want to develop a list view that when swiped left to right - displays in the left corner an accept (true) icon (non clickable - show just a color change when swiping left

相关标签:
6条回答
  • 2020-12-05 12:05

    It worked for me... I hope it will work for you..!

    set OnTouchListener to listview as

    listview.setOnTouchListener(new OnSwipeTouchListener(getActivity(),
                listview));
    

    The OnSwipeTouchListener class is as follows:

    public class OnSwipeTouchListener implements OnTouchListener {
    
        ListView list;
        private GestureDetector gestureDetector;
        private Context context;
    
        public OnSwipeTouchListener(Context ctx, ListView list) {
            gestureDetector = new GestureDetector(ctx, new GestureListener());
            context = ctx;
            this.list = list;
        }
    
        public OnSwipeTouchListener() {
            super();
        }
    
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return gestureDetector.onTouchEvent(event);
        }
    
        public void onSwipeRight(int pos) {
            //Do what you want after swiping left to right
    
        }
    
        public void onSwipeLeft(int pos) {
    
            //Do what you want after swiping right to left
        }
    
        private final class GestureListener extends SimpleOnGestureListener {
    
            private static final int SWIPE_THRESHOLD = 100;
            private static final int SWIPE_VELOCITY_THRESHOLD = 100;
    
            @Override
            public boolean onDown(MotionEvent e) {
                return true;
            }
    
            private int getPostion(MotionEvent e1) {
                return list.pointToPosition((int) e1.getX(), (int) e1.getY());
            }
    
            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2,
                    float velocityX, float velocityY) {
                float distanceX = e2.getX() - e1.getX();
                float distanceY = e2.getY() - e1.getY();
                if (Math.abs(distanceX) > Math.abs(distanceY)
                        && Math.abs(distanceX) > SWIPE_THRESHOLD
                        && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                    if (distanceX > 0)
                        onSwipeRight(getPostion(e1));
                    else
                        onSwipeLeft(getPostion(e1));
                    return true;
                }
                return false;
            }
    
        }
    }
    
    0 讨论(0)
  • 2020-12-05 12:07

    Using an answer at https://stackoverflow.com/a/31094315/2914140 I made it so.

    View.OnTouchListener swipeListener = new View.OnTouchListener() {
        private float dx;
    
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    dx = v.getX() - event.getRawX();
                    break;
                case MotionEvent.ACTION_MOVE:
                    // You can limit x-coordinate.
                    float x = Math.min(event.getRawX() + dx, 0);
                    // x = Math.max(x, ((View) v.getParent()).getWidth() - v.getWidth()); // Scroll if layout is wider than screen.
                    v.animate()
                            .x(x)
                            .setDuration(0)
                            .start();
                    break;
                default:
                    return false;
            }
            return true;
        }
    };
    

    In getView of your adapter write:

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        final ViewHolder viewHolder;
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.item_layout, false);
            viewHolder = new ViewHolder(convertView);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }
    
        // Fill data.
        final Item item = items.get(position);
        viewHolder.caption.setText(item.getCaption());
        // Set onTouch listener.
        convertView.setOnTouchListener(swipeListener);
        return convertView;
    }
    

    I think the same can be achieved by using HorizontalScrollView inside item_layout.xml.

    0 讨论(0)
  • 2020-12-05 12:08

    Take a look at this library, it will give u very good examples and will point u to the right direction. Good luck.

    0 讨论(0)
  • 2020-12-05 12:08

    Please avoid above approach otherwise you are going to full fill controller with view logic (something you have to avoid) visit https://github.com/xenione/SwipeLayout there is a swipe maker with some examples

    0 讨论(0)
  • 2020-12-05 12:10

    Solution number 1 :

    You Have to do like following to reach "near" to your functionality,

    Wrap the adapter of your ListView

    Like following :

      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        // Create an Adapter for your content
        String[] content = new String[20];
        for (int i=0;i<20;i++) content[i] = "Row "+(i+1);
        ArrayAdapter<String> stringAdapter = new ArrayAdapter<String>(
            this,
            R.layout.row_bg,
            R.id.text,
            new ArrayList<String>(Arrays.asList(content))
        );
    
       // Wrap your content in a SwipeActionAdapter
       mAdapter = new SwipeActionAdapter(stringAdapter);
    
       // Pass a reference of your ListView to the SwipeActionAdapter
       mAdapter.setListView(getListView());
    
       // Set the SwipeActionAdapter as the Adapter for your ListView
       setListAdapter(mAdapter);
      }
    

    Create a background layout for each swipe direction

    Like Following:

      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
       // Create an Adapter for your content
       String[] content = new String[20];
       for (int i=0;i<20;i++) content[i] = "Row "+(i+1);
       ArrayAdapter<String> stringAdapter = new ArrayAdapter<String>(
            this,
            R.layout.row_bg,
            R.id.text,
            new ArrayList<String>(Arrays.asList(content))
       );
    
       // Wrap your content in a SwipeActionAdapter
       mAdapter = new SwipeActionAdapter(stringAdapter);
    
       // Pass a reference of your ListView to the SwipeActionAdapter
       mAdapter.setListView(getListView());
    
       // Set the SwipeActionAdapter as the Adapter for your ListView
       setListAdapter(mAdapter);
    
       // Set backgrounds for the swipe directions
        mAdapter.addBackground(SwipeDirections.DIRECTION_FAR_LEFT,R.layout.row_bg_left_far)
              .addBackground(SwipeDirections.DIRECTION_NORMAL_LEFT,R.layout.row_bg_left)
             .addBackground(SwipeDirections.DIRECTION_FAR_RIGHT,R.layout.row_bg_right_far)
            .addBackground(SwipeDirections.DIRECTION_NORMAL_RIGHT,R.layout.row_bg_right);
    }
    

    You got both libraries and Example from the here : https://github.com/wdullaer/SwipeActionAdapter

    This will not exact like you want, but i hope this will help you so much to fulfilled your functionality.

    Solution number 2 :

    Solution 2 is about Changing some code in your Used code : http://www.tutecentral.com/android-swipe-listview/

    i had try your code from the link http://www.tutecentral.com/android-swipe-listview/ and changing some code and successfully solve your problem(your confusion) about onOpened(..) method ( called left to right and vice versa )

    First change :

    1. custom_row.xml layout file has three button swipe_button1 to 3 , remove middle of them.

    2. Copy paste following code for remain two button :

      <Button
          android:id="@+id/swipe_button1"
          android:layout_width="48dp"
          android:layout_height="48dp"
          android:layout_alignParentLeft="true"
          android:layout_alignParentTop="true"
          android:background="@drawable/your_accept_image" />
      
      <Button
          android:id="@+id/swipe_button3"
          style="@style/MyListButtonAction"
          android:layout_width="48dp"
          android:layout_height="48dp"
          android:layout_alignParentRight="true"
          android:layout_alignParentTop="true"
          android:background="@drawable/your_reject_image" />
      

    Remains code same for this layout.

    Second change :

    So now your accept and reject and list code is ready , now discuss about onOpened(..) method.

    Confusion solution 1- You told , your onOpend(...) method called same both left to right and vice-verse

    -> just to change following :

    public void onOpened(int position, boolean toRight) {
    
                if(toRight)
                {
    
                    //  for left to right your api calling here
                    swipelistview.closeAnimate(position);
                }
                else
                {
                    // for right to left your api calling here
                    swipelistview.closeAnimate(position);
                }
    
    
            }
    

    Confusion solution 2 when i take finger up it will must display entire listview or listview sides should retain it corners so its not working

    -> i already answered it in above

    called swipelistview.closeAnimate(position); in both if else, it hide left accept and right reject image when your your swipe left and right over.

    So final code is following :

    Entire cutom_row.xml layout

     <?xml version="1.0" encoding="utf-8"?>
     <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="fill_parent"
         android:layout_height="fill_parent" >
    
      <RelativeLayout
        android:id="@+id/back"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:tag="back" >
    
        <Button
            android:id="@+id/swipe_button1"
            android:layout_width="48dp"
            android:layout_height="48dp"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:background="@drawable/accept_image" />
    
        <Button
            android:id="@+id/swipe_button3"
            style="@style/MyListButtonAction"
            android:layout_width="48dp"
            android:layout_height="48dp"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:background="@drawable/reject_image" />
    </RelativeLayout>
    
    
    <RelativeLayout
        android:id="@+id/front"
        style="@style/MyListFrontContent"
        android:orientation="vertical"
        android:tag="front" >
    
        <ImageView
            android:id="@+id/example_image"
            style="@style/MyListImage" />
    
        <TextView
            android:id="@+id/example_itemname"
            style="@style/MyListTitle"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/example_image" />
      </RelativeLayout>
    
    </FrameLayout>
    

    Entire MainActivity.java

    public class MainActivity extends Activity {
    
    SwipeListView swipelistview;
    ItemAdapter adapter;
    List<ItemRow> itemData;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        swipelistview=(SwipeListView)findViewById(R.id.example_swipe_lv_list); 
        itemData=new ArrayList<ItemRow>();
        adapter=new ItemAdapter(this,R.layout.custom_row,itemData);
    
        swipelistview.setSwipeListViewListener(new BaseSwipeListViewListener() {
            @Override
            public void onOpened(int position, boolean toRight) {
    
                if(toRight)
                {
    
                    //  for left to right your api calling here
                    swipelistview.closeAnimate(position);
                }
                else
                {
                    // for right to left your api calling here
                    swipelistview.closeAnimate(position);
                }
    
    
            }
    
            @Override
            public void onClosed(int position, boolean fromRight) {
                // close list slide
            }
    
            @Override
            public void onListChanged() {
    
            }
    
            @Override
            public void onMove(int position, float x) {
    
    
            }
    
            @Override
            public void onStartOpen(int position, int action, boolean right) {
                Log.d("swipe", String.format("onStartOpen %d - action %d", position, action));
    
    
    
            }
    
            @Override
            public void onStartClose(int position, boolean right) {
                Log.d("swipe", String.format("onStartClose %d", position));
    
    
            }
    
            @Override
            public void onClickFrontView(int position) {
                Log.d("swipe", String.format("onClickFrontView %d", position));
    
    
    
    
            }
    
            @Override
            public void onClickBackView(int position) {
                Log.d("swipe", String.format("onClickBackView %d", position));
    
                swipelistview.closeAnimate(position);//when you touch back view it will close
    
            }
    
            @Override
            public void onDismiss(int[] reverseSortedPositions) {
    
            }
    
        });
    
        //These are the swipe listview settings. you can change these
        //setting as your requirement 
        swipelistview.setSwipeMode(SwipeListView.SWIPE_MODE_BOTH); // there are five swiping modes
        //    swipelistview.setSwipeActionLeft(SwipeListView.SWIPE_ACTION_DISMISS); //there are four swipe actions 
        swipelistview.setSwipeActionRight(SwipeListView.SWIPE_ACTION_REVEAL);
        swipelistview.setOffsetLeft(convertDpToPixel(0f)); // left side offset
        swipelistview.setOffsetRight(convertDpToPixel(80f)); // right side offset
        swipelistview.setAnimationTime(500); // Animation time
        swipelistview.setSwipeOpenOnLongPress(true); // enable or disable SwipeOpenOnLongPress
    
        swipelistview.setAdapter(adapter);
    
    
        for(int i=0;i<10;i++)
        {
            itemData.add(new ItemRow("Swipe Item"+ i,getResources().getDrawable(R.drawable.ic_launcher) ));
    
        }
    
        adapter.notifyDataSetChanged();
    }
    
    public int convertDpToPixel(float dp) {
        DisplayMetrics metrics = getResources().getDisplayMetrics();
        float px = dp * (metrics.densityDpi / 160f);
        return (int) px;
    }
    
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
      }
    
     }
    

    Other code and library remains same, It helpful to you and other also, So enjoy.

    0 讨论(0)
  • 2020-12-05 12:21

    based on @Pratibha Sarode solution I adapt it as follow with a listview poupulated with a cursoradaptor and a database : In the main activity :

      //-- Attach cursor adapter to the ListView
        lvItems.setAdapter(todoAdapter);
        /////////////////// Swipe Management
        lvItems.setOnTouchListener(new OnSwipeList(AfficList.this,lvItems){
            public void onSwipeRight(int pos) {
                AnnonceDbHandler dbHandler = new AnnonceDbHandler(AfficList.this, null, null, 1);
                String sIdAnn=dbHandler.RechercheIdIndex(pos);
                //Toast.makeText(AfficList.this, "Right ("+pos+") : "+sIdAnn, Toast.LENGTH_SHORT).show();
                dbHandler.deleteAnnonce(sIdAnn, AfficList.this);
                Cursor NewCursor = dbAnnonces.rawQuery("SELECT  * FROM annonces", null);
                todoAdapter.swapCursor(NewCursor);
                lvItems.setAdapter(todoAdapter);
                todoAdapter.notifyDataSetChanged();
            }
            public void onSwipeLeft(int pos) {
                AnnonceDbHandler dbHandler = new AnnonceDbHandler(AfficList.this, null, null, 1);
                String sIdAnn=dbHandler.RechercheIdIndex(pos);
                //Toast.makeText(AfficList.this, "Right ("+pos+") : "+sIdAnn, Toast.LENGTH_SHORT).show();
                dbHandler.deleteAnnonce(sIdAnn, AfficList.this);
                Cursor NewCursor = dbAnnonces.rawQuery("SELECT  * FROM annonces", null);
                todoAdapter.swapCursor(NewCursor);
                lvItems.setAdapter(todoAdapter);
                todoAdapter.notifyDataSetChanged();
            }
        });
    

    It work's great deleting lines with swipe movment !

    0 讨论(0)
提交回复
热议问题