![【移動應(yīng)用開發(fā)技術(shù)】Android中如何通過ViewDragHelper實現(xiàn)ListView的Item的側(cè)拉劃出效果_第1頁](http://file4.renrendoc.com/view/2b55a533e829d1fe0701b440f7656c89/2b55a533e829d1fe0701b440f7656c891.gif)
![【移動應(yīng)用開發(fā)技術(shù)】Android中如何通過ViewDragHelper實現(xiàn)ListView的Item的側(cè)拉劃出效果_第2頁](http://file4.renrendoc.com/view/2b55a533e829d1fe0701b440f7656c89/2b55a533e829d1fe0701b440f7656c892.gif)
![【移動應(yīng)用開發(fā)技術(shù)】Android中如何通過ViewDragHelper實現(xiàn)ListView的Item的側(cè)拉劃出效果_第3頁](http://file4.renrendoc.com/view/2b55a533e829d1fe0701b440f7656c89/2b55a533e829d1fe0701b440f7656c893.gif)
![【移動應(yīng)用開發(fā)技術(shù)】Android中如何通過ViewDragHelper實現(xiàn)ListView的Item的側(cè)拉劃出效果_第4頁](http://file4.renrendoc.com/view/2b55a533e829d1fe0701b440f7656c89/2b55a533e829d1fe0701b440f7656c894.gif)
![【移動應(yīng)用開發(fā)技術(shù)】Android中如何通過ViewDragHelper實現(xiàn)ListView的Item的側(cè)拉劃出效果_第5頁](http://file4.renrendoc.com/view/2b55a533e829d1fe0701b440f7656c89/2b55a533e829d1fe0701b440f7656c895.gif)
版權(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)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年臨街店鋪門面租賃合同范文(2篇)
- 2025年二手房轉(zhuǎn)讓協(xié)議參考樣本(三篇)
- 2025年倉儲設(shè)施的租賃合同(2篇)
- 2025年企業(yè)公司員工保密合同(2篇)
- 2025年度安全保衛(wèi)人員招聘與培訓合同
- 工廠搬遷運輸服務(wù)協(xié)議
- 廢品回收運輸合同
- 展覽館裝修居間協(xié)議
- 城市公交燃油供應(yīng)協(xié)議
- 機械設(shè)備搬遷居間協(xié)議
- 2023年心理咨詢師之心理咨詢師基礎(chǔ)知識考試題庫附完整答案【有一套】
- 證券公司信用風險和操作風險管理理論和實踐中金公司
- 一級建造師繼續(xù)教育最全題庫及答案(新)
- 2022年高考湖南卷生物試題(含答案解析)
- GB/T 20909-2007鋼門窗
- GB/T 17854-1999埋弧焊用不銹鋼焊絲和焊劑
- GB/T 15593-2020輸血(液)器具用聚氯乙烯塑料
- 直線加速器專項施工方案
- 儲能設(shè)備項目采購供應(yīng)質(zhì)量管理方案
- 2022年全國卷高考語文答題卡格式
- 復旦大學簡介 (課堂PPT)
評論
0/150
提交評論