你看过ios imessage app吗?在此应用程序中查看聊天消息的时间戳,我们需要向左滑动。最初它们是隐藏的但是当我们向左滑动时,隐藏的时间戳被显示出来。我想在我的Android应用程序中实现它。
当我们向左滑动时,灰色气泡中的消息仍然固定,但是,蓝色气泡中的消息向左滑动以显示时间戳。
以下是我到目前为止所尝试的内容。
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。但是,存在一些问题。以下是我的问题。
假设我开始滑动,隐藏的TextView部分/半可见。在隐藏的TextView变得完全可见之前,我滚动了ListView,现在ListView开始滚动。现在,如果我再次开始滑动,隐藏的TextView的其余/另一半不会变得可见。 我怎么处理这个?如果无法处理,则至少告诉我如何在启动滑动时禁用ListView滚动,并在滑动停止后启用ListView滚动。
第二个问题是,如果我从ListView的空白区域开始滑动,即左右TextView的中间部分,则滑动工作完全正常。但是,如果我从右侧或左侧TextView开始滑动而不是滑动,则会触发TextViews的单击侦听器。当我单击右侧或左侧TextView时,他们的onClickListener会被触发,当我滑动时,ListView的滑动应该被触发。
请帮我解决这个问题。
注意:这与传统的ListView滑动功能不同。在传统的ListView滑动中,向左滑动完整的行并显示隐藏的视图。在我的情况下,我只想要滑动部分行(蓝色气泡)以显示隐藏的视图(时间戳)。灰色气泡保持固定。我想在ListView的所有行上而不仅仅是单行。对于传统的ListView滑动,有很多库,例如SwipeMenuListView,android-swipelistview和AndroidSwipeLayout以及许多其他库,但这些库并不符合我的要求。 < / p>