android下拉菜单滚动,Android Scroll实现弹性滑动_列表下拉弹性滑动的示例代码

Android Scroll实现弹性滑动_列表下拉弹性滑动的示例代码

发布时间:2020-09-05 12:09:10

来源:脚本之家

阅读:113

作者:键盘舞者113

我这一次讲使用scroll实现弹性滑动,我不会只有一个例子就说完,因为写文章的时候我也在学习,我分几次讲完吧。

首先上一段代码,

private void smoothScrollByScroller(int dy){

mScroller.startScroll(0,dy,0,dy*-1,1000);

invalidate();

}

@Override

public void computeScroll() {

if (mScroller.computeScrollOffset()) {

scrollTo(mScroller.getCurrX(), mScroller.getCurrY());

postInvalidate();

}

}

这段代码是实现弹性滑动的核心,第一个函数指的是缓慢滑动的意思,但是却没有这个滑动的实际功能。

startScroll这函数的五个参数指的是起点x坐标,起点y坐标,x位移量,y位移量,这段滑动的时间。这个函数的内部是不断计算在滑动时间里x和y坐标应该是什么值,然后因为invalidate会调用computeScroll,这个computeScrollOffset函数是判断当前滑动是否结束,如果没有结束通过getCurrX和getCurry获得startScroll函数计算的值,在使用scrollTo滑动相应的位置,因为startScroll会运算很多次,也就是将滑动时间分成很多段,相应的坐标也都算出来,跟着给scrollTo去实现滑动。

这很像是ValueAmition,将时间分成很多段,然后计算相应的值,同时分很多次去实现。

我贴一个类似QQ消息列表的常见的弹性滑动,这里下拉是没有刷新的,

public class MainActivity extends AppCompatActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

}

}

public final class PullView extends ViewGroup {

private int mLastY;

private Context mContext;

private Scroller mScroller;

//子View的个数

private int mChildCount;

public PullView(Context context){

this(context,null);

}

public PullView(Context context, AttributeSet attributeSet){

super(context,attributeSet);

mContext=context;

initView();

}

private void initView(){

mScroller=new Scroller(mContext);

}

@Override

public boolean onTouchEvent(MotionEvent event) {

int y=(int)event.getY();

switch (event.getAction()){

//手指按下时,初始化按下位置的X,Y位置值

case MotionEvent.ACTION_DOWN:

mLastY=y;

break;

//计算滑动的偏移量,产生滑动效果

case MotionEvent.ACTION_MOVE:

//手指向下滑动delayY>0,向上滑动delayY<0

int delayY=y-mLastY;

delayY=delayY*-1;

scrollBy(0,delayY);

break;

case MotionEvent.ACTION_UP:

/**

* scrollY是指:View的上边缘和View内容的上边缘(其实就是第一个ChildView的上边缘)的距离

* scrollY=上边缘-View内容上边缘,scrollTo/By方法滑动的知识View的内容

* 往下滑动scrollY是负值

*/

int scrollY=getScrollY();

smoothScrollByScroller(scrollY);

break;

}

mLastY=y;

return true;

}

/**

* 执行滑动效果

* 使用scroller实现

* @param dy

*/

private void smoothScrollByScroller(int dy){

mScroller.startScroll(0,dy,0,dy*-1,1000);

invalidate();

}

@Override

public void computeScroll() {

if (mScroller.computeScrollOffset()) {

scrollTo(mScroller.getCurrX(), mScroller.getCurrY());

postInvalidate();

}

}

/**

* 重新计算子View的高度和宽度

* @param widthMeasureSpec

* @param heightMeasureSpec

*/

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

int measuredWidth;

int measureHeight;

mChildCount = getChildCount();

//测量子View

measureChildren(widthMeasureSpec, heightMeasureSpec);

int widthSpaceSize = MeasureSpec.getSize(widthMeasureSpec);

int widthSpaceMode = MeasureSpec.getMode(widthMeasureSpec);

int heightSpaceSize = MeasureSpec.getSize(heightMeasureSpec);

int heightSpaceMode = MeasureSpec.getMode(heightMeasureSpec);

//获取横向的padding值

int paddingLeft=getPaddingLeft();

int paddingRight=getPaddingRight();

final View childView = getChildAt(0);

/**

* 如果子View的数量是0,就读取LayoutParams中数据

* 否则就对子View进行测量

* 此处主要是针对wrap_content这种模式进行处理,因为默认情况下

* wrap_content等于match_parent

*/

if (mChildCount == 0) {

ViewGroup.LayoutParams layoutParams=getLayoutParams();

if(layoutParams!=null){

setMeasuredDimension(layoutParams.width,layoutParams.height);

}else {

setMeasuredDimension(0, 0);

}

} else if (heightSpaceMode == MeasureSpec.AT_MOST && widthSpaceMode == MeasureSpec.AT_MOST) {

measuredWidth = childView.getMeasuredWidth() * mChildCount;

measureHeight = getChildMaxHeight();

//将两侧的padding值加上去

measuredWidth=paddingLeft+measuredWidth+paddingRight;

setMeasuredDimension(measuredWidth, measureHeight);

} else if (heightSpaceMode == MeasureSpec.AT_MOST) {

measureHeight = getChildMaxHeight();

setMeasuredDimension(widthSpaceSize, measureHeight);

} else if (widthSpaceMode == MeasureSpec.AT_MOST) {

measuredWidth = childView.getMeasuredWidth() * mChildCount;

measuredWidth=paddingLeft+measuredWidth+paddingRight;

setMeasuredDimension(measuredWidth, heightSpaceSize);

}

}

/**

* 获取子View中最大高度

* @return

*/

private int getChildMaxHeight(){

int maxHeight=0;

for (int i = 0; i < mChildCount; i++) {

View childView = getChildAt(i);

if (childView.getVisibility() != View.GONE) {

int height = childView.getMeasuredHeight();

if(height>maxHeight){

maxHeight=height;

}

}

}

return maxHeight;

}

/**

* 设置子View的布局

* @param changed

* @param l

* @param t

* @param r

* @param b

*/

@Override

protected void onLayout(boolean changed, int l, int t, int r, int b) {

int childLeft = 0;

for (int i = 0; i < mChildCount; i++) {

View childView = getChildAt(i);

if (childView.getVisibility() != View.GONE) {

int childWidth = childView.getMeasuredWidth();

childView.layout(childLeft, 0, childLeft + childWidth, childView.getMeasuredHeight());

childLeft += childWidth;

}

}

}

}

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="horizontal" >

android:layout_width="match_parent"

android:layout_height="1500dp"

android:background="#806363">

这里的ViewGroup的绘画和测量我就不多说,我就说一下它获取函数,计算坐标的一些事。

它在手指按下时记录y坐标,在手指移动时,跟着移动子View,在手指抬起时,使用弹性滑动的函数smoothScrollByScroller。

大家会发现为什么一些计算出的坐标要加负号,因为在我们人眼里,我们下拉y坐标的位移量是正的,但是在系统认为这个值是负的,原因我太菜不知道,知道的求大神评论留言告诉。

下一次写一个随手指弹性滑动的例子。

以上这篇Android Scroll实现弹性滑动_列表下拉弹性滑动的示例代码就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持亿速云。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值