您的位置:首页 > 其它

自定义ViewGroup(这里以自定义一个类似ViewPager的控件为例)

2015-07-18 10:36 399 查看
首先,我们得先要明白ViewGroup是什么,职责是什么?

ViewGroup就是用来放置View控件的的容器,职责是测量每一个子view的大小,还有摆放的位置。

* 1,写一个类继承于ViewGroup

* 2,重载onMeasure方法,用于测量的子View的大小

* 3,重载onLayout,用于安置子view的位置

到这里,一个ViewGroup就算自定义完成了,

下面的步骤是实现ViewGroup的功能

想要实现子类滑动的效果,就要借助Scroller这个类,这个类的使用请参考http://blog.csdn.net/qq_15949077/article/details/46940507

* 4.然后通过Gesturector手势识别器的ontuchEvent屏幕监听器即可实现页面的滑动

* 5,最后写一个内部接口,对外提供一个监听的set方法

看代码吧,这是一个实现类似viewPager的例子,里面的Scroller类作用很大

public class MyViewGroup extends ViewGroup {
GestureDetector gd;//手势识别器
Scroller scroll;
int itemID=0;

int firstX;
int lastX;
int dis;

boolean isFling;

itemChangelistener listener;

/**
* 事件中断器用的变量
*/
int downx;
int downy;
int movex;
int movey;
int distancex;
int distancey;

public MyViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub

scroll=new Scroller(context);

gd=new GestureDetector(context, new OnGestureListener() {

@Override
public boolean onSingleTapUp(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}

@Override
public void onShowPress(MotionEvent e) {
// TODO Auto-generated method stub

}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
// TODO Auto-generated method stub
if(itemID==0&&distanceX<0){

}
else if(itemID==getChildCount()-1&&distanceX>0){

}
else{
scrollBy((int) distanceX, 0);
}

return false;
}

@Override
public void onLongPress(MotionEvent e) {
// TODO Auto-generated method stub

}

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
// TODO Auto-generated method stub

isFling=true;

if(itemID==0&&velocityX>0){

}
else if(itemID==getChildCount()-1&&velocityX<0){

}
else if(velocityX>0){
itemID--;

}
else if(velocityX<0){
itemID++;

}

return false;
}

@Override
public boolean onDown(MotionEvent e) {
// TODO Auto-generated method stub

return false;
}
});
}

//测量子view的大小
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
for(int i=0;i<this.getChildCount();i++){
getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);

}

}

//指定子View的位置
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
for(int i=0;i<this.getChildCount();i++){
getChildAt(i).layout(i*getWidth(), 0, i*getWidth()+getWidth(), getHeight());
}
}

/**
* 事件中断器
* 比较上下和左右移动的距离谁大,大的就移动谁
*
*
* 如果返回值为true:则代表事件到这来被中断掉,就会执行自己的onTouchEvent,
* 注意,奇怪的是从move开始,而不是down,所以在down里有做处理的要注意,
* 而且这里有时会产生跳动bug,原因不知道,理解不了,(不是因为从move开始执行的原因,因为在down都没做处理的情况下也一样跳动)
* 解决这个bug的方法也很简单,在dowm的方法里将这个事件传给手势识别器就ok了
*
* 如果返回值为false:将不会执行onTouchEvent方法,而是把事件传给子控件
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub

boolean result=false;
switch(ev.getAction()){
case MotionEvent.ACTION_DOWN:
gd.onTouchEvent(ev);
downx=(int) ev.getX();
downy=(int) ev.getY();

break;
case MotionEvent.ACTION_MOVE:

movex=(int) ev.getX();
movey=(int) ev.getY();
distancex=Math.abs(movex-downx);
distancey=Math.abs(movey-downy);

if(distancex>distancey&&distancex>10){
result= true;
}
else{
result= false;
}
//			else if(distancex<distancey&&distancey>10){
//				result= false;
//			}

break;

}
return result;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
gd.onTouchEvent(event);

switch(event.getAction()){
case MotionEvent.ACTION_DOWN:

firstX=(int)event.getX();

break;
case MotionEvent.ACTION_MOVE:

break;
case MotionEvent.ACTION_UP:

lastX=(int) event.getX();
dis=lastX-firstX;
if(!isFling){

if(itemID==0&&dis>0){

}
else if(itemID==getChildCount()-1&&dis<0){

}
else if(dis>0&&dis>getWidth()/5){
itemID--;
}
else if(dis<0&&Math.abs(dis)>getWidth()/5){
itemID++;
}

}

myScrollto(itemID);
break;
}

return true;
}

/**
* 开始移动
* @param ItemID
*/
public void myScrollto(int itemID){
if(listener!=null){
listener.itemID(itemID);
}
int dis=itemID*getWidth()-getScrollX();

scroll.startScroll(getScrollX(), 0, dis, 0, Math.abs(dis));
invalidate();

}

/**
* 执行invalidata方法后回调
*/
@Override
public void computeScroll() {
// TODO Auto-generated method stub
super.computeScroll();
if(scroll.computeScrollOffset()){
scrollTo(scroll.getCurrX(), 0);
invalidate();
}
else{
isFling=false;
}
}

/**
* 对外部提供的设置指定页面的方法
* @param itemID
*/
public void setItemID(int itemID){
this.itemID=itemID;
myScrollto(itemID);
}

/**
* 对外提供一个监听页面改变后获取id的方法
* @param listener
*/
public void setonItemChangelistener(itemChangelistener listener){
this.listener=listener;
}

/**
* 对外提供的滑动到哪个页面id的接口
* @author Administrator
*
*/
interface itemChangelistener{
void itemID(int ItemID);
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: