主要的思路是:
重写ListView中的Item,也就是LinearLayout的onTouchEvent方法,以监听横向滑动和纵向滑动:
1)纵向滑动时,不管
2)横向滑动时,请求父容器,也即是ListView不要拦截触摸事件,自己在子View(也就是LinearLayout)里面处理就好了,当横向触摸时间结束(MotionEvent.Action_UP)或者划出边界(MotionEvent.Action_CANCEL)时,恢复允许父容器拦截触摸事件。
先上效果图
重写的LinearLayout如下:
- package ex.oyyj.listviewfulldemo;
- import android.animation.Animator;
- import android.animation.ObjectAnimator;
- import android.content.Context;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.util.TypedValue;
- import android.view.MotionEvent;
- import android.view.ViewParent;
- import android.widget.LinearLayout;
- /**
- * Created by oyyj on 2015/8/6.
- */
- public class HorizontalSlideLayout extends LinearLayout {
- private static String TAG = "VerticalSlideLayout";
- private int DRAG_X_THROD = 0;
- private int SCROLL_X = 0;
- private final int ANIM_DURATION = 300;
- private static final int SLIDE_TO_LEFT = -1;
- private static final int SLIDE_TO_RIGHT = 1;
- private int mSlideDirection = 0;
- public HorizontalSlideLayout(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- //判断横划的阈值,为了兼容不同尺寸的设备,以dp为单位
- DRAG_X_THROD = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 30, context.getResources().getDisplayMetrics());
- SCROLL_X = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, context.getResources().getDisplayMetrics());
- }
- public HorizontalSlideLayout(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
- public HorizontalSlideLayout(Context context) {
- this(context, null, 0);
- }
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- }
- int downX, downY;
- boolean isNeedToGoBack;
- private ObjectAnimator mAnimator;
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- boolean isInterceptHere = false;
- try {
- switch (ev.getAction()) {
- case MotionEvent.ACTION_DOWN:
- downX = (int) ev.getX();
- downY = (int) ev.getY();
- isInterceptHere = true;
- if (mAnimator != null) {
- mAnimator.cancel();
- }
- break;
- case MotionEvent.ACTION_MOVE:
- int dx = (int) Math.abs(ev.getX() - downX);
- int dy = (int) Math.abs(ev.getY() - downY);
- if (dx > dy && dx > DRAG_X_THROD) {
- Log.i(TAG, "横划!拦截它");
- setParentInterceptTouchEvent(true);
- isInterceptHere = true;
- mSlideDirection = (ev.getX() - downX) > 0 ? SLIDE_TO_RIGHT : SLIDE_TO_LEFT;
- if (mSlideDirection == SLIDE_TO_LEFT) {
- isNeedToGoBack = true;
- playAnimation(SCROLL_X, ANIM_DURATION);
- } else if (mSlideDirection == SLIDE_TO_RIGHT && isNeedToGoBack) {
- playAnimation(0, ANIM_DURATION);
- }
- } else if (dy > dx) {
- Log.i(TAG, "竖划!不拦截");
- }
- break;
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- setParentInterceptTouchEvent(false);
- isInterceptHere = false;
- downX = 0;
- downY = 0;
- break;
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return isInterceptHere;
- }
- private void playAnimation(int translationX, int duration) {
- if (mAnimator != null) {
- mAnimator.cancel();
- }
- mAnimator = ObjectAnimator.ofInt(this, "scrollX", translationX);
- mAnimator.setDuration(duration);
- mAnimator.start();
- mAnimator.addListener(listener);
- }
- /* 这个函数很重要,请求禁止父容器拦截触摸事件 */
- public void setParentInterceptTouchEvent(boolean disallow) {
- ViewParent parent = getParent();
- if (parent != null) {
- parent.requestDisallowInterceptTouchEvent(disallow);
- }
- }
- Animator.AnimatorListener listener = new Animator.AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animator) {
- }
- @Override
- public void onAnimationEnd(Animator animator) {
- mAnimator = null;
- }
- @Override
- public void onAnimationCancel(Animator animator) {
- mAnimator = null;
- }
- @Override
- public void onAnimationRepeat(Animator animator) {
- }
- };
- }
package ex.oyyj.listviewfulldemo;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.ViewParent;
import android.widget.LinearLayout;
/**
* Created by oyyj on 2015/8/6.
*/
public class HorizontalSlideLayout extends LinearLayout {
private static String TAG = "VerticalSlideLayout";
private int DRAG_X_THROD = 0;
private int SCROLL_X = 0;
private final int ANIM_DURATION = 300;
private static final int SLIDE_TO_LEFT = -1;
private static final int SLIDE_TO_RIGHT = 1;
private int mSlideDirection = 0;
public HorizontalSlideLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
//判断横划的阈值,为了兼容不同尺寸的设备,以dp为单位
DRAG_X_THROD = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 30, context.getResources().getDisplayMetrics());
SCROLL_X = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, context.getResources().getDisplayMetrics());
}
public HorizontalSlideLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public HorizontalSlideLayout(Context context) {
this(context, null, 0);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
}
int downX, downY;
boolean isNeedToGoBack;
private ObjectAnimator mAnimator;
@Override
public boolean onTouchEvent(MotionEvent ev) {
boolean isInterceptHere = false;
try {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = (int) ev.getX();
downY = (int) ev.getY();
isInterceptHere = true;
if (mAnimator != null) {
mAnimator.cancel();
}
break;
case MotionEvent.ACTION_MOVE:
int dx = (int) Math.abs(ev.getX() - downX);
int dy = (int) Math.abs(ev.getY() - downY);
if (dx > dy && dx > DRAG_X_THROD) {
Log.i(TAG, "横划!拦截它");
setParentInterceptTouchEvent(true);
isInterceptHere = true;
mSlideDirection = (ev.getX() - downX) > 0 ? SLIDE_TO_RIGHT : SLIDE_TO_LEFT;
if (mSlideDirection == SLIDE_TO_LEFT) {
isNeedToGoBack = true;
playAnimation(SCROLL_X, ANIM_DURATION);
} else if (mSlideDirection == SLIDE_TO_RIGHT && isNeedToGoBack) {
playAnimation(0, ANIM_DURATION);
}
} else if (dy > dx) {
Log.i(TAG, "竖划!不拦截");
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
setParentInterceptTouchEvent(false);
isInterceptHere = false;
downX = 0;
downY = 0;
break;
}
} catch (Exception e) {
e.printStackTrace();
}
return isInterceptHere;
}
private void playAnimation(int translationX, int duration) {
if (mAnimator != null) {
mAnimator.cancel();
}
mAnimator = ObjectAnimator.ofInt(this, "scrollX", translationX);
mAnimator.setDuration(duration);
mAnimator.start();
mAnimator.addListener(listener);
}
/* 这个函数很重要,请求禁止父容器拦截触摸事件 */
public void setParentInterceptTouchEvent(boolean disallow) {
ViewParent parent = getParent();
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(disallow);
}
}
Animator.AnimatorListener listener = new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
}
@Override
public void onAnimationEnd(Animator animator) {
mAnimator = null;
}
@Override
public void onAnimationCancel(Animator animator) {
mAnimator = null;
}
@Override
public void onAnimationRepeat(Animator animator) {
}
};
}
贴上详细调用代码:
activity_main.xml
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
- android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
- android:paddingRight="@dimen/activity_horizontal_margin"
- android:paddingTop="@dimen/activity_vertical_margin"
- android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"
- android:background="#ffffff">
- <ListView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@+id/listView"
- android:divider="@drawable/divider"
- android:listSelector="@drawable/selector_list_background"
- android:layout_centerInParent="true" />
- </RelativeLayout>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"
android:background="#ffffff">
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/listView"
android:divider="@drawable/divider"
android:listSelector="@drawable/selector_list_background"
android:layout_centerInParent="true" />
</RelativeLayout>
MainActivity.java
- package ex.oyyj.listviewfulldemo;
- import android.app.Activity;
- import android.os.Bundle;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.BaseAdapter;
- import android.widget.ListView;
- import android.widget.TextView;
- public class MainActivity extends Activity {
- private ListView mlistView;
- String[] films = new String[]{
- "煎饼侠",
- "猎妖记",
- "大圣归来",
- "道士下山",
- "王朝的女人·杨贵妃",
- "栀子花开",
- "太平轮(下) ",};
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- mlistView = (ListView) findViewById(R.id.listView);
- final TitleAdapter titleAdapter = new TitleAdapter(LayoutInflater.from(this), films);
- mlistView.setAdapter(titleAdapter);
- }
- private class TitleAdapter extends BaseAdapter {
- String[] itemNames;
- LayoutInflater inflater;
- public TitleAdapter(LayoutInflater _inflater, String[] names) {
- inflater = _inflater;
- itemNames = names.clone();
- }
- @Override
- public Object getItem(int i) {
- return itemNames[i];
- }
- @Override
- public long getItemId(int i) {
- return i;
- }
- @Override
- public int getCount() {
- return itemNames.length;
- }
- @Override
- public View getView(int i, View view, ViewGroup viewGroup) {
- try {
- ViewHolder holder = new ViewHolder();
- if (view == null ) {
- view = inflater.inflate(R.layout.item_layout, viewGroup, false);
- holder.title = (TextView) view.findViewById(R.id.item);
- view.setTag(holder);
- } else {
- holder = (ViewHolder) view.getTag();
- }
- if (holder != null && holder.title != null) {
- TextView tv = holder.title;
- tv.setText(itemNames[i]);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return view;
- }
- private class ViewHolder {
- TextView title;
- }
- }
- }
package ex.oyyj.listviewfulldemo;
import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends Activity {
private ListView mlistView;
String[] films = new String[]{
"煎饼侠",
"猎妖记",
"大圣归来",
"道士下山",
"王朝的女人·杨贵妃",
"栀子花开",
"太平轮(下) ",};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mlistView = (ListView) findViewById(R.id.listView);
final TitleAdapter titleAdapter = new TitleAdapter(LayoutInflater.from(this), films);
mlistView.setAdapter(titleAdapter);
}
private class TitleAdapter extends BaseAdapter {
String[] itemNames;
LayoutInflater inflater;
public TitleAdapter(LayoutInflater _inflater, String[] names) {
inflater = _inflater;
itemNames = names.clone();
}
@Override
public Object getItem(int i) {
return itemNames[i];
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public int getCount() {
return itemNames.length;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
try {
ViewHolder holder = new ViewHolder();
if (view == null ) {
view = inflater.inflate(R.layout.item_layout, viewGroup, false);
holder.title = (TextView) view.findViewById(R.id.item);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
if (holder != null && holder.title != null) {
TextView tv = holder.title;
tv.setText(itemNames[i]);
}
} catch (Exception e) {
e.printStackTrace();
}
return view;
}
private class ViewHolder {
TextView title;
}
}
}
转自:http://blog.csdn.net/oyyj42/article/details/47333443