关于Scroller的理解

/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]

* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};

*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
*  再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*  
*  当偏移的位置超出View的边界大小时,动画结束后会弹回边界处

*/


package com.example.View;


import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.Scroller;

public class myViewPager extends ViewGroup {

Context context;
private GestureDetector mDetector;
private Scroller mScroller;

int startX, startY, endX, offX;

public myViewPager(Context context, AttributeSet attrs, int defStyleAttr,int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
this.context = context;
initView();
}

public myViewPager(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
initView();
}


public myViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
initView();
}


public myViewPager(Context context) {
super(context);
this.context = context;
initView();
}


public void initView() {
// 定义手势识别器
mDetector = new GestureDetector(context,new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY) {// 参1:起点动作, 参2:终点动作;参3:x方向滑动距离;参4:y方向滑动距离
scrollBy((int) distanceX, 0);// 页面滑动一定距离;x:水平方向的滑动偏移量;y:竖直方向滑动的偏移量;(相对偏移)
// scrollTo(x, y);//绝对位移;和当前位置无关,以当前左上角坐标为原点滑动到确定好的位置上
return super.onScroll(e1, e2, distanceX, distanceY);
}
});
// 定义滚动器
mScroller = new Scroller(context);
}


// 测量子控件长宽,不然有些子控件不能展示出来
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec); // 不能删,测量viewpager本身的宽高
// 遍历,测量子控件长宽
for (int i = 0; i < getChildCount(); i++) {
getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
}
// MeasureSpec.AT_MOST;//相当于wrap
// MeasureSpec.EXACTLY;//相当于match
MeasureSpec.getMode(widthMeasureSpec);// 获取宽高模式
MeasureSpec.getSize(heightMeasureSpec);// 获得具体宽度
}


// 设置子控件位置
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
for (int i = 0; i < getChildCount(); i++) {
getChildAt(i).layout(getWidth() * i, 0, getWidth() * (i + 1),getHeight());// 设置为一字排开
}
}


// 触摸监听
@Override
public boolean onTouchEvent(MotionEvent event) {
mDetector.onTouchEvent(event);// 委托手势识别器来处理
// 手指起来后子控件画面完整展示
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
int pos,offset,nowX;
nowX = getScrollX();// 返回已经滑动的离左边的距离
pos = nowX / getWidth();// 当前展示的前一副View
offset = nowX - pos * getWidth();

if (offset > getWidth() / 2) {
if (nowX > (getChildCount() - 1) * getWidth()) {// 在最右边
pos = getChildCount() - 1;
setCurrItem(pos);
} else
setCurrItem(pos + 1);
} else {
if (nowX > (getChildCount() - 1) * getWidth()) {// 在最右边
pos = getChildCount() - 1;
setCurrItem(pos);
} else
setCurrItem(pos);
}
invalidate();
break;


default:
break;
}
return true;// 消耗掉
}

// 中断触摸事件监听处理,决定是否下传事件处理给子控件
// ,即该myViewpager类决定是否下传事件处理给他的Child控件
// return true;中断
// return false;不中断
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// 在这里判断,如果左右滑动大于上下滑动的距离,则不中断,交给子控件处理
// 否则,则有Viewpager处理
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = (int) ev.getX();
startY = (int) ev.getY();

// 该事件被子控件先执行,在下面虽然返回true,但收拾识别器已丢失Action.Dowm的监听
// 所以,在这里强行调用手势识别器,获得事件监听
mDetector.onTouchEvent(ev);
break;

case MotionEvent.ACTION_MOVE:
int onEndX = (int) ev.getX();
int onEndY = (int) ev.getY();
int offX = onEndX - startX;
int offY = onEndY - startY;
if (Math.abs(offX) > Math.abs(offY)) {
return true;
}
break;

case MotionEvent.ACTION_UP:
break;
}
return false;
}


//事件分发机制
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
return super.dispatchTouchEvent(ev);
}

public void setCurrItem(int pos) {
// scrollTo(getWidth() * pos, 0);// 滑动到绝对位置,立刻滑动到位置
int posNext = pos * getWidth();// 需要回复到整个图片需要的宽度,目标位置
int distance = posNext - getScrollX();// 移动距离 = 目标位置- 当前位置

// 距离越长,时间越久,可以让时间=距离
// 此处并不会立即启动滑动动画,而是不断回调computeScroll这个方法
mScroller.startScroll(getScrollX(), 0, distance, 0, Math.abs(distance));
// 参1:起始x位置;参2:起始y位置;参3:x方向移动距离;参4:y方向移动距离;参5:移动时间
invalidate();// 刷新界面,不然mScroller.startScroll();不会成功执行
}

// 处理mScroller.startScroll();其中startScroll只是为需要的位移分段,computeScroll则执行处理
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {// 判断滑动是否已经结束,没有结束才处理以下逻辑
int TonextX = mScroller.getCurrX();// 获得下一个需要去到的X坐标
scrollTo(TonextX, 0);
invalidate();
}
}
}

/**
 * 事件处理机制:
 * 
 * 首先是最外层控件先获得事件监听
 * 
 * 监听: 由上到下,父到子
 * 
 * 处理: (如果子控件不处理)由下到上,子到父,如果消耗掉,就没了
 * 
 * 事件处理流程:
 * dispatchTouchEvent->onInterceptTouchEvent->onTouchEvent
 * 分发 ->中断->处理
 * 
 */

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本火锅店点餐系统采用Java语言和Vue技术,框架采用SSM,搭配Mysql数据库,运行在Idea里,采用小程序模式。本火锅店点餐系统提供管理员、用户两种角色的服务。总的功能包括菜品的查询、菜品的购买、餐桌预定和订单管理。本系统可以帮助管理员更新菜品信息和管理订单信息,帮助用户实现在线的点餐方式,并可以实现餐桌预定。本系统采用成熟技术开发可以完成点餐管理的相关工作。 本系统的功能围绕用户、管理员两种权限设计。根据不同权限的不同需求设计出更符合用户要求的功能。本系统中管理员主要负责审核管理用户,发布分享新的菜品,审核用户的订餐信息和餐桌预定信息等,用户可以对需要的菜品进行购买、预定餐桌等。用户可以管理个人资料、查询菜品、在线点餐和预定餐桌、管理订单等,用户的个人资料是由管理员添加用户资料时产生,用户的订单内容由用户在购买菜品时产生,用户预定信息由用户在预定餐桌操作时产生。 本系统的功能设计为管理员、用户两部分。管理员为菜品管理、菜品分类管理、用户管理、订单管理等,用户的功能为查询菜品,在线点餐、预定餐桌、管理个人信息等。 管理员负责用户信息的删除和管理,用户的姓名和手机号都可以由管理员在此功能里看到。管理员可以对菜品的信息进行管理、审核。本功能可以实现菜品的定时更新和审核管理。本功能包括查询餐桌,也可以发布新的餐桌信息。管理员可以查询已预定的餐桌,并进行审核。管理员可以管理公告和系统的轮播图,可以安排活动。管理员可以对个人的资料进行修改和管理,管理员还可以在本功能里修改密码。管理员可以查询用户的订单,并完成菜品的安排。 当用户登录进系统后可以修改自己的资料,可以使自己信息的保持正确性。还可以修改密码。用户可以浏览所有的菜品,可以查看详细的菜品内容,也可以进行菜品的点餐。在本功能里用户可以进行点餐。用户可以浏览没有预定出去的餐桌,选择合适的餐桌可以进行预定。用户可以管理购物车里的菜品。用户可以管理自己的订单,在订单管理界面里也可以进行查询操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值