在ListView

时间:2015-09-17 09:41:23

标签: android listview animation swipe-gesture

你看过ios imessage app吗?在此应用程序中查看聊天消息的时间戳,我们需要向左滑动。最初它们是隐藏的但是当我们向左滑动时,隐藏的时间戳被显示出来。我想在我的Android应用程序中实现它。

enter image description here

当我们向左滑动时,灰色气泡中的消息仍然固定,但是,蓝色气泡中的消息向左滑动以显示时间戳。

以下是我到目前为止所尝试的内容。

SwipeDetector.java - 它会检测滑动

public class SwipeDetector implements View.OnTouchListener {

private SwipeListener swipeListener;
private int hundred;

public static enum Action {
    LR, // Left to right
    RL, // Right to left
    TB, // Top to bottom
    BT, // Bottom to top
    None // Action not found
}

private static final int HORIZONTAL_MIN_DISTANCE = 30; // The minimum
// distance for
// horizontal swipe
private static final int VERTICAL_MIN_DISTANCE = 80; // The minimum distance
// for vertical
// swipe
private float downX, downY, upX, upY; // Coordinates
private Action mSwipeDetected = Action.None; // Last action

public SwipeDetector(Context context) {
    hundred = (int) context.getResources().getDimension(R.dimen.hundred);
}

public boolean swipeDetected() {
    return mSwipeDetected != Action.None;
}

public Action getAction() {
    return mSwipeDetected;
}

/**
 * Swipe detection
 */@Override
public boolean onTouch(View v, MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
        {
            downX = event.getX();
            downY = event.getY();
            mSwipeDetected = Action.None;
            return false; // allow other events like Click to be processed
        }
        case MotionEvent.ACTION_MOVE:
        {
            upX = event.getX();
            upY = event.getY();

            float deltaX = downX - upX;
            float deltaY = downY - upY;

            float absX = Math.abs(deltaX);
            float absY = Math.abs(deltaY);

            if((absX >= (3 * absY)) && absX <= hundred) {
                if (deltaX > 0) {
                    mSwipeDetected = Action.RL;
                    swipeListener.onSwipe(MotionEvent.ACTION_MOVE, Action.RL, absX);
                    return false;
                }
            }
            return false;
        }
        case MotionEvent.ACTION_UP:
            swipeListener.onSwipe(MotionEvent.ACTION_UP, Action.BT, 0);
            return false;
    }
    return false;
}

/**
 * Set chat send listener
 * @param listener
 */
public void setSwipeListener(SwipeListener listener) {
    swipeListener = listener;
}

public interface SwipeListener {
    void onSwipe(int event, Action action, float x);
}

}

SwipeActivity.java - 它的Activity类

public class SwipeActivity extends AppCompatActivity implements SwipeDetector.SwipeListener {

private ListView mListView;
private SwipeListAdapter mAdapter;

private ArrayList<String> mData = new ArrayList<>();
private SwipeDetector.SwipeListener mSwipeListener;

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

    mSwipeListener = this;

    for (int i=0; i<50; i++) {
        mData.add("Text");
    }

    mListView = (ListView) findViewById(R.id.listview);
    mAdapter = new SwipeListAdapter(SwipeActivity.this, mData);
    mListView.setAdapter(mAdapter);

    mListView.requestDisallowInterceptTouchEvent(true);

    // Set the touch listener
    final SwipeDetector swipeDetector = new SwipeDetector(SwipeActivity.this);
    swipeDetector.setSwipeListener(mSwipeListener);
    mListView.setOnTouchListener(swipeDetector);
}

@Override
public void onSwipe(int event, SwipeDetector.Action action, float x) {
    System.out.println("swipe: " + action + " = " + x);
    swipeListView(event, x);
}

private void swipeListView(int event, float x) {
    updateListView(event, x);
}

/**
 * Update ListView using animation
 * @param event
 * @param x
 */
private void updateListView(int event, float x) {
    int start = mListView.getFirstVisiblePosition();
    int end = mListView.getLastVisiblePosition();
    for(int i=start, j=end; i<=j; i++) {
        View v = mListView.getChildAt(i - start);
        TextView tv = (TextView) v.findViewById(R.id.textviewright);
        TextView tvH = (TextView) v.findViewById(R.id.textviewhidden);

        switch (event) {
            case MotionEvent.ACTION_MOVE:
                tv.animate().translationX(-x).setDuration(0);
                tvH.animate().translationX(-x).setDuration(0);
                break;
            case MotionEvent.ACTION_UP:
                tv.animate().translationX(0).setDuration(500);
                tvH.animate().translationX(0).setDuration(500);
                break;
        }
    }
}
}

SwipeListAdapter.java - ListView适配器

public class SwipeListAdapter extends BaseAdapter {

private Context mContext;
private ArrayList<String> mData;

public SwipeListAdapter() {}

public SwipeListAdapter(Context context, ArrayList<String> data){
    this.mContext = context;
    this.mData = data;
}

@Override
public int getCount() {
    return mData.size();
}

@Override
public Object getItem(int position) {
    return mData.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}

private class ViewHolder {
    TextView mLeftText;
    TextView mRightText;
    TextView mHiddenText;
}

@Override
public View getView(final int position, View view, ViewGroup viewGroup) {
    ViewHolder holder = null;
    if (view == null) {
        holder = new ViewHolder();
        LayoutInflater mInflater = (LayoutInflater) mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        view = mInflater.inflate(R.layout.item_list_swipe, null);

        holder.mLeftText =  (TextView) view.findViewById(R.id.textviewleft);
        holder.mRightText =  (TextView) view.findViewById(R.id.textviewright);
        holder.mHiddenText =  (TextView) view.findViewById(R.id.textviewhidden);

        view.setTag(holder);
    } else {
        holder = (ViewHolder) view.getTag();
    }

    holder.mRightText.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(mContext, "Right", Toast.LENGTH_SHORT).show();
        }
    });

    holder.mLeftText.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(mContext, "Left", Toast.LENGTH_SHORT).show();
        }
    });

    String text = mData.get(position);
    holder.mLeftText.setText(text + " " + position);
    holder.mRightText.setText(text + " " + position);

    return view;
}
}

activity_swipe.xml - 用于SwipeActivity的xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<ListView
    android:id="@+id/listview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

</LinearLayout>

item_list_swipe.xml - ListView项目/行xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
    android:id="@+id/textviewleft"
    android:layout_width="wrap_content"
    android:layout_height="56dp"
    android:background="#FF0000"
    android:layout_alignParentLeft="true"
    android:gravity="center_vertical"
    android:padding="16dp"
    android:text="TextView"
    android:visibility="visible"/>

<TextView
    android:id="@+id/textviewright"
    android:layout_width="wrap_content"
    android:layout_height="56dp"
    android:background="#00FF00"
    android:layout_toLeftOf="@+id/textviewhidden"
    android:gravity="center_vertical"
    android:padding="16dp"
    android:text="TextView"
    android:visibility="visible"/>


<TextView
    android:id="@+id/textviewhidden"
    android:layout_width="100dp"
    android:layout_height="56dp"
    android:background="#0000FF"
    android:layout_alignParentRight="true"
    android:gravity="center"
    android:layout_marginRight="-100dp"
    android:padding="16dp"
    android:text="Date"
    android:visibility="visible"/>

</RelativeLayout>

使用上面的代码,我可以根据滑动的像素显示隐藏的TextView。但是,存在一些问题。以下是我的问题。

  1. 假设我开始滑动,隐藏的TextView部分/半可见。在隐藏的TextView变得完全可见之前,我滚动了ListView,现在ListView开始滚动。现在,如果我再次开始滑动,隐藏的TextView的其余/另一半不会变得可见。 我怎么处理这个?如果无法处理,则至少告诉我如何在启动滑动时禁用ListView滚动,并在滑动停止后启用ListView滚动。

  2. 第二个问题是,如果我从ListView的空白区域开始滑动,即左右TextView的中间部分,则滑动工作完全正常。但是,如果我从右侧或左侧TextView开始滑动而不是滑动,则会触发TextViews的单击侦听器。当我单击右侧或左侧TextView时,他们的onClickListener会被触发,当我滑动时,ListView的滑动应该被触发。

  3. 请帮我解决这个问题。

    注意:这与传统的ListView滑动功能不同。在传统的ListView滑动中,向左滑动完整的行并显示隐藏的视图。在我的情况下,我只想要滑动部分行(蓝色气泡)以显示隐藏的视图(时间戳)。灰色气泡保持固定。我想在ListView的所有行上而不仅仅是单行。对于传统的ListView滑动,有很多库,例如SwipeMenuListViewandroid-swipelistviewAndroidSwipeLayout以及许多其他库,但这些库并不符合我的要求。 < / p>

0 个答案:

没有答案