一、前言:
需求:一個ViewGroup中有多個控件动看,類似于常見的底部Tab布局尊剔,這幾個子布局之間既可以點(diǎn)擊切換,也可以左右滑動切換
實(shí)現(xiàn):自定義父控件菱皆,在onInterceptTouchEvent方法中判斷是否點(diǎn)擊還是滑動须误,如果判斷是點(diǎn)擊,則直接交給child來響應(yīng)點(diǎn)擊事件去仇轻;如果是滑動京痢,則
攔截事件,并通過回調(diào)傳遞給調(diào)用者處理拯田。
優(yōu)點(diǎn):該控件只對觸摸事件的分發(fā)做了相應(yīng)處理历造,適用于各種滑動與點(diǎn)擊沖突的情況....
使用:直接將該控件作為父布局即可,通過setmSetOnSlideListener回調(diào)處理對應(yīng)滑動事件
二船庇、使用:
1、代碼
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.widget.RelativeLayout;
public class MyRadioRelativeLayout extends RelativeLayout {
public MyRadioRelativeLayout(Context context) {
this(context, null);
}
public MyRadioRelativeLayout(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
public MyRadioRelativeLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
private void initView() {
}
private boolean mScrolling;
private float touchDownX;
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchDownX = event.getX();
mScrolling = false;
break;
case MotionEvent.ACTION_MOVE:
if (Math.abs(touchDownX - event.getX()) >= ViewConfiguration.get(
getContext()).getScaledTouchSlop()) {
mScrolling = true;
} else {
mScrolling = false;
}
break;
case MotionEvent.ACTION_UP:
mScrolling = false;
break;
}
return mScrolling;
}
float x1 = 0;
float x2 = 0;
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
return true;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
x2 = event.getX();
if (touchDownX - x2 > DensityUtil.dip2px(getContext(), 40)) {
if(mSetOnSlideListener!=null){
mSetOnSlideListener.onRightToLeftSlide();
}
}
if (touchDownX - x2 < -DensityUtil.dip2px(getContext(), 40)) {
if(mSetOnSlideListener!=null){
mSetOnSlideListener.onLeftToRightSlide();
}
}
break;
}
return super.onTouchEvent(event);
}
private setOnSlideListener mSetOnSlideListener;
public setOnSlideListener getmSetOnSlideListener() {
return mSetOnSlideListener;
}
public void setmSetOnSlideListener(setOnSlideListener mSetOnSlideListener) {
this.mSetOnSlideListener = mSetOnSlideListener;
}
public interface setOnSlideListener{
void onRightToLeftSlide();
void onLeftToRightSlide();
}
}
2侣监、解析:
ViewConfiguration.getScaledTouchSlop () 用法
getScaledTouchSlop是一個距離鸭轮,表示滑動的時候,手的移動要大于這個距離才開始移動控件橄霉。如果小于這個距離就不觸發(fā)移動控件窃爷,如viewpager就是用這個距離來判斷用戶是否翻頁。
ViewConfiguration滑動參數(shù)設(shè)置類:
/**
* 包含了方法和標(biāo)準(zhǔn)的常量用來設(shè)置UI的超時姓蜂、大小和距離
*/
public class ViewConfiguration {
// 設(shè)定水平滾動條的寬度和垂直滾動條的高度按厘,單位是像素px
private static final int SCROLL_BAR_SIZE = 10;
//定義滾動條逐漸消失的時間,單位是毫秒
private static final int SCROLL_BAR_FADE_DURATION = 250;
// 默認(rèn)的滾動條多少秒之后消失钱慢,單位是毫秒
private static final int SCROLL_BAR_DEFAULT_DELAY = 300;
// 定義邊緣地方褪色的長度
private static final int FADING_EDGE_LENGTH = 12;
//定義子控件按下狀態(tài)的持續(xù)事件
private static final int PRESSED_STATE_DURATION = 125;
//定義一個按下狀態(tài)轉(zhuǎn)變成長按狀態(tài)的轉(zhuǎn)變時間
private static final int LONG_PRESS_TIMEOUT = 500;
//定義用戶在按住適當(dāng)按鈕逮京,彈出全局的對話框的持續(xù)時間
private static final int GLOBAL_ACTIONS_KEY_TIMEOUT = 500;
//定義一個touch事件中是點(diǎn)擊事件還是一個滑動事件所需的時間,如果用戶在這個時間之內(nèi)滑動束莫,那么就認(rèn)為是一個點(diǎn)擊事件
private static final int TAP_TIMEOUT = 115;
/**
* Defines the duration in milliseconds we will wait to see if a touch event
* is a jump tap. If the user does not complete the jump tap within this interval, it is
* considered to be a tap.
*/
//定義一個touch事件時候是一個點(diǎn)擊事件懒棉。如果用戶在這個時間內(nèi)沒有完成這個點(diǎn)擊,那么就認(rèn)為是一個點(diǎn)擊事件
private static final int JUMP_TAP_TIMEOUT = 500;
//定義雙擊事件的間隔時間
private static final int DOUBLE_TAP_TIMEOUT = 300;
//定義一個縮放控制反饋到用戶界面的時間
private static final int ZOOM_CONTROLS_TIMEOUT = 3000;
/**
* Inset in pixels to look for touchable content when the user touches the edge of the screen
*/
private static final int EDGE_SLOP = 12;
/**
* Distance a touch can wander before we think the user is scrolling in pixels
*/
private static final int TOUCH_SLOP = 16;
/**
* Distance a touch can wander before we think the user is attempting a paged scroll
* (in dips)
*/
private static final int PAGING_TOUCH_SLOP = TOUCH_SLOP * 2;
/**
* Distance between the first touch and second touch to still be considered a double tap
*/
private static final int DOUBLE_TAP_SLOP = 100;
/**
* Distance a touch needs to be outside of a window's bounds for it to
* count as outside for purposes of dismissing the window.
*/
private static final int WINDOW_TOUCH_SLOP = 16;
//用來初始化fling的最小速度览绿,單位是每秒多少像素
private static final int MINIMUM_FLING_VELOCITY = 50;
//用來初始化fling的最大速度策严,單位是每秒多少像素
private static final int MAXIMUM_FLING_VELOCITY = 4000;
//視圖繪圖緩存的最大尺寸,以字節(jié)表示饿敲。在ARGB888格式下妻导,這個尺寸應(yīng)至少等于屏幕的大小
@Deprecated
private static final int MAXIMUM_DRAWING_CACHE_SIZE = 320 * 480 * 4; // HVGA screen, ARGB8888
//flings和scrolls摩擦力度大小的系數(shù)
private static float SCROLL_FRICTION = 0.015f;
/**
* Max distance to over scroll for edge effects
*/
private static final int OVERSCROLL_DISTANCE = 0;
/**
* Max distance to over fling for edge effects
*/
private static final int OVERFLING_DISTANCE = 4;
}