最近,做了个项目同事使用了FragmentTabhost来作为软件的底部的选择类似actionbar的功能,点击不同的按钮加载不同的fragment,但是老板希望能够让他能够滑动起来,原本想的很简单,准备直接加个scrollview来实现,实际做起来发现,scrollview 的Touchevent被拦截了无法获取,查了下资料顺便回顾了一下android的拦截机制,故决定从高层的分发入手自己实现一个类似scrollview的功能。
说一下思路吧,实现滚动的方式有很多,我选择了自己感觉比较简单的scrollBy来实现,同时移动的是在父容器中的位置,所以现在布局文件中在bottom位置留了个Linearlayout作为滑动的区域,由于需要重写高层容器的onInterceptTouchEvent方法,用来作为scrollview的linearlayout需要自己实例化,这时再重写onInterceptTouchEvent方法,在MotionEvent.ACTION_DOWN:中获得按下时的坐标,在获得move后的坐标得到offset量这样就能狗实现滑动的效果(注意在move最后要将startX和startY重新进行赋值),这时滑动便能够实现了。
但是,这时出现了一个问题,就是在滑动后,还是有点击按钮的事件触发,我们在滑动时并不需要将up分发下级view因此我们在得到offset大于3时判定此时在进行滑动,不将up分发出去。此时便已经能够实现滑动时不触发按钮的点击事件。
但是此时仍然觉得不是很完美,那就是view可以一直滑动到边界,最后甚至不能够在拉出来,于是便写定一个最多允许滑动的值,当滑动值超过allowOffsetlength时,只允许往左滑动,小于-allowOffsetlength时只允许往右滑动,其他时候,左右都可以滑动。
直接上代码:
LinearLayout container = (LinearLayout) view.findViewById(R.id.container);
LinearLayout mContainer = new LinearLayout(this) {
int startX = 0;
int offsetX = 0;
boolean isMove = false;
int totalOffsetWidth = 0;//已滑动距离
int allowOffsetlength ;//允许滑动的距离
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = (int) ev.getRawX();
isMove = false;
allowOffsetlength=getWidth() / 2;
case MotionEvent.ACTION_MOVE:
offsetX = (int) ev.getX() - startX;
if(totalOffsetWidth>=allowOffsetlength){
direction=LEFT;
}else if(totalOffsetWidth<=-allowOffsetlength){
direction=RIGHT;
}else{
direction= <span style="font-family: Arial, Helvetica, sans-serif;">ALL</span><span style="font-family: Arial, Helvetica, sans-serif;">;</span><span style="font-family: Arial, Helvetica, sans-serif;">;</span><span style="font-family: Arial, Helvetica, sans-serif;">
</span> }
switch(direction){
case ALL:
totalOffsetWidth += offsetX;
scrollBy(-offsetX, 0);
break;
case LEFT:
if(offsetX<0){
totalOffsetWidth += offsetX;
scrollBy(-offsetX, 0);
}
break;
case RIGHT:
if(offsetX>0){
totalOffsetWidth += offsetX;
scrollBy(-offsetX, 0);
}
break;
}
startX = (int) ev.getX();
if (Math.abs(offsetX) > 3) {
isMove = true;
}
break;
case MotionEvent.ACTION_UP:
if (isMove) {
return true;
}
}
return super.onInterceptTouchEvent(ev);
}
};
mContainer.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mTabHost = new FragmentTabHost(this);
mTabHost.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
mTabHost.offsetLeftAndRight(200);
//得到fragment的个数
int count = fragmentArray.length;
for (int i = 0; i < count; i++) {
//为每一个Tab按钮设置图标、文字和内容
TabSpec tabSpec = mTabHost.newTabSpec(mTextviewArray[i]).setIndicator(getTabItemView(i));
//将Tab按钮添加进Tab选项卡中
mTabHost.addTab(tabSpec, fragmentArray[i], null);
//设置Tab按钮的背景
//mTabHost.getTabWidget().getChildAt(i).setBackgroundResource(R.drawable.selector_tab_background);
}
container.addView(mContainer);
mContainer.addView(mTabHost);