ScrollLayout 的使用
来源:互联网 发布:java输入输出学生成绩 编辑:程序博客网 时间:2024/06/05 01:03
package com.Scroll;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller;
public class ScrollLayout extends ViewGroup
{
private static final String TAG = "ScrollLayout";
private Scroller mScroller; //生成滑动条对象
private VelocityTracker mVelocityTracker;
private int mCurScreen;
private int mDefaultScreen = 1;
private static final int TOUCH_STATE_REST = 0;
private static final int TOUCH_STATE_SCROLLING = 1;
private static final int SNAP_VELOCITY = 600;
private int mTouchState = TOUCH_STATE_REST;
private int mTouchSlop;
private float mLastMotionX;
//构造函数
public ScrollLayout(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
// TODO Auto-generated constructor stub
}
//构造函数
public ScrollLayout(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
mScroller = new Scroller(context);
mCurScreen = mDefaultScreen;
mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); //计算子视图能滑动的距离
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
{
// TODO Auto-generated method stub
if (changed)
{
int childLeft = 0;
final int childCount = getChildCount();//记录滚动视图组有多少个子视图
for (int i=0; i<childCount; i++)
{
final View childView = getChildAt(i);//获取子视图
if (childView.getVisibility() != View.GONE)//判断当前子视图是否可视
{
final int childWidth = childView.getMeasuredWidth(); //获取母体宽度
childView.layout(childLeft, 0,
childLeft+childWidth, childView.getMeasuredHeight()); //设置子体位置
childLeft += childWidth;//记录字体左边边界位置
}
}
}
}
//view.View的子函数,需要重写
//执行初始的判断测量,滑到初始位置,其他时候不产生作用
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final int width = MeasureSpec.getSize(widthMeasureSpec);//MeasureSpec是全局静态变量View的成员变量,封装传递从父到子的布局要求。
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (widthMode != MeasureSpec.EXACTLY) //如果父母没有为子窗体提供合适的宽度,则抛出异常
{
throw new IllegalStateException("ScrollLayout only canmCurScreen run at EXACTLY mode!");
}
if (heightMode != MeasureSpec.EXACTLY) //如果父母没有为子窗体提供合适的高度,则抛出异常
{
throw new IllegalStateException("ScrollLayout only can run at EXACTLY mode!");
}
// The children are given the same width and height as the scrollLayout
final int count = getChildCount();//记录子视图个数
for (int i = 0; i < count; i++)
{
getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
}
scrollTo(mCurScreen * width, 0);
}
/**
* According to the position of current layout
* scroll to the destination page.
*/
//判断当前滚动坐标是否超过屏幕一半
public void snapToDestination()
{
final int screenWidth = getWidth();
final int destScreen = (getScrollX()+ screenWidth/2)/screenWidth;
snapToScreen(destScreen);
}
public void snapToScreen(int whichScreen)
{
// get the valid layout page
whichScreen = Math.max(0, Math.min(whichScreen, getChildCount()-1)); //计算当前应该显示的是第几个子窗体(0、1、2……)
if (getScrollX() != (whichScreen*getWidth()))//判断当前子窗体是否停在准确位置,不准确则运行
{
int X=320;
if(whichScreen==2)X=getScrollX()-320;
if(whichScreen==0)X=getScrollX()+320;
final int delta = getWidth()-X;//记录当前距离标准位置坐标的距离
mScroller.startScroll(X, 0,
delta, 0, Math.abs(delta)*2); //设置子窗体滑动的横向起点、纵向起点、横向位移、纵向位移、移动时间(微秒)
mCurScreen = 1;
Log.e(TAG, "moving to screen "+mCurScreen);
invalidate(); // Redraw the layout
System.out.println("重画结束");
}
}
//没搞懂这段代码是干嘛用的,注释运行之后发现没有异样。
public void setToScreen(int whichScreen)
{
whichScreen = Math.max(0, Math.min(whichScreen, getChildCount()-1));
mCurScreen = whichScreen;
scrollTo(whichScreen*getWidth(), 0);
}
public int getCurScreen()
{
return mCurScreen;
}
@Override
public void computeScroll()
{
// TODO Auto-generated method stub
if (mScroller.computeScrollOffset())
{
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
// TODO Auto-generated method stub
if (mVelocityTracker == null) //如果获取触屏没有移动,则重新获取
{
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
final int action = event.getAction();
final float x = event.getX();
switch (action)
{
case MotionEvent.ACTION_DOWN:
if (!mScroller.isFinished())//如果中途结束了进程。则中断动作
{
mScroller.abortAnimation();
}
mLastMotionX = x; //获取第当前横坐标
break;
case MotionEvent.ACTION_MOVE:
int deltaX = (int)(mLastMotionX - x);//记录移动的距离
mLastMotionX = x; //获取当前横坐标
scrollBy(deltaX, 0); //滑动当前子视图
break;
case MotionEvent.ACTION_UP:
//下面这个语句如果不注释的话,滚动视图会停留在各种位置,而不是和屏幕边界对齐
// if (mTouchState == TOUCH_STATE_SCROLLING) {
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000); //设置当前滚动条的滚动速度
int velocityX = (int) velocityTracker.getXVelocity(); //获得当前横坐标滚动素速度
//如果滚动速度大于600像素/秒,而且当前子视图不是最左端视图,则向左偏移
if (velocityX > SNAP_VELOCITY && mCurScreen > 0)
{
// Fling enough to move left
snapToScreen(mCurScreen - 1);
}
else
//如果滚动速度大于600像素/秒,而且当前子视图不是最右端视图,则向右偏移
if (velocityX < -SNAP_VELOCITY
&& mCurScreen < getChildCount() - 1)
{
// Fling enough to move right
snapToScreen(mCurScreen + 1);
}
//其他的则,按照移动坐标位置移动子视图
else
{
snapToDestination();
}
//设置完子视图的滑动之后,应该释放掉mVelocityTracker对象
if (mVelocityTracker != null)
{
mVelocityTracker.recycle();
mVelocityTracker = null;
}
// }
mTouchState = TOUCH_STATE_REST;
break;
case MotionEvent.ACTION_CANCEL:
mTouchState = TOUCH_STATE_REST;
break;
}
return true;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
final int action = ev.getAction();
//如果当前动作是在移动且触屏状态显示不是初始值则返回true结束该函数
if ((action == MotionEvent.ACTION_MOVE) &&
(mTouchState != TOUCH_STATE_REST))
{
return true;
}
final float x = ev.getX();
switch (action)
{
case MotionEvent.ACTION_MOVE:
final int xDiff = (int)Math.abs(mLastMotionX-x);
//如果按下时的坐标和当前移动到的位置的坐标差的绝对值大于子视图可移动的距离则修改为正在滑动
if (xDiff>mTouchSlop)
{
mTouchState = TOUCH_STATE_SCROLLING;
}
break;
case MotionEvent.ACTION_DOWN:
mLastMotionX = x;
//如果滚动完成,则返回初始值,否则返回滚动中的状态
mTouchState = mScroller.isFinished()? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING;
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
mTouchState = TOUCH_STATE_REST;
break;
}
return mTouchState != TOUCH_STATE_REST;
}
}
- ScrollLayout 的使用
- ScrollLayout
- ScrollLayout的学习【仿launcher滑动】
- ScrollLayout的学习【仿launcher滑动】
- 真正解决ScrollLayout与Gallery等组件的滑动冲突
- 真正解决ScrollLayout与Gallery等组件的滑动冲突
- 实现手指滑动切换视图的自定义布局类ScrollLayout
- 关于 ScrollLayout加载时总是显示在中间的视图解决方法
- android ScrollLayout VelocityTracker
- 自定义布局-ScrollLayout
- 自定义布局-ScrollLayout
- Android ScrollLayout 下拉回弹
- 自定义组件:ScrollLayout
- 简单实现ScrollLayout
- Android ScrollLayout判断滑动完毕。
- 自定义布局-ScrollLayout,左右滑动切换
- 开源中国控件ScrollLayout分析
- android自定义布局-ScrollLayout 实现左右滑动
- poj 1654 这题我想多了
- 学hibernate的地方
- BloomFilter简易实现
- 在S3C2440上配置UART
- 想做硬件开发的人员必看
- ScrollLayout 的使用
- 在PropertyGrid使用JsonStore
- 锂电池充电的原理
- XEN的命令集
- php 解决can not modify header infomation的方法
- Xen的源码包编译安装
- ExtJS4学习笔记十--Grid使用
- java的引用传递
- android全屏显示