千家信息网

Android中如何通过自定义ViewGroup实现一个弹性滑动效果

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,本篇内容主要讲解"Android中如何通过自定义ViewGroup实现一个弹性滑动效果",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Android中如何通
千家信息网最后更新 2026年11月03日Android中如何通过自定义ViewGroup实现一个弹性滑动效果

本篇内容主要讲解"Android中如何通过自定义ViewGroup实现一个弹性滑动效果",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Android中如何通过自定义ViewGroup实现一个弹性滑动效果"吧!

实现原理

onMeasure()中测量所有子View

 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  // 测量所有子View  int count = getChildCount();  for (int i = 0; i < count; i++) {   View childView = getChildAt(i);   measureChild(childView, widthMeasureSpec, heightMeasureSpec);  }  setMeasuredDimension(widthMeasureSpec, heightMeasureSpec); }

onLayout()中,将所有的子View按照位置依次往下排列

@Override protected void onLayout(boolean changed, int l, int t, int r, int b) {  // 设置ViewGroup的高度,对所有子View进行排列  int childCount = getChildCount();  MarginLayoutParams params = (MarginLayoutParams) getLayoutParams();  params.height = mScreenHeight * childCount;  for (int i = 0; i < childCount; i++) {   View childView = getChildAt(i);   if (childView.getVisibility() != View.GONE) {    // 给每个ChildView放置在指定位置    childView.layout(l, i * mScreenHeight, r, (i + 1) * mScreenHeight);   }  } }

onTouchEvent()中处理滑动

 @Override public boolean onTouchEvent(MotionEvent event) {  switch (event.getAction()) {   case MotionEvent.ACTION_DOWN:    mLastY = (int) event.getY();    mStart = getScrollY();    return true;   case MotionEvent.ACTION_MOVE:    if (!mScroller.isFinished()) {     // 终止滑动     mScroller.abortAnimation();    }    int offsetY = (int) (mLastY - event.getY());    Log.d(TAG, "onTouchEvent: getScrollY: " + getScrollY());    Log.d(TAG, "onTouchEvent: offsetY " + offsetY);    // 到达顶部,使用offset判断方向    if (getScrollY() + offsetY < 0) { // 当前已经滑动的 Y 位置     offsetY = 0;    }    // 到达底部    if (getScrollY() > getHeight() - mScreenHeight && offsetY > 0) {     offsetY = 0;    }    scrollBy(0, offsetY);    // 滑动完成后,重新设置LastY位置    mLastY = (int) event.getY();    break;   case MotionEvent.ACTION_UP:    mEnd = getScrollY();    int distance = mEnd - mStart;    if (distance > 0) { // 向上滑动     if (distance < mScreenHeight / 3) {      Log.d(TAG, "onTouchEvent: distance < screen/3");      // 回到原来位置      mScroller.startScroll(0, getScrollY(), 0, -distance);     } else {      // 滚到屏幕的剩余位置      mScroller.startScroll(0, getScrollY(), 0, mScreenHeight - distance);     }    } else {    // 向下滑动     if (-distance < mScreenHeight / 3) {      mScroller.startScroll(0, getScrollY(), 0, -distance);     } else {      mScroller.startScroll(0, getScrollY(), 0, -mScreenHeight - distance);     }    }    postInvalidate();  }  return super.onTouchEvent(event); }

其中ACTION_UP这段代码是处理弹性滑动的

case MotionEvent.ACTION_UP:    mEnd = getScrollY();    int distance = mEnd - mStart;    if (distance > 0) { // 向上滑动     if (distance < mScreenHeight / 3) {      Log.d(TAG, "onTouchEvent: distance < screen/3");      // 回到原来位置      mScroller.startScroll(0, getScrollY(), 0, -distance);     } else {      // 滚到屏幕的剩余位置      mScroller.startScroll(0, getScrollY(), 0, mScreenHeight - distance);     }    } else {    // 向下滑动     if (-distance < mScreenHeight / 3) {      mScroller.startScroll(0, getScrollY(), 0, -distance);     } else {      mScroller.startScroll(0, getScrollY(), 0, -mScreenHeight - distance);     }    }    postInvalidate();

完整代码

public class ScrollViewGroup extends ViewGroup { private static final String TAG = "ScrollView"; private Scroller mScroller; private int mScreenHeight; // 窗口高度 private int mLastY; private int mStart; private int mEnd; public ScrollViewGroup(Context context) {  this(context, null); } public ScrollViewGroup(Context context, AttributeSet attrs) {  this(context, attrs, 0); } public ScrollViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {  super(context, attrs, defStyleAttr);  mScroller = new Scroller(context);  // 获取屏幕高度  WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);  DisplayMetrics metrics = new DisplayMetrics();  windowManager.getDefaultDisplay().getMetrics(metrics);  mScreenHeight = metrics.heightPixels;  Log.d(TAG, "ScrollViewGroup: ScreenHeight " + mScreenHeight); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  // 测量所有子View  int count = getChildCount();  for (int i = 0; i < count; i++) {   View childView = getChildAt(i);   measureChild(childView, widthMeasureSpec, heightMeasureSpec);  }  setMeasuredDimension(widthMeasureSpec, heightMeasureSpec); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) {  // 设置ViewGroup的高度,对所有子View进行排列  int childCount = getChildCount();  MarginLayoutParams params = (MarginLayoutParams) getLayoutParams();  params.height = mScreenHeight * childCount;  for (int i = 0; i < childCount; i++) {   View childView = getChildAt(i);   if (childView.getVisibility() != View.GONE) {    // 给每个ChildView放置在指定位置    childView.layout(l, i * mScreenHeight, r, (i + 1) * mScreenHeight);   }  } } @Override public boolean onTouchEvent(MotionEvent event) {  switch (event.getAction()) {   case MotionEvent.ACTION_DOWN:    mLastY = (int) event.getY();    mStart = getScrollY();    return true;   case MotionEvent.ACTION_MOVE:    if (!mScroller.isFinished()) {     // 终止滑动     mScroller.abortAnimation();    }    int offsetY = (int) (mLastY - event.getY());    Log.d(TAG, "onTouchEvent: getScrollY: " + getScrollY());    Log.d(TAG, "onTouchEvent: offsetY " + offsetY);    // 到达顶部,使用offset判断方向    if (getScrollY() + offsetY < 0) { // 当前已经滑动的 Y 位置     offsetY = 0;    }    // 到达底部    if (getScrollY() > getHeight() - mScreenHeight && offsetY > 0) {     offsetY = 0;    }    scrollBy(0, offsetY);    // 滑动完成后,重新设置LastY位置    mLastY = (int) event.getY();    break;   case MotionEvent.ACTION_UP:    mEnd = getScrollY();    int distance = mEnd - mStart;    if (distance > 0) { // 向上滑动     if (distance < mScreenHeight / 3) {      Log.d(TAG, "onTouchEvent: distance < screen/3");      // 回到原来位置      mScroller.startScroll(0, getScrollY(), 0, -distance);     } else {      // 滚到屏幕的剩余位置      mScroller.startScroll(0, getScrollY(), 0, mScreenHeight - distance);     }    } else {    // 向下滑动     if (-distance < mScreenHeight / 3) {      mScroller.startScroll(0, getScrollY(), 0, -distance);     } else {      mScroller.startScroll(0, getScrollY(), 0, -mScreenHeight - distance);     }    }    postInvalidate();  }  return super.onTouchEvent(event); } @Override public void computeScroll() {  if (mScroller.computeScrollOffset()) {   scrollTo(mScroller.getCurrX(), mScroller.getCurrY());   postInvalidate();  } }}

到此,相信大家对"Android中如何通过自定义ViewGroup实现一个弹性滑动效果"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

位置 弹性 屏幕 高度 效果 剩余 测量 代码 内容 方向 顶部 处理 学习 实用 更深 兴趣 原理 实用性 实际 操作简单 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 云电互联网科技 互联网科技logo 互联网高科技股票 互联网科技公司做什么 中国互联网金融科技基金 科技大学互联网专业好不好 太原新华互联网科技学校怎么样 青海省互联网新科技 湖南洣水互联网科技有限公司扣款 互联网实体化科技化 银川新华互联网科技职业技术培训学校图片 阿里互联网科技企业 互联网科技实习生岗位 浙南科技城互联网大厦招聘 上海创道互联网络科技有限公司 信承诺互联网科技有限公司 互联网时代科技型公司的机会 互联网科技职业技能培训学校 悟空问答互联网科技 第三届互联网大会安防黑科技 紫鲸互联网科技 时间互联网络科技 米客互联网科技 大白互联网科技 科技与互联网的利与弊 字节跳动和互联网科技 湖北码尼互联网科技有限公司电话 移动互联网科技公司 济南有互联网科技公司吗 重庆科技产业互联网有哪些
0