Android ListView向左和向左滑动以接受和拒绝

时间:2015-06-18 06:33:35

标签: android listview swipe

我想开发一个列表视图,当从左向右滑动时 - 在左角显示一个accept(true)图标(不可点击 - 从左向右滑动时只显示颜色变化),如下面的屏幕截图所示:

enter image description here

当我从左向右滑动时,它会接受(调用'接受' API), 当我从右向左滑动时,它会显示如下:

enter image description here

这是在iOS中完成的,但我无法在Android中找到如何执行此操作,我尝试使用Google搜索,但无法找到我想要的内容。

我尝试了以下示例:http://www.tutecentral.com/android-swipe-listview/

但在该示例中,当我从左向右和从右向左滑动时,会调用相同的onOpened(..)方法,因此很难知道何时调用accept以及何时调用reject API,因为任何类型的滑动都会调用相同的方法。

并且我还希望接受(在左侧)和拒绝(在右侧)图像仅在我向左或向右滑动时显示,但是当我拿起手指时它们必须消失并且整个ListView应显示(不要同时显示两个侧面图像)。

所以请任何人帮我理解如何做到这一点。

我的问题有些令人困惑,但我不知道如何解释整个动画,所以我试着像上面那样解释。

如果有人可以帮助我,我们将非常感激。

6 个答案:

答案 0 :(得分:13)

解决方案编号1:

你必须做的就像跟随到达" near"对你的功能,

包装ListView的适配器

如下:

  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);
  }

为每个滑动方向创建背景布局

喜欢以下:

  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);
}

你从这里得到了两个库和例子: https://github.com/wdullaer/SwipeActionAdapter

这不符合您的要求,但我希望这会帮助您实现您的功能。

解决方案编号2:

解决方案2是关于更改已使用代码中的某些代码:http://www.tutecentral.com/android-swipe-listview/

我从链接http://www.tutecentral.com/android-swipe-listview/尝试了您的代码并更改了一些代码并成功解决了关于onOpened(..)方法的问题(您的困惑)(从左到右调用,反之亦然)

首先改变:

  1. custom_row.xml布局文件有三个按钮swipe_button1到3, 删除它们中间。

  2. 复制粘贴以下代码以保留两个按钮:

    <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" />
    

  3. 此布局保持代码相同。

    第二次改变:

    所以现在你的接受和拒绝以及列表代码已准备就绪,现在讨论onOpened(..)方法。

    混淆解决方案1 ​​ - 你说过,你的onOpend(...)方法从左到右都是一样的,反之亦然

    - &GT;只是为了改变以下内容:

    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);
                }
    
    
            }
    

    混乱解决方案2 当我拿起手指时,它必须显示整个列表视图或列表视图边应该保留它的角落以便它不起作用

    - &GT;我已经在上面回答了

    在if else中调用 swipelistview.closeAnimate(position); ,当你向左和向右滑动时,它会隐藏左接受和右边拒绝图像。

    所以最后的代码如下:

    整个cutom_row.xml布局

     <?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>
    

    整个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;
      }
    
     }
    

    其他代码和库保持不变,它对您和其他人也很有帮助,所以尽情享受。

答案 1 :(得分:5)

它对我有用......我希望它对你有用..!

将OnTouchListener设置为listview为

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

OnSwipeTouchListener类如下:

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;
        }

    }
}

答案 2 :(得分:1)

看一下this库,它会给你很好的例子,并指出你正确的方向。祝你好运。

答案 3 :(得分:1)

请避免使用上述方法,否则您将使用视图逻辑完全填充控制器(您必须避免的事情)访问https://github.com/xenione/SwipeLayout有一个滑动制造商带有一些示例

答案 4 :(得分:1)

基于@Pratibha Sarode解决方案我将其改编为如下的listview与cursoradaptor和数据库: 在主要活动中:

  //-- 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();
        }
    });

使用滑动动作删除行很棒!

答案 5 :(得分:0)

https://stackoverflow.com/a/31094315/2914140使用答案我就是这样做的。

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;
    }
};

在适配器的getView中写:

@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;
}

我认为通过在item_layout.xml中使用Horizo​​ntalScrollView可以实现同样的目的。