Android ViewDragHelper使用方法詳解
幫我們實(shí)現(xiàn)各種類(lèi)型的復(fù)雜手勢(shì)操作。其實(shí)例通過(guò)靜態(tài)工廠(chǎng)創(chuàng)建ViewDragHelper一般用在一個(gè)自定義ViewGroup的內(nèi)部。
初始化操作
private ViewDragHelper mDrragHelper;
public SlideViewGroup(@NonNull Context context) {
this(context,null);
}
public SlideViewGroup(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public SlideViewGroup(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
super(context, attrs, defStyleAttr);
mDrragHelper=ViewDragHelper.create(this,1.0f,mCallback);
}
mDrragHelper=ViewDragHelper.create(this,1.0f,mCallback);第一個(gè)操作表示當(dāng)前操作的對(duì)象,第二個(gè)參數(shù)為手勢(shì)操作敏感度,
第三個(gè)參數(shù)為我們手勢(shì)處理的毀掉接口
我們需要先在view事件分發(fā)時(shí)把手勢(shì)操作交給ViewFragHelper
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
//交給viewdrag去攔截
//事件分發(fā)攔截
float x=0;
int action = event.getAction();
switch(action){
case MotionEvent.ACTION_DOWN:
x =event.getX();
break;
// return false;
case MotionEvent.ACTION_MOVE:
if (STATE==0&getX()-x<0){
return mDrragHelper.shouldInterceptTouchEvent(event);
}else if (STATE==1){
return mDrragHelper.shouldInterceptTouchEvent(event);
}
break;
}
return false;
}
//boolean control=true;//控制downx的初始化
@Override
public boolean onTouchEvent(MotionEvent event) {
mDrragHelper.processTouchEvent(event);
//if (control)
float downX=0;
if (event.getAction()==MotionEvent.ACTION_DOWN){
downX=event.getRawX();
if (STATE==1){
//if (event.getRawX()>0&downX<leftWidth-rightViewWidth)
//close();
// Toast.makeText(this.getContext(), "leftWidth"+leftWidth+"rawx"+event.getRawX(), Toast.LENGTH_SHORT).show();
}
}
if (event.getAction()==MotionEvent.ACTION_UP){
//Toast.makeText(this.getContext(), "downx"+downX, Toast.LENGTH_SHORT).show();
//點(diǎn)擊刪除//&downX>leftWidth-rightViewWidth&downX<leftWidth-rightViewWidth/2
// Toast.makeText(this.getContext(), "刪除1", Toast.LENGTH_SHORT).show();
if (STATE==1&event.getRawX()>leftWidth-rightViewWidth&event.getRawX()<leftWidth-rightViewWidth/2){
// Toast.makeText(this.getContext(), "刪除2", Toast.LENGTH_SHORT).show();
if (skipListener!=null){
// Toast.makeText(this.getContext(), "刪除3", Toast.LENGTH_SHORT).show();
skipListener.onDelete();
}
// Toast.makeText(this.getContext(), "刪除", Toast.LENGTH_SHORT).show();
}
//點(diǎn)擊刪除&downX>leftWidth-rightViewWidth/2&downX<leftWidth-rightViewWidth
if (STATE==1&event.getRawX()>leftWidth-rightViewWidth/2&event.getRawX()<leftWidth){
// Toast.makeText(this.getContext(), "修改", Toast.LENGTH_SHORT).show();
if (skipListener!=null){
skipListener.onDefine();
}
}
}
return true;
}
重點(diǎn)在這兩句
mDrragHelper.shouldInterceptTouchEvent(event); mDrragHelper.processTouchEvent(event);
我們可以在onInterceptTouchEvent決定什么時(shí)候把事件交給我們的手勢(shì)操作類(lèi)
然后是回調(diào)類(lèi)
private ViewDragHelper.Callback mCallback=new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==leftView;
}
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
if (left>=0)
return 0;
if (left<-rightViewWidth)
return -rightViewWidth;
return left;
}
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
rightView.layout(leftWidth + left, 0, leftWidth + rightViewWidth, viewHeight);
/* if (left<0&left>rightViewWidth/2){
mDrragHelper.smoothSlideViewTo(leftView,left,0);
mDrragHelper.smoothSlideViewTo(rightView,left,0);
}*/
/* if (left>=-(leftWidth+rightViewWidth)) {
rightView.layout(leftWidth + left, 0, leftWidth + rightViewWidth, viewHeight);
}
if (left<-(leftWidth+rightViewWidth)){
rightView.layout(leftWidth, 0, leftWidth + rightViewWidth, viewHeight);
}*/
}
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
Log.i("left xvel",xvel+"y"+yvel);
if (xvel<0){
open();/* mDrragHelper.smoothSlideViewTo(rightView,rightViewWidth/2,0);*/
}else if (leftView.getLeft()<-rightViewWidth/2)
{open();}else {
// Log.i("left open","open");
close();
}
}
@Override
public int getViewHorizontalDragRange(View child) {
return -rightViewWidth;
}
@Override
public void onEdgeTouched(int edgeFlags, int pointerId) {
super.onEdgeTouched(edgeFlags, pointerId);
}
};
tryCaptureView的返回值表示我們?cè)试S操作的child
clampViewPositionHorizontal()方法的默認(rèn)返回值為0,返回值代表水平移動(dòng)的距離,也就是left值,當(dāng)返回left值時(shí),我們操作的view就會(huì)跟著我們的拖動(dòng)而移動(dòng),當(dāng)然還有數(shù)值方向的方法,如果需要也可以重寫(xiě)豎直操作的方法
onViewPositionChanged()方法就是當(dāng)我們移動(dòng)時(shí)就會(huì)回調(diào)這個(gè)方法,此處的left參數(shù)就是水平移動(dòng)返回的left,dx就是水平距離相對(duì)變化
onViewRelased()方法就是手指抬起時(shí)(釋放)時(shí)回調(diào)的方法,xvel每秒鐘水平速度速度慢時(shí)為0,單位為像素,yvel為每秒鐘豎直方向的速度。速度有正負(fù)之分
滑動(dòng)邊緣:
分為滑動(dòng)左邊緣還是右邊緣:EDGE_LEFT和EDGE_RIGHT,下面的代碼設(shè)置了可以處理滑動(dòng)左邊緣:
mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
假如如上設(shè)置,onEdgeTouched方法會(huì)在左邊緣滑動(dòng)的時(shí)候被調(diào)用,這種情況下一般都是沒(méi)有和子view接觸的情況。
@Override
public void onEdgeTouched(int edgeFlags, int pointerId) {
super.onEdgeTouched(edgeFlags, pointerId);
Toast.makeText(getContext(), "edgeTouched", Toast.LENGTH_SHORT).show();
}
如果你想在邊緣滑動(dòng)的時(shí)候根據(jù)滑動(dòng)距離移動(dòng)一個(gè)子view,可以通過(guò)實(shí)現(xiàn)onEdgeDragStarted方法,并在onEdgeDragStarted方法中手動(dòng)指定要移動(dòng)的子View
@Override
public void onEdgeDragStarted(int edgeFlags, int pointerId) {
mDragHelper.captureChildView(mDragView2, pointerId);
}
滑動(dòng)
手指在當(dāng)前view的下邊緣就可以滑動(dòng)
下面看一個(gè)我在ontochEvent調(diào)用的方法
public void open(){
if (listener!=null){
listener.onOpen(this);
}
if (mDrragHelper.smoothSlideViewTo(leftView,-rightViewWidth,0))
ViewCompat.postInvalidateOnAnimation(SlideViewGroup.this);
STATE=1;
}
就是平滑滑動(dòng),
ViewCompat.postInvalidateOnAnimation(SlideViewGroup.this)
上面那個(gè)方法就是刷新布局(重繪操作)
然后會(huì)回調(diào)次viewgroup的computerScroll
@Override
public void computeScroll() {
if (mDrragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
其實(shí)滑動(dòng)本身還是調(diào)用的scrollto跟據(jù)時(shí)間百分比移動(dòng),根據(jù)比例移動(dòng)固定距離后就不移動(dòng)了,所以我們需要重復(fù)刷新,需要判斷臨界條件,可能是時(shí)間可能是距離,可以點(diǎn)進(jìn)continueSetting方法返回false代表動(dòng)畫(huà)完成,進(jìn)去一看就明白了,需要判斷滑動(dòng)事件是否完成,如果完成就不再刷新,如果沒(méi)完成就刷新。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android利用ViewDragHelper輕松實(shí)現(xiàn)拼圖游戲的示例
- Android ViewDragHelper仿淘寶拖動(dòng)加載效果
- Android ViewDragHelper使用介紹
- Android 中通過(guò)ViewDragHelper實(shí)現(xiàn)ListView的Item的側(cè)拉劃出效果
- Android ViewDragHelper完全解析 自定義ViewGroup神器
- Android基于ViewDragHelper仿QQ5.0側(cè)滑界面效果
- Android使用ViewDragHelper實(shí)現(xiàn)仿QQ6.0側(cè)滑界面(一)
- Android使用ViewDragHelper實(shí)現(xiàn)QQ6.X最新版本側(cè)滑界面效果實(shí)例代碼
相關(guān)文章
Android SharedPreferences實(shí)現(xiàn)記住密碼和自動(dòng)登錄
這篇文章主要為大家詳細(xì)介紹了Android SharedPreferences實(shí)現(xiàn)記住密碼和自動(dòng)登錄,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05
詳解如何在Flutter中用小部件創(chuàng)建響應(yīng)式布局
由于Flutter的跨平臺(tái)、單一代碼庫(kù)的能力,了解屏幕管理以防止像柔性溢出錯(cuò)誤或糟糕的用戶(hù)界面設(shè)計(jì)這樣的問(wèn)題是至關(guān)重要的。本文將探討如何用靈活和擴(kuò)展的小部件創(chuàng)建響應(yīng)式布局,需要的可以參考一下2022-02-02
Android 自動(dòng)化測(cè)試經(jīng)驗(yàn)分享 深入U(xiǎn)iScrollable
UiScrollable是一個(gè)UiCollection(這東西還沒(méi)搞懂),我們可以使用它,在可滑動(dòng)的頁(yè)面(水平滑動(dòng)或上下滑動(dòng)都可以)上查找我們想要的控件(item)2013-05-05

