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

Android 滑动侧边栏(Sliding Menu)第一种实现 - 1 手动滚动+自动滚动

2013-03-10 22:31 465 查看
    之前的分析与一种解决方案,当前例子未充分考虑处理Touch事件,之后会接着完善例子。

《Android 滑动侧边栏(Sliding Menu)实现分析》

《Android 滑动侧边栏(Sliding Menu)第一种实现 - 1 手动滚动+自动滚动》 (本篇文章)

《Android 滑动侧边栏(Sliding Menu)第一种实现 - 2 手动滚动+自动滚动 + 事件处理》

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


一、 先来看看效果图



二、实现展示

方案具体使用可参考之前Demo
布局ViewGroup(左测绿色视图和右侧蓝色视图分别是其子View)《自定义ViewGrup》
手动滚动ViewGroup.layout(left, top, right, bottom); 《layout方法官方文档》
自动滚动 Scroller 和 ViewGroup.layout();《Scroller Demo》 
三、伪代码

1. 布局上面的Demo中可以找到相关Demo

2  手动滚动和自动滚动都是在onTouchEvent中进行控制,先看下源码,不喜欢贴大段的完整代码,最后会提供完整代码下载

public class SlidingMenus extends ViewGroup {

private View mRightView;
private View mLeftView;

// 记录一次移动位置,用于计算移动偏移量
private int mLastX;

// 按下时记录,用于判断当前滚动时向左还是向右
private int mMotionX;

......

@Override
public boolean onTouchEvent(MotionEvent event) {

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

switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastX = x;
mMotionX = x;

boolean inRegion = canSliding(event);

return inRegion;

case MotionEvent.ACTION_MOVE:

scrollIfNeed(x);
return true;

case MotionEvent.ACTION_UP:

autoScrollIfNeed(x);

break;
}

return true;
}

......

}


3. canSliding进行判断,仅右侧视图可以滚动,左侧视图不能滚动

/**
* 只有右侧视图可以移动
*
* @param event
* @return true 可以滚动
*/
private boolean canSliding(MotionEvent event) {
int[] location = new int[2];
// 获取右侧视图相对于屏幕坐标值
mRightView.getLocationOnScreen(location);
RectF region = new RectF();
region.set(location[0] , location[1] ,
location[0] + mRightView.getWidth(),
location[1] + mRightView.getHeight());

// 当前手指点击位置是否在右侧视图区域内
boolean inRegion = region.contains(event.getRawX(), event.getRawY());
return inRegion;
}


4. 右侧视图随手指移动,具体实现方法在scrollIfNeed

private void scrollIfNeed(final int x) {
// 计算与上次的偏移量
int deltaX = x - mLastX;

// 减少移动次数
if (x != mLastX) {
int l = mRightView.getLeft();
int t = mRightView.getTop();
int b = mRightView.getBottom();

// 右侧视图的滑动区域,只能在左侧视图范围内滑动
int rightViewLeft = Math.max(mLeftView.getLeft(), l + deltaX);
rightViewLeft = Math.min(mLeftView.getRight(), rightViewLeft);

// 控制随手指滑动
mRightView.layout(rightViewLeft, t, rightViewLeft + mRightView.getWidth(), b);
}

// 记录当前值供下次计算
mLastX = x;
}


5. 手指抬起后,视图随手指自动滚动具体实现在autoScrollIfNeed

private void autoScrollIfNeed(final int x) {
mScrollRunnable = new ScrollRunnable();

// 用于判断滑动方向
final int deltaX = x - mMotionX;
// x轴向右是依次递增与手指落下点差值,小于0说明是手指向左滑动
boolean moveLeft = deltaX <= 0;

// 滑动距离超过左侧视图一半,才会沿着手指方向滚动
final int distance = Math.abs(deltaX);
if (distance < mLeftView.getWidth() / 2) {
// 从哪来回哪去
moveLeft = !moveLeft;
}

// 启动自动滚动
mScrollRunnable.startScroll(moveLeft);
}

private class ScrollRunnable implements Runnable {
// 滚动辅助类,提供起始位置,移动偏移,移动总时间,可以获取每次滚动距离
private Scroller mScroller = new Scroller(getContext());

@Override
public void run() {
final Scroller scroller = mScroller;
// 计算滚动偏移,返回是否可以接着滚动
boolean more = scroller.computeScrollOffset();
// 计算后获取需要滚动到的位置
final int x = scroller.getCurrX();

if (more) {
// 与手动滚动调用的方法相同
scrollIfNeed(x);
// 当前子线程已经执行完,但是需要接着滚动
// 所以把当前Runnable再次添加到消息队列中
post(this);
} else {
// 不需要滚动
endScroll();
}

}

private void startScroll(boolean moveLeft) {
// 滚动前设置初始值
mLastX = mRightView.getLeft();

int dx = 0;

// 计算移动总距离
if (moveLeft) {
// 当前到左视图左侧边界距离
dx = mLeftView.getLeft() - mRightView.getLeft();
} else {
// 到右侧边界
dx = mLeftView.getRight() - mRightView.getLeft();
}

// 开始滚动
mScroller.startScroll(mRightView.getLeft(), 0, dx, 0, 300);
// 把当前Runnable添加到消息队列中
post(this);
}

private void endScroll() {
// 从消息队列中把当前Runnable删除,即停止滚动
removeCallbacks(this);
}

}


四、完整源码下载

源码下载连接

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