您的位置:首页 > 移动开发 > Android开发

Android 滑动侧边栏(Sliding Menu)第二种实现方式 1

2013-03-09 23:27 519 查看
     之前做过《Android 滑动侧边栏(Sliding Menu)实现分析》,今天尝试选择一种解决方案来实现效果。

     这一周工作都比较忙,今天先实现了布局+随手指移动,但是发现选择的方案有问题,先来看个效果图后面再介绍解决方案和不足之处。

    

一、效果图



二、选择的解决方案

方案具体使用可参考之前Demo
布局ViewGroup(左测绿色视图和右侧蓝色视图分别是其子View)《自定义ViewGrup》
随手指移动View.mScrollX,scrollTo() ,scrollBy()《scrollBy使用》
1. 布局使用ViewGroup没有问题,从上图中就可以看到绿和蓝两个视图可以叠加在一起,也可以错开。

2. 但是使用mScrollX不行,虽然上图中看到了达到滚动的效果,但是效果实现其实很雷人,并不符合Android框架的设计。

    选择使用mScrollX的目的是因为可以提高效率,因为其仅重新调用onDraw不会调用onMeasure,onLayout方法。《具体分析

    既然有些限制,不用着急换其他解决方案,毕竟写这些效果也是学习的目的,多尝试下总没有坏处,基于这种目的之后来看看如何绕过这个问题达到想要的滚动效果。   

三、为什么Sliding Menu不能使用mScrollX来处理滚动?

1. mScrollX,mScrollY是用来控制父视图中的子视图滚动,这样随来也没什么问题啊?反正是控制滚动。但是这种滚动却不是想要的效果,如果想让视图滚动并需在其父视图调用scrollTo或scrollBy方法 ,但是这样会导致绿色子视图和蓝色子视图一起滚动。具体解释在《Android View.scrollTo,
View.scrollBy控制视图滚动原理》 

public SlidingMenu(Context context) {
super(context);

initSlidingMenu(context);
}

private void initSlidingMenu(Context context) {
// 为了使用mScrollX滚动,并且仅滚动右侧
// 只能把右侧视图单独放入一个独立的ViewGruop中
mRightViewGroup = new LinearLayout(context);
mRightViewGroup.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
addView(mRightViewGroup);
}

/**
* 提供右侧显示视图
*
* @param rightView
*/
public void addRightView(View rightView) {
// 此ViewGroup是包裹在右侧蓝色视图外的ViewGroup
mRightViewGroup.addView(rightView);

// 设置Touch事件
mRightView.setOnTouchListener(new RightViewTouchEvent());
}

/**
*	右侧视图可以随手指移动
*/
private class RightViewTouchEvent implements OnTouchListener {

private int mMotionX;

@Override
public boolean onTouch(View view, MotionEvent event) {

final int x = (int) event.getX();
int deltaX;

switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mMotionX = x;
Log.e("Test", "ACTION_DOWN");
return true;

case MotionEvent.ACTION_MOVE:
deltaX = x - mMotionX;
mRightViewGroup.scrollBy(-deltaX, 0);

Log.e("Test", "ACTION_MOVE "
+ " , mMotionX = " + mMotionX
+ " , x = " + x
+ " , deltaX = " + deltaX
+ " , mX = " + mRightViewGroup.getScrollX());
return true;

case MotionEvent.ACTION_UP:
mMotionX = 0;
Log.e("Test", "ACTION_UP");
break;
}

return false;
}

}


    从上面的代码可以看出,既然scrollTo有上面提到的要求,但是可以通过把需要滚动的蓝色视图单独放入一个ViewGroup,这样可以使蓝色视图达到滚动效果。

    在上面的代码中可以看到onTouch事件中添加了LOG,也是通过LOG才发现一个问题。

四、touch事件问题

    这个问题也是由mScrollX引起的,因为解决上面三的问题,所以把蓝色视图放入一个独立的ViewgGroup,如果想让其滚动,需要滚动需要覆写此独立ViewGroup的onTouchEvent,这样做本身是符合逻辑的,但是从打印的LOG中发现出现问题。

ACTION_DOWN
ACTION_MOVE  , mMotionX = 66 , x = 66 , deltaX = 0 , mX = 1
ACTION_MOVE  , mMotionX = 66 , x = 66 , deltaX = 0 , mX = 1
ACTION_MOVE  , mMotionX = 66 , x = 73 , deltaX = 7 , mX = -6
ACTION_MOVE  , mMotionX = 66 , x = 69 , deltaX = 3 , mX = -9
ACTION_MOVE  , mMotionX = 66 , x = 68 , deltaX = 2 , mX = -11
ACTION_MOVE  , mMotionX = 66 , x = 70 , deltaX = 4 , mX = -15
ACTION_MOVE  , mMotionX = 66 , x = 69 , deltaX = 3 , mX = -18
ACTION_MOVE  , mMotionX = 66 , x = 68 , deltaX = 2 , mX = -20
ACTION_MOVE  , mMotionX = 66 , x = 69 , deltaX = 3 , mX = -23
ACTION_MOVE  , mMotionX = 66 , x = 68 , deltaX = 2 , mX = -25
ACTION_MOVE  , mMotionX = 66 , x = 67 , deltaX = 1 , mX = -26
ACTION_UP


    上面的LOG是在蓝色视图区域横向向右滑动,按照预期应该是x值从66逐渐递增,但是从上面LOG可以看出x值得变化规律是 66, 73,69,68 , 70 , 69。

    图上效果正常是因为错误的使用,计算的deltaY是当前点与Action_Down按下时点的差值,而scrollBy的参数是相对上次移动的值。

    为什么即使手指在蓝色区域内向右滑动,其获取的event.getX()的值还是基本没什么变化呢? 原因是点击在蓝色区域内,getX()获取的是当前手指与蓝色区域左侧的距离,因为蓝色区域所手指移动,所以获取到的值也没什么变化。《Android Touch事件rawX,rawY与x,y的区别》

    当然这个问题也可以通过获取getRawX来解决,但是感觉没必要再接着处理因使用mScrollX引出的问题,因为其在View当中已经说明,是针对父视图中内容滚动支持提供的参数。

五、源码

源码下载

   

    为什么这个解决方案不是想要的效果还要写出来,并且提供源码下载? 感觉这是一个尝试的过程,尝试有可能直接成功也可能失败,但是我也没感觉这是失败,毕竟是学习的从这个解决方案中加深了对mScrollX进行滚动的了解。

原文地址: http://blog.csdn.net/love_world_/article/details/8654885
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: