繼承viewgroup製作的自定義元件常常是一些布局或者組合元件:
和view的自定義元件類似,需要重寫onmeause和onlayout測量元件的寬高和布局,因為viewgruop裡面包含了子元件,所有在測量和定位的時候都是以子元件為中心進行測量和定位;不需要重寫ondraw方法,因為viewgroup是乙個容器類,我們只需要呼叫它的子元件的draw方法即可
還要注意事件分發時,要重寫onintecepttouchevent,判斷事件來臨時需不需要向子元件傳遞下去;
下面以一下側滑元件為例:
我們建立的元件由兩個子元件組合而成,該元件可以左右側滑,而裡面的子元件「選單欄」可以上下滑動;
1. 建立乙個類,繼承viewgroup,重寫onmeasure和onlayout和構造器
measure
選單欄( 寬度等於自己的真實寬度 高度和父類的控制項相同)
主介面 (寬高都和父控制項相同)
layout:
選單欄 (右邊為 0 ,0 左邊為 -自己寬度長 0 )
主介面 (和父類的相同)
2. 監控事件分發:
當我們在螢幕上滑動時,如何區分是左右滑動還是數值滑動,傳遞給viewgroup還是它的子類scrollview;
需要乙個判斷使用者滑動的長度,大於此長度就認為是滑動;此長度 == viewconfiguration.get(context).getscaletouchslop
用上面的長度,在onintecepttouchevent的move動作中,如果x軸上變化距離大於此變數並且y小於此長度就是水平滑動,返回true,阻斷事件分發;反之fasle
3. 左右的滑動效果
滑動效果的主要在ontouchevent方法裡面完成:
switch(down move up)三個動作,down裡面記錄初始的x座標,move裡面用當前座標減去初始座標就是x軸的位移;
在move中,
view.getscrollx()獲取開始接觸螢幕時的座標,此座標+移動的x軸座標差就是移動後的座標,判斷此座標如果大於0直接scrollto(0,0);如果小於-選單欄的,則移動到左邊的選單欄
view.scrollto(int x,int y)滑動到具體的xy座標
view.scrollby(int dx,int dy); 滑動了多少距離 當前座標加dx和dy
慢慢滑動的效果:
在我們抬起手指,檢視當前的x軸座標,如果小於選單欄/2,往左慢慢滑動選單欄,大於選單欄/2,慢慢滑動右邊
借助scroller輔助類幫助滑動:
startscroll(int startx, int starty, int dx, int dy, int duration) 在規定的時間內完成滑動,模擬滑動,但此方法不會使view滑動
computescrolloffset() 如果模擬沒完成,返回true,完成則false
//重寫view的方法,drawchild -- >> child.draw() -->> computescroll
computescroll()
在此方法中,我們通過判斷computescrolloffset看模擬是否完成,如果沒完成就滑動元件scrollto(scroller.getcurrx,0)然後呼叫 invalidate重畫draw即可實現再次呼叫此方法,直到模擬完成
public
class
sildview
extends
viewgroup
/*測量布局*/
@override
protected
void
onmeasure(int widthmeasurespec, int heightmeasurespec)
/*布局下去*/
@override
protected
void
onlayout(boolean arg0, int l, int t, int r, int b)
@override
public
boolean
ontouchevent(motionevent event) else
if(scrollx > 0)else
lastx = currentx;
break;
case motionevent.action_up:
int midx = -this.getchildat(0).getwidth()/2;
int x = getscrollx();
if(x < midx)else
switchui(viewflag);
break;
}return
true;
}/**
* 選單介面和功能介面的切換
* true為功能介面
* false為選單介面
* 注:滑動是從當前介面滑動到目標位置,而不是直接跳轉到目標position
*/public
void
switchui(boolean flagui)else
//模擬滑動過程
scroller.startscroll(currentx, 0, dx, 0,math.abs(dx)*5);
invalidate(); //此函式會經過viewgroup下面的drawchild()-->child.draw()-->computescroll()最終完成滑動並顯示出來
}@override
public
void
computescroll()
}@override
public
boolean
onintercepttouchevent(motionevent ev)
break;
case motionevent.action_up:
log.i(tag, "action_up: ");
break;
}return
super.onintercepttouchevent(ev);
}//功能介面是否開啟
public
boolean
isshown()
//開啟功能介面
public
void
showview()
//掩藏功能介面
public
void
hideview()
}
自定義ViewGroup之側滑選單
最近pm2.5對側滑選單比較感興趣,很多頁面上都用到了側滑選單,之前也在網上看到了很多關於側滑,有自定義recyclerview,也有自定義item的,但是當自己真正去用的時候,發現有很多問題,所以打算自己參考網上的思路自己寫乙個,果然,看花容易繡花難,寫的很艱辛,不過最後還是實現了,下面看看效果圖...
自定義ViewGroup(一)
1 概述 viewgroup是乙個view的容器,他可以給出childview的測量模式和測量其寬高,他的作用非常重要。childview測量模式 exactly 表示設定了精確的值,一般當childview設定其寬 高為精確值 match parent時,viewgroup會將其設定為exactl...
ViewGroup 自定義控制項
自定義viewgroup這篇文章是針對自定義layoutmanager來寫的,提取出相關自定義的相同點。所有的自定義都可以歸結為在父控制項裡面放置子控制項。一 繼承類 viewgroup 繼承之後需要實現構造,由於一般是在xml中引入所有需要實現以下構造 viewgroup context cont...