Android新的收件箱应用程序样式列表视图,左右滑动

时间:2014-11-06 04:19:00

标签: android listview swipeview

我试图建立Android新的收件箱样式列表视图,左右滑动,如图所示,我已经尝试47deg swipelistview但它不稳定,是否有其他库可用?!

right swipe left swipe

到目前为止尝试了47度

 public class MainActivity extends Activity {

        Listview pullToRefreshListView;
        SwipeListView swipelistview;
        ItemAdapter adapter;
        List<ItemRow> itemData;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            pullToRefreshListView = (ListView) findViewById(R.id.example_swipe_lv_list);
            swipelistview = pullToRefreshListView.getRefreshableView();
            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) {
                        adapter.remove(position);
                        Toast.makeText(MainActivity.this, "Open to dismiss",
                                Toast.LENGTH_SHORT).show();
                    } // swipelistview.dismiss(position);
                    else {
                        Toast.makeText(MainActivity.this, "Open to edit",
                                Toast.LENGTH_SHORT).show();
                    }
                }

                @Override
                public void onClosed(int position, boolean fromRight) {
                }

                @Override
                public void onListChanged() {
                }

                @Override
                public void onMove(int position, float x) {
                }

                @Override
                public void onStartOpen(int position, int action, boolean right) {
                    if (right) {
                        // adapter.onRight();
                        swipelistview.getChildAt(position).findViewById(R.id.back)
                                .setBackgroundColor(Color.GREEN);

                        swipelistview.getChildAt(position)
                                .findViewById(R.id.imageViewLeft)
                                .setVisibility(View.VISIBLE);
                        swipelistview.getChildAt(position)
                                .findViewById(R.id.imageViewRight)
                                .setVisibility(View.GONE);
                    } else {
                        // adapter.onLeft();
                        swipelistview.getChildAt(position).findViewById(R.id.back)
                                .setBackgroundColor(Color.RED);
                        swipelistview.getChildAt(position)
                                .findViewById(R.id.imageViewLeft)
                                .setVisibility(View.GONE);
                        swipelistview.getChildAt(position)
                                .findViewById(R.id.imageViewRight)
                                .setVisibility(View.VISIBLE);
                    }
                }

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

                    // swipelistview.openAnimate(position); //when you touch front
                    // view it will open

                }

                @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.setSwipeActionRight(SwipeListView.SWIPE_ACTION_REVEAL); // there
                                                                                    // are
                                                                                    // four
                                                                                    // swipe
                                                                                    // actions
            swipelistview.setSwipeActionLeft(SwipeListView.SWIPE_ACTION_REVEAL);
            swipelistview.setOffsetRight(convertDpToPixel(0f)); // left side
                                                                // offset
            swipelistview.setOffsetLeft(convertDpToPixel(0f)); // right side
                                                                // offset
            swipelistview.setAnimationTime(60); // Animation time
            swipelistview.setSwipeOpenOnLongPress(false); // enable or disable
                                                            // SwipeOpenOnLongPress
            swipelistview.setSwipeCloseAllItemsWhenMoveList(true);
            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;
}
    }

适配器类

public class ItemAdapter extends ArrayAdapter<ItemRow> {

    List<ItemRow> data;
    Context context;
    int layoutResID;

    public ItemAdapter(Context context, int layoutResourceId, List<ItemRow> data) {
        super(context, layoutResourceId, data);

        this.data = data;
        this.context = context;
        this.layoutResID = layoutResourceId;

        // TODO Auto-generated constructor stub
    }

    NewsHolder holder = null;
    View row = null;

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

        row = convertView;
        holder = null;

        if (row == null) {
            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            row = inflater.inflate(layoutResID, parent, false);

            holder = new NewsHolder();

            holder.itemName = (TextView) row
                    .findViewById(R.id.example_itemname);
            holder.icon = (ImageView) row.findViewById(R.id.example_image);
            holder.imageViewRight = (ImageView) row
                    .findViewById(R.id.imageViewRight);
            holder.imageViewLeft = (ImageView) row
                    .findViewById(R.id.imageViewLeft);

            row.setTag(holder);
        } else {
            holder = (NewsHolder) row.getTag();
        }

        ItemRow itemdata = data.get(position);
        holder.itemName.setText(itemdata.getItemName());
        holder.icon.setImageDrawable(itemdata.getIcon());

        return row;

    }
    public void remove(int pos){
        data.remove(pos);

    }

    public void onLeft() {

        holder.imageViewLeft.setVisibility(View.VISIBLE);
        holder.imageViewRight.setVisibility(View.GONE);
    }

    public void onRight() {
        holder.imageViewRight.setVisibility(View.VISIBLE);
        holder.imageViewLeft.setVisibility(View.GONE);
    }

    static class NewsHolder {

        TextView itemName;
        ImageView icon;
        ImageView imageViewLeft, imageViewRight;

        RelativeLayout mRelativeLayout;
    }

3 个答案:

答案 0 :(得分:12)

您可以简单地支持&#34;刷卡&#34;而不是使用自定义ListView。列表项onTouch上的手势,如下所示:

private static final int DEFAULT_THRESHOLD = 128;

row.setOnTouchListener(new View.OnTouchListener() {

    int initialX = 0;
    final float slop = ViewConfiguration.get(context).getScaledTouchSlop();

    public boolean onTouch(final View view, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            initialX = (int) event.getX();
            view.setPadding(0, 0, 0, 0);
        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
            int currentX = (int) event.getX();
            int offset = currentX - initialX;
            if (Math.abs(offset) > slop) {
                view.setPadding(offset, 0, 0, 0);

                if (offset > DEFAULT_THRESHOLD) {
                    // TODO :: Do Right to Left action! And do nothing on action_up.
                } else if (offset < -DEFAULT_THRESHOLD) {
                    // TODO :: Do Left to Right action! And do nothing on action_up.
                }
            }
        } else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
            // Animate back if no action was performed.
            ValueAnimator animator = ValueAnimator.ofInt(view.getPaddingLeft(), 0);
            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                    view.setPadding((Integer) valueAnimator.getAnimatedValue(), 0, 0, 0);
                }
            });
            animator.setDuration(150);
            animator.start();
        }
};

如果没有执行任何操作,我也会使用反向动画。

这个解决方案很轻巧,所以你不应该遇到任何滞后。

答案 1 :(得分:12)

退房:SwipeActionAdapter

这是一个很棒的图书馆,完全符合您的要求。 允许双向滑动与基础LayoutColor。它易于实现,看起来很棒!

Left Swipe Right Swipe

答案 2 :(得分:2)

更新答案

正如我之前提到的,我采用了相同的方法,似乎按预期工作。我已经为RelativeLayout添加了3个图层。顶层是您想要显示的。第二层是普通背景,左侧是删除图标。第三层是另一个普通背景,右侧是共享图标。我实现了一个扩展View.OnTouchListener的滑动检测器类。

public class SwipeDetector implements View.OnTouchListener {

    private static final int MIN_DISTANCE = 300;
    private static final int MIN_LOCK_DISTANCE = 30; // disallow motion intercept
    private boolean motionInterceptDisallowed = false;
    private float downX, upX;
    private ObjectHolder holder;
    private int position;

    public SwipeDetector(ObjectHolder h, int pos) {
        holder = h;
        position = pos;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN: {
            downX = event.getX();
            return true; // allow other events like Click to be processed
        }

        case MotionEvent.ACTION_MOVE: {
            upX = event.getX();
            float deltaX = downX - upX;

            if (Math.abs(deltaX) > MIN_LOCK_DISTANCE && listView != null && !motionInterceptDisallowed) {
                listView.requestDisallowInterceptTouchEvent(true);
                motionInterceptDisallowed = true;
            }

            if (deltaX > 0) {
                holder.deleteView.setVisibility(View.GONE);
            } else {
                // if first swiped left and then swiped right
                holder.deleteView.setVisibility(View.VISIBLE);
            }

            swipe(-(int) deltaX);
            return true;
        }

        case MotionEvent.ACTION_UP:
            upX = event.getX();
            float deltaX = upX - downX;
            if (Math.abs(deltaX) > MIN_DISTANCE) {
                // left or right
                swipeRemove();
            } else {
                swipe(0);
            }

            if (listView != null) {
                listView.requestDisallowInterceptTouchEvent(false);
                motionInterceptDisallowed = false;
            }

            holder.deleteView.setVisibility(View.VISIBLE);
            return true;

        case MotionEvent.ACTION_CANCEL:
            holder.deleteView.setVisibility(View.VISIBLE);
            return false;
        }

    return true;
    }

    private void swipe(int distance) {
        View animationView = holder.mainView;
        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) animationView.getLayoutParams();
        params.rightMargin = -distance;
        params.leftMargin = distance;
        animationView.setLayoutParams(params);
    }

    private void swipeRemove() {
        remove(getItem(position));
        notifyDataSetChanged();
    }
}


public static class ObjectHolder {
    public LinearLayout mainView;
    public RelativeLayout deleteView;
    public RelativeLayout shareView;

    /* other views here */
}

我还添加了requestDisallowInterceptTouchEvent,以便ListView(父母)在涉及一定量的垂直滚动时不会拦截触摸事件。

我写了一篇关于它的博文,你可以找到它here。我还添加了Youtube video for demo


旧答案

我自己实施了其中一个,但它有点不同。我只使用触摸而不是滑动。触摸打开,触摸即可关闭。这是youtube demo

我创建了自定义ArrayAdapter。为了设置布局,我创建了一个这样的自定义布局。

<RelativeLayout>
     <RelativeLayout>
          <Stuff that you want at the back of your list/>
     </RelativeLayout>
     <RelativeLayout>
          <Stuff that you want at the front of your list/>
     </RelativeLayout>
</RelativeLayout>

使用RelativeLayout,我将顶视图放在底部视图上。两者都有相同的尺寸。您可以为内部布局使用不同的布局。

在Custom ArrayAdapter中,

@Override
public view getView(int position, View convertView, ViewGroup parent) {
    // get holder and entry
    // set each element based on entry preferences



    holder.topView.setOnClickListener(new View.OnClickListener() {

          @Override
          public void onClick(View v) {
              if (entry.isSwiped()) {
                  swipeWithAnimationValue(holder.topView, 1);
                  entry.setSwiped(false);
              } else {
                  closeOtherSwipes(entry);  // if you want to keep only one entry open at a time
                  swipeWithAnimationValue(holder.topView, 0);
                  entry.setSwiped(true);
              }
         }
   });
}

普通动画不起作用,因为它只是移动视图,但它仍然存在,所以如果你试图点击,点击仍然会出现在顶视图上。因此我使用了valueAnimator并实际移动了这些列表。

public void swipeWithAnimationValue(final View view, final int direction) {
    final int width = view.getWidth();
    Log.i(TAG, "view width = " + String.valueOf(width));
    ValueAnimator animationSwipe;
    int duration = 300;
    if (direction == 0) {
         animationSwipe = ValueAnimator.ofInt(0, view.getWidth() - 200);
    } else {
         animationSwipe = ValueAnimator.ofInt(view.getWidth() - 200, 0);
    }

    animationSwipe.setDuration(duration);
    AnimatorUpdateListener maringUpdater = new AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {

             RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) view.getLayoutParams();
             params.rightMargin = -(Integer)animation.getAnimatedValue();
             params.leftMargin = (Integer)animation.getAnimatedValue();
             view.setLayoutParams(params);
        }
    };

    animationSwipe.addUpdateListener(maringUpdater);
    animationSwipe.setRepeatCount(0);
    animationSwipe.start();
}