【移動應(yīng)用開發(fā)技術(shù)】Android中如何通過ViewDragHelper實現(xiàn)ListView的Item的側(cè)拉劃出效果_第1頁
【移動應(yīng)用開發(fā)技術(shù)】Android中如何通過ViewDragHelper實現(xiàn)ListView的Item的側(cè)拉劃出效果_第2頁
【移動應(yīng)用開發(fā)技術(shù)】Android中如何通過ViewDragHelper實現(xiàn)ListView的Item的側(cè)拉劃出效果_第3頁
【移動應(yīng)用開發(fā)技術(shù)】Android中如何通過ViewDragHelper實現(xiàn)ListView的Item的側(cè)拉劃出效果_第4頁
【移動應(yīng)用開發(fā)技術(shù)】Android中如何通過ViewDragHelper實現(xiàn)ListView的Item的側(cè)拉劃出效果_第5頁
已閱讀5頁,還剩12頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

【移動應(yīng)用開發(fā)技術(shù)】Android中如何通過ViewDragHelper實現(xiàn)ListView的Item的側(cè)拉劃出效果

/upload/information/20200623/125/126976.gif實現(xiàn)該自定義控件的大體步驟如下:/upload/information/20200623/125/126977.png/upload/information/20200623/125/126978.png以上2部分就是該自定義控件要包含的2個直接子View./**

*

Created

by

mChenys

on

2015/12/26.

*/

public

class

SwipeLayout

extends

FrameLayout

{

private

ViewDragHelper.Callback

mCallback;

private

ViewDragHelper

mDragHelper;

private

View

mBackView;

//item的側(cè)邊布局

private

View

mFrontView;//當前顯示的item布局

private

int

mWidth;

//屏幕的寬度,mFrontView的寬度

private

int

mHeight;

//mFrontView的高度

private

int

mRange;//mFrontView側(cè)拉時向左移動的最大距離,即mBackView的寬度

public

SwipeLayout(Context

context)

{

this(context,

null);

}

public

SwipeLayout(Context

context,

AttributeSet

attrs)

{

this(context,

attrs,

0);

}

public

SwipeLayout(Context

context,

AttributeSet

attrs,

int

defStyleAttr)

{

super(context,

attrs,

defStyleAttr);

init();

}

//1.初始ViewDragHelper

private

void

init()

{

mCallback

=

new

ViewDragHelper.Callback()

{

//3.在回調(diào)方法中處理觸摸事件

@Override

public

boolean

tryCaptureView(View

child,

int

pointerId)

{

return

true;

//允許所有子控件的滑動

}

//設(shè)定滑動的邊界值

@Override

public

int

clampViewPositionHorizontal(View

child,

int

left,

int

dx)

{

if

(child

==

mFrontView)

{

//前景View的滑動范圍是(0~

-mRange)

if

(left

>

0)

{

left

=

0;

}

else

if

(left

<

-mRange)

{

left

=

-mRange;

}

}

if

(child

==

mBackView)

{

//背景View的滑動范圍是(mWidth

-

mRange

~

mWidth)

if

(left

>

mWidth)

{

left

=

mWidth;

}

else

if

(left

<

(mWidth

-

mRange))

{

left

=

mWidth

-

mRange;

}

}

//返回修正過的建議值

return

left;

}

//監(jiān)聽View的滑動位置的改變,同步前景View和背景View的滑動事件

@Override

public

void

onViewPositionChanged(View

changedView,

int

left,

int

top,

int

dx,

int

dy)

{

if

(changedView

==

mFrontView)

{

//當滑動前景View時,也需要滑動背景View

mBackView.offsetLeftAndRight(dx);

}

else

if

(changedView

==

mBackView)

{

//當滑動背景View時,也需要滑動前景View

mFrontView.offsetLeftAndRight(dx);

}

//

兼容老版本

invalidate();

}

//處理釋放后的開啟和關(guān)閉動作

@Override

public

void

onViewReleased(View

releasedChild,

float

xvel,

float

yvel)

{

if

(xvel

<

0)

{

//有向左滑動的速度,則打開

open();

}

else

if

(xvel

==

0

&&

mFrontView.getLeft()

<

-mRange

/

2.0f)

{

//前景View向左滑動的left小于背景View寬度一半的負值時,打開

open();

}

else

{

//其他情況為關(guān)閉

close();

}

}

};

mDragHelper

=

ViewDragHelper.create(this,

mCallback);

}

//2.傳遞觸摸事件

@Override

public

boolean

onInterceptTouchEvent(MotionEvent

ev)

{

return

mDragHelper.shouldInterceptTouchEvent(ev);

}

@Override

public

boolean

onTouchEvent(MotionEvent

event)

{

try

{

mDragHcessTouchEvent(event);

}

catch

(Exception

e)

{

e.printStackTrace();

}

return

true;

}

//獲取子控件的引用

@Override

protected

void

onFinishInflate()

{

super.onFinishInflate();

mBackView

=

getChildAt(0);

//獲取背景View,即展示數(shù)據(jù)的Item的右邊隱藏的側(cè)滑布局

mFrontView

=

getChildAt(1);//獲取前景View,即展示數(shù)據(jù)的Item

}

//獲取子控件的相關(guān)寬高信息

@Override

protected

void

onSizeChanged(int

w,

int

h,

int

oldw,

int

oldh)

{

super.onSizeChanged(w,

h,

oldw,

oldh);

mWidth

=

mFrontView.getMeasuredWidth();

mHeight

=

mFrontView.getMeasuredHeight();

mRange

=

mBackView.getMeasuredWidth();

}

//確定子控件的初始位置

@Override

protected

void

onLayout(boolean

changed,

int

left,

int

top,

int

right,

int

bottom)

{

super.onLayout(changed,

left,

top,

right,

bottom);

layoutChildView(false);

}

/**

*

放置子控件的位置

*

*

@param

isOpen

是否是打開前景View,true打開,false關(guān)閉

*/

private

void

layoutChildView(boolean

isOpen)

{

//計算前景View的位置,將坐標信息封裝到矩形中

Rect

fontRect

=

computerFontViewRect(isOpen);

//擺放前景View

mFrontView.layout(fontRect.left,

fontRect.top,

fontRect.right,

fontRect.bottom);

//擺放背景View,left坐標是前景View的right坐標

int

left

=

fontRect.right;

mBackView.layout(left,

0,

left

+

mRange,

mHeight);

//由于上面是后擺放背景View,所以會覆蓋前景View,因此需要通過下面的方式將前景View顯示在前面

bringChildToFront(mFrontView);

}

/**

*

計算前景View的坐標

*

*

@param

isOpen

是否是打開前景View

*

@return

*/

private

Rect

computerFontViewRect(boolean

isOpen)

{

int

left

=

isOpen

?

-mRange

:

0;

return

new

Rect(left,

0,

left

+

mWidth,

mHeight);

}

/**

*

打開側(cè)邊欄mBackView,默認平滑打開

*/

public

void

open()

{

open(true);

}

/**

*

打開側(cè)邊欄mBackView

*

*

@param

isSmooth

是否平滑打開

*/

public

void

open(boolean

isSmooth)

{

if

(isSmooth)

{

if

(mDragHelper.smoothSlideViewTo(mFrontView,

-mRange,

0))

{

//動畫在繼續(xù)

ViewCompat.postInvalidateOnAnimation(this);

}

}

else

{

layoutChildView(true);

}

}

/**

*

關(guān)閉側(cè)邊欄mBackView,默認平滑關(guān)閉

*/

public

void

close()

{

close(true);

}

/**

*

關(guān)閉側(cè)邊欄mBackView

*

*

@param

isSmooth

是否平滑關(guān)閉

*/

public

void

close(boolean

isSmooth)

{

if

(isSmooth)

{

if

(mDragHelper.smoothSlideViewTo(mBackView,

mWidth,

0))

{

//動畫在繼續(xù)

ViewCompat.postInvalidateOnAnimation(this);

}

}

else

{

layoutChildView(false);

}

}

@Override

public

void

computeScroll()

{

puteScroll();

if

(mDragHelper.continueSettling(true))

{

//動畫還在繼續(xù)

ViewCompat.postInvalidateOnAnimation(this);

}

}

}<?xml

version="1.0"

encoding="utf-8"?>

<.csdn.blog.myswipelayout.view.SwipeLayout

xmlns:android="/apk/res/android"

android:id="@+id/sl"

android:layout_width="match_parent"

android:layout_height="60dp"

android:minHeight="60dp"

android:background="#44000000"

>

<!--后置布局-->

<LinearLayout

android:layout_width="wrap_content"

android:layout_height="match_parent"

android:orientation="horizontal"

>

<TextView

android:id="@+id/tv_call"

android:layout_width="60dp"

android:layout_height="match_parent"

android:background="#666666"

android:gravity="center"

android:text="Edit"

android:textColor="#ffffff"

/>

<TextView

android:id="@+id/tv_del"

android:layout_width="60dp"

android:layout_height="match_parent"

android:background="#ff0000"

android:gravity="center"

android:text="Delete"

android:textColor="#ffffff"

/>

</LinearLayout>

<!--前景布局-->

<LinearLayout

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="#44ffffff"

android:gravity="center_vertical"

android:orientation="horizontal"

>

<ImageView

android:id="@+id/iv_image"

android:layout_width="40dp"

android:layout_height="40dp"

android:layout_marginLeft="15dp"

android:src="@drawable/head_1"

/>

<TextView

android:id="@+id/tv_name"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginLeft="15dp"

android:text="Name"

/>

</LinearLayout>

</.csdn.blog.myswipelayout.view.SwipeLayout>/upload/information/20200623/125/126979.gif需要考慮2點:/**

*

側(cè)拉SwipeLayout的監(jiān)聽

*

Created

by

mChenys

on

2015/12/26.

*/

public

interface

SwipeViewListener

{

//關(guān)閉

void

onClose(SwipeLayout

mSwipeLayout);

//打開

void

onOpen(SwipeLayout

mSwipeLayout);

//正在側(cè)拉

void

onDraging(SwipeLayout

mSwipeLayout);

//開始要去關(guān)閉

void

onStartClose(SwipeLayout

mSwipeLayout);

//開始要去開啟

void

onStartOpen(SwipeLayout

mSwipeLayout);

}//以下是定義SwipeLayout的打開,關(guān)閉,滑動的3種狀態(tài)

public

enum

Status

{

CLOSE,

OPEN,

DRAGING;

}

//默認關(guān)閉

private

Status

mStatus

=

Status.CLOSE;

//滑動的監(jiān)聽器

private

SwipeViewListener

mSwipeViewListener;

//設(shè)置監(jiān)聽器

public

void

setSwipeViewListener(SwipeViewListener

swipeViewListener)

{

mSwipeViewListener

=

swipeViewListener;

}/**

*

處理滑動,打開,關(guān)閉的3種情況

*

在onViewPositionChanged

調(diào)用

*/

private

void

dispatchSwipeEvent()

{

if

(mSwipeViewListener

!=

null)

{

mSwipeViewListener.onDraging(this);

}

//記錄上一次的狀態(tài)

Status

preStatus

=

mStatus;

//獲取當前的狀態(tài)

mStatus

=

getCurrStatus();

if

(preStatus

!=

mStatus

&&

null

!=

mSwipeViewListener)

{

//說明有狀態(tài)發(fā)生變化

if

(mStatus

==

Status.CLOSE)

{

//關(guān)閉

mSwipeViewListener.onClose(this);

}

else

if

(mStatus

==

Status.OPEN)

{

//打開

mSwipeViewListener.onOpen(this);

}

else

if

(mStatus

==

Status.DRAGING)

{

//這里有2中情況,要么要打開,要么要關(guān)閉

if

(preStatus

==

Status.CLOSE)

{

//如果之前是關(guān)閉的,那么就是要打開

mSwipeViewListener.onStartOpen(this);

}

else

if

(preStatus

==

Status.OPEN)

{

//如果之前是打開,那么就是要關(guān)閉

mSwipeViewListener.onStartClose(this);

}

}

}

}

/**

*

獲取當前的狀態(tài)

*

*

@return

*/

private

Status

getCurrStatus()

{

int

left

=

mFrontView.getLeft();

if

(left

==

0)

{

return

Status.CLOSE;

}

else

if

(left

==

-mRange)

{

return

Status.OPEN;

}

return

Status.DRAGING;

}public

class

MainActivity

extends

AppCompatActivity

{

private

List<String>

mData

=

new

ArrayList<>();//數(shù)據(jù)集合

@Override

protected

void

onCreate(Bundle

savedInstanceState)

{

super.onCreate(savedInstanceState);

//獲取數(shù)據(jù),注意:Arrays.asList返回的并不是一個java.util.ArrayList,而是一個Arrays類的內(nèi)部類,該List實現(xiàn)是不能進行增刪操作的

//因此必須再包裝一下

mData

=

new

ArrayList<>(Arrays.asList(Constant.NAME));

ListView

listView

=

new

ListView(this);

listView.setAdapter(mAdapter);

setContentView(listView);

}

//自定義適配器

private

BaseAdapter

mAdapter

=

new

BaseAdapter()

{

//標記當前打開的SwipeLayout的集合

private

List<SwipeLayout>

mOpenItem

=

new

ArrayList<>();

@Override

public

int

getCount()

{

return

mData.size();

}

@Override

public

String

getItem(int

position)

{

return

mData.get(position);

}

@Override

public

long

getItemId(int

position)

{

return

position;

}

@Override

public

View

getView(final

int

position,

View

convertView,

ViewGroup

parent)

{

ViewHolder

holder

=

null;

if

(null

==

convertView)

{

holder

=

new

ViewHolder();

convertView

=

View.inflate(MainActivity.this,

R.layout.item_list,

null);

holder.mSwipeLayout

=

(SwipeLayout)

convertView;

holder.tvName

=

(TextView)

convertView.findViewById(R.id.tv_name);

holder.tvDel

=

(TextView)

convertView.findViewById(R.id.tv_del);

holder.tvEdit

=

(TextView)

convertView.findViewById(R.id.tv_edit);

convertView.setTag(holder);

}

else

{

holder

=

(ViewHolder)

convertView.getTag();

}

//設(shè)置側(cè)拉監(jiān)聽

holder.mSwipeLayout.setSwipeViewListener(getSwipeViewListener());

holder.tvName.setText(getItem(position));

holder.tvDel.setOnClickListener(new

View.OnClickListener()

{

@Override

public

void

onClick(View

v)

{

//刪除

mData.remove(position);

mAdapter.notifyDataSetChanged();

}

});

holder.tvEdit.setOnClickListener(new

View.OnClickListener()

{

@Override

public

void

onClick(View

v)

{

ToastUtils.showToast(MainActivity.this,"編輯");

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論