@wangwangheng
2015-06-17T12:51:45.000000Z
字数 4042
阅读 2248
不可发布
- 实现这个功能需要理解Android中对触摸事件的分发
- 关于事件分发,我自己花了一张图,可以参考下Android View之间的触摸事件传递图
整体思路 在页面加载完成之后,把ViewPager的高度设置为ScrollView的高度减去Tab的高度,然后在ScrollView、ListView的触摸时间分发上想办法完成想要的功能;
在HomeFragment中,调用时机是页面刷新完成之后:
mScrollView.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if(!resized && getActivity() != null){
LayoutParams params = mViewPager.getLayoutParams();
// 只能通过屏幕高度设置,当有虚拟键盘的时候有问题
// 为什么要加上底部的虚拟按钮条的高度?因为手机有虚拟按钮
// 有的手机没有;而且,具有虚拟按钮的手机的具体表现还不一样;
int virtualBackBarHeight = CuliuUtils.getScreenHeight()
- getActivity().getWindow().getDecorView().getHeight();
// top bar和bottom bar的高度
int topbarHeight = getResources()
.getDimensionPixelSize(R.dimen.topbar_height);
int bottomBarHeight = getResources()
.getDimensionPixelSize(R.dimen.bottom_bar_height);
int topAndBottomBarHeight = topbarHeight + bottomBarHeight;
LinearLayout.LayoutParams p = (android.widget.LinearLayout.LayoutParams)
mTabs.getLayoutParams();
int margin = p.topMargin + p.bottomMargin
+ mTabsBottomDividerView.getHeight();
params.height = CuliuUtils.getScreenHeight() - statusBarHeight -
mTabs.getHeight() - topAndBottomBarHeight
- virtualBackBarHeight - margin;
mViewPager.setLayoutParams(params);
mScrollView.setInterceptParams(mViewPager);
resized = true;
}
}
});
特别注意的是,ViewPager 的高度只要设置一次就行了,所以要有排斥机制,并且在内存被回收之后,要重新设置高度(使用保存了的ViewPager的高度)
主要思路: 在自定义的ScrollView的onInterceptTouchEvent()
方法中(MyScrollView),判断手指在屏幕X轴上和Y轴上移动的距离的大小,如果在X轴移动的距离大于在Y轴上移动的距离,则把事件分发到子View上(返回false);否则直接自己处理(返回true)
case MotionEvent.ACTION_DOWN:
xDistance = yDistance = 0f;
lastX = ev.getX();
lastY = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
final float curX = ev.getX();
final float curY = ev.getY();
xDistance += Math.abs(curX - lastX);
yDistance += Math.abs(curY - lastY);
lastX = curX;
lastY = curY;
if(xDistance > yDistance){
return false;
}
break;
因为
MyScrollView extends ScrollView
, 所以,如果在X轴移动的距离不大于在Y轴移动的距离,会调用ScrollView
的onInterceptTouchEvent()
,在ACTION_MOVE
的时候,如果在Y轴的手指滑动距离大于ViewConfiguration所以定义的最小滑动距离(touchSlop,从这个方法ViewConfiguration.get(context).getScaledTouchSlop()
得到)的话,则返回true这一块内容,可以继续做优化:可以在X轴移动距离大于Y轴距离的时候,添加上X轴移动距离和TouchSlop的比较逻辑
主要思路: 需要处理MyScrollView的onInterceptTouchEvent()以及HomeListView的onTouchEvent以及onScroll方法
通过VelocityTracker得到当前Y轴的移动速度,如果>0说明手指正在往下滑动,如果<0,则说明正在往上滑动;关于VelocityTracker可以参考网上的文章,如Android VelocityTracker简介
得到View的显示区域的方法:
Rect global = new Rect();
mNoInterceptView.getGlobalVisibleRect(global);
主界面底部Tabbar和Fragment是一一关联的关系,逻辑比较简单,但是有一点需要注意的就是,当内存被干掉之后(onSaveInstanceState()方法),Android其实是会保存Fragment的状态的,所以要在状态恢复(onRestoreInstanceState()或者onCreate()方法)的时候,恢复这些Fragment;否则会导致页面混乱
每次进入应用请求Settings,会返回列表界面和微店的备用ip列表信息,程序中也固定一个列表界面和微店的ip;
如果请求Settings失败,则使用列表界面的备用ip重新请求,如果请求成功则切换列表的请求ip为列表备用ip列表中的一个;
如果列表界面请求失败,用户下次请求的的时候把列表界面的请求ip切换为settings请求下来的ip列表中的任意一个;如果settings中的ip列表为空,则使用备用列表;并设置host为api.chuchujie.com
如果微店请求失败,用户下次请求微店的时候把地址切换为Settings中请求的下来的微店ip列表中的任意一个,如果Settings中没有微店ip列表,则使用微店的备用Ip;并设置host为wxapi.chuchujie.com
具体的逻辑,可以参考
SwitchHostManager
类
订单评论页中的店铺评价(EditText中的内容),是在失去焦点的时候设置到保存评价信息的对象中去的,这一点要注意一下
新分类主要使用大荣写的一个通用的列表界面框架,这个可以和大荣沟通
目前主界面中使用的Banner都是BannerFragment来实现的,自动跳转下一个Banner的逻辑都在BannerViewPager类中;
实现无限循环滚动的逻辑可以看一下ViewPager无限循环,并做了优化————到最后一个和第0个切换的时候的逻辑从onPageSelected()方法移动到了onPageScrolled()方法。