這次跟大家介紹怎么簡單的實現(xiàn)類似QQ消息Item的左右滑動菜單的實現(xiàn)。首先見效果圖先:
這就實現(xiàn)了ListView或RecyclerView加載的item的View實現(xiàn)側(cè)滑菜單寥假。至于這么實現(xiàn)市框,很簡單就是通過繼承HorizontalScrollView,再判斷滑動的距離以滑到對應(yīng)的View或菜單昧旨。具體如下:
首先拾给,在item的界面布局方面如下:
<?xml version="1.0" encoding="utf-8"?>
<com.example.jack.listviewitemscroll.widget.ScrollListViewItem
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/leftbutton"/>
<include layout="@layout/context_view"/>
<include layout="@layout/rightbutton"/>
</LinearLayout>
</com.example.jack.listviewitemscroll.widget.ScrollListViewItem>
就是ScrollListViewItem包裹著LinearLayout里面的三個View,分別是左菜單,內(nèi)容和右菜單對應(yīng)的View兔沃。最為重點的就是ScrollListViewItem這個類蒋得,這就是我們繼承HorizontalScrollView類所自定義的控制菜單滑動的類。
這個類的源碼如下:
public class ScrollListViewItem extends HorizontalScrollView{
private static int ScreenWidth=0;
private static int MenuWidth=0;
private static int HalfMenuWidth=0;
private boolean operateLeft=false;
private boolean operateRight=false;
private boolean once;
ViewGroup left;
ViewGroup centre;
ViewGroup right;
public ScrollListViewItem(Context context) {
this(context, null);
}
public ScrollListViewItem(Context context, AttributeSet attrs) {
super(context, attrs,0);
}
public ScrollListViewItem(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr,0);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if(!once){
LinearLayout linearLayout=(LinearLayout)getChildAt(0);
left=(ViewGroup)linearLayout.getChildAt(0);
centre=(ViewGroup)linearLayout.getChildAt(1);
right=(ViewGroup)linearLayout.getChildAt(2);
ScreenWidth= ScreenUtils.getScreenWidth(getContext());
MenuWidth=ScreenWidth/4;
HalfMenuWidth=MenuWidth/2;
left.getLayoutParams().width=MenuWidth;
centre.getLayoutParams().width=ScreenWidth;
right.getLayoutParams().width=MenuWidth;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if(changed){
this.scrollTo(MenuWidth,0);
once=true;
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch(ev.getAction()){
case MotionEvent.ACTION_UP:
//在左側(cè)
if(operateLeft){
if(getScrollX()<HalfMenuWidth){
//滑到左最末尾
this.scrollTo(0, 0);
}else if(getScrollX()>HalfMenuWidth&&getScrollX()<MenuWidth+HalfMenuWidth){
//滑到中間
this.scrollTo(MenuWidth, 0);
}else{
this.scrollTo(MenuWidth * 2, 0);
}
}
//向右側(cè)
if(operateRight){
if(getScrollX()>MenuWidth+HalfMenuWidth){
//滑到最右
this.scrollTo(MenuWidth + MenuWidth, 0);
}else if(getScrollX()>HalfMenuWidth&&getScrollX()<MenuWidth+HalfMenuWidth){
//滑到中間
this.scrollTo(MenuWidth, 0);
}else{
//滑到最左
this.scrollTo(0, 0);
}
}
return true;
}
return super.onTouchEvent(ev);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if(l>MenuWidth){
operateLeft=false;
operateRight=true;
}else{
operateLeft=true;
operateRight=false;
}
}
}
在onMeasure()這個自定義View的測量方法里乒疏,我們首先拿到左菜單额衙,內(nèi)容,右菜單所對用的view,即left,centre,right這三個View,然后獲取屏幕的寬度怕吴,動態(tài)設(shè)定菜單的寬度為屏幕寬度的四分之一窍侧,而內(nèi)容的寬度就是整個屏幕的寬度毕源,即
left.getLayoutParams().width=MenuWidth;
centre.getLayoutParams().width=ScreenWidth;
right.getLayoutParams().width=MenuWidth;
然后我們在onLayout()方法里對這三個View進(jìn)行定位怠堪,即讓他滑到內(nèi)容的那個View糠涛。
然后回調(diào)onScrollChanged(int l, int t, int oldl, int oldt)方法绞绒,當(dāng)l大于菜單寬度時是右側(cè)娘纷,當(dāng)l小于菜單寬度時是右側(cè)甥厦。(注:l是屏幕最右邊到整個View最右邊的距離)
其次就是最重要的onTouchEvent(MotionEvent ev)方法了玻靡。(注:是屏幕最右邊到整個View最右邊的距離).當(dāng)operateLeft==true的時候,滑動在操作在左側(cè),當(dāng)getScrollX()<HalfMenuWidth
,即在最左向右滑還不到菜單的二分之一寬度時冠桃,恢復(fù)原狀煞肾,即this.scrollTo(0, 0);
咧织,當(dāng)getScrollX()>HalfMenuWidth&&getScrollX()<MenuWidth+HalfMenuWidth
,即最左向右滑大于菜單的二分之一寬度但卻小于左菜單加右菜單一半的寬度,所以只能滑到內(nèi)容區(qū)域籍救,即this.scrollTo(MenuWidth, 0);
习绢,這兩種情況除外都會滑到最后邊的菜單,所以this.scrollTo(MenuWidth * 2, 0)
;
同樣的道理蝙昙,當(dāng)operateRight==true時闪萄,getScrollX()>MenuWidth+HalfMenuWidth
時梧却,即在最右菜單但滑動的距離小于菜單寬度的一半,所以只能恢復(fù)原狀即this.scrollTo(MenuWidth + MenuWidth, 0);
,當(dāng)getScrollX()>HalfMenuWidth&&getScrollX()<MenuWidth+HalfMenuWidth
時桃煎,即滑動大于菜單一半但是卻小于左菜單加右菜單一半的寬度篮幢,所以是內(nèi)容區(qū)域,即滑動 this.scrollTo(MenuWidth, 0);为迈,除這兩種情況都是要滑到最左邊的菜單三椿,即 this.scrollTo(0, 0);。到此整個流程就講完了葫辐。
最后奉上源碼