Android Scroller实现弹性滑动效果

 更新时间:2022年04月18日 16:16:26   作者:15130140362  
这篇文章主要为大家详细介绍了Android Scroller实现弹性滑动效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了Android Scroller实现弹性滑动的具体代码,供大家参考,具体内容如下

首先看下实现效果,可以看到当我们手指松开时图片会逐渐滑动到初始位置,而不是直接跳变到中心点。

代码实现

当手指触摸到view上时即TouchEvent位MotionEvent.ACTION_DOWN时,记录开始的坐标位置,同时由于手指再次按到屏幕上的的时候view还在执行动画,所以当动画还在执行的时候我们需要将动画停止。

if (!mScroller.isFinished()) {
    mScroller.abortAnimation();
                }
mStartX = (int) event.getX();
mStartY = (int) event.getY();

当然后当用户手指在屏幕上面滑动的时候,即event为MotionEvent.ACTION_MOVE时,我们需要将view的位置进行移动,这里我使用的是scrollBy的方式移动view的位置。

int curX = (int) event.getX();
int curY = (int) event.getY();
Log.i(TAG, "onTouchEvent: curX" + curX + "curY" + curY);
int delX = curX - mStartX;
int delY = curY - mStartY;
mStartX = curX;
mStartY = curY;
mViewGroup.scrollBy(-delX, -delY);

为什么使用scrollBy移动位置的时候前面还有个mViewGroup呢,因为我们在使用scrollBy/scrollTo的时候实际上移动的是view中内容,所以当我们想要移动view自身的时候那么就需要得到该view的parent,然后移动parent里面的内容,即我们需要移动的View,同时可以看到我们scrollBy方法中对变化的值取了负数,这个由于View内部计算滑动距离的两个属性的计算方式与我们平常使用的刚好相反。

mScrollX用来记录横向滚动的距离:该属性的计算方式为: view左边缘位置减去view内容左边缘位置

所以当我们滑动view到右侧的时候,我们需要对取变化距离的负值。

mScrollY用来计算纵向滚动的距离:该属性的计算方式为: view上边缘位置减去view内容上边缘的位置

紧接着当用的手指抬起的时候,即event为MotionEvent.ACTION_UP,我们需要将view平滑移动到起始位置。

case MotionEvent.ACTION_UP:
                mScroller.startScroll(mViewGroup.getScrollX(), mViewGroup.getScrollY(),
                        -mViewGroup.getScrollX(), -mViewGroup.getScrollY(), 1000);
                invalidate();// 在ui线程中调用
                break;

    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            mViewGroup.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            postInvalidate();// 在非ui线程中调用
        }
    }

这里我们使用了scroller进行平滑移动,查看startScroll的源码,这个函数其实并没有干什么

该函数知识设置了一些参数,并没有移动view的位置。View的移动其实是由下面的invalidate()触发的,因为invalidate()会让view 重绘,重新绘制的时候会调用到view自身的draw()方法,而draw方法又会调用到computeScroll()方法,再computeScroll()方法中,我们首先判断判断当前的移动是否结束,没有结束的话通过getCurrX(),getCurrY()移动到当前动画所在位置,然后再次重新绘制view,然后继续调用draw,继续上面的过程,直到scroller结束即computeScrollOffset()返回false。

完整代码

使用的时候只需要将这个view,放置在xml中,并配置一个图片背景

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".Main2Activity">

    <com.example.recyclerviewlearn.CustomizeImageView
        android:layout_centerInParent="true"
        android:background="@drawable/ic_launcher_background"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</RelativeLayout>

下面是自定义ImageView的代码

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

public class CustomizeImageView extends androidx.appcompat.widget.AppCompatImageView {
    private static final String TAG = "CustomizeImageView";

    private ViewGroup mViewGroup;

    private int mStartX = 0;

    private int mStartY = 0;

    private Scroller mScroller = new Scroller(this.getContext());

    public CustomizeImageView(Context context) {
        super(context);
    }

    public CustomizeImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomizeImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        mViewGroup = (ViewGroup) getParent();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i(TAG, "onTouchEvent: ");
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (!mScroller.isFinished()) {
                    mScroller.abortAnimation();
                }
                mStartX = (int) event.getX();
                mStartY = (int) event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                Log.i(TAG, "onTouchEvent: startX" + mStartX + "mStartY" + mStartY);
                int curX = (int) event.getX();
                int curY = (int) event.getY();
                Log.i(TAG, "onTouchEvent: curX" + curX + "curY" + curY);
                int delX = curX - mStartX;
                int delY = curY - mStartY;
                mStartX = curX;
                mStartY = curY;
                Log.i(TAG, "onTouchEvent: ACTION_MOVE");
                mViewGroup.scrollBy(-delX, -delY);
                break;
            case MotionEvent.ACTION_UP:
                mScroller.startScroll(mViewGroup.getScrollX(), mViewGroup.getScrollY(),
                        -mViewGroup.getScrollX(), -mViewGroup.getScrollY(), 1000);
                invalidate();
                break;
            default:
                break;
        }
        return true;
    }

    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            mViewGroup.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            invalidate();
        }
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Android利用AudioRecord类实现音频录制程序

    Android利用AudioRecord类实现音频录制程序

    这篇文章主要为大家详细介绍了Android利用AudioRecord类实现音频录制程序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-04-04
  • Android O对后台Service限制详解

    Android O对后台Service限制详解

    这篇文章主要为大家介绍了Android O对后台Service限制详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • Android创建外部lib库及自定义View的图文教程

    Android创建外部lib库及自定义View的图文教程

    这篇文章主要给大家介绍了关于Android创建外部lib库及自定义View的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11
  • android实现底部导航栏

    android实现底部导航栏

    这篇文章主要为大家详细介绍了android实现底部导航栏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-06-06
  • Android实现视频播放--腾讯浏览服务(TBS)功能

    Android实现视频播放--腾讯浏览服务(TBS)功能

    TBS视频播放器可以支持市面上几乎所有的视频格式,包括mp4, flv, avi, 3gp, webm, ts, ogv, m3u8, asf, wmv, rm, rmvb, mov, mkv等18种视频格式。这篇文章主要介绍了Android实现视频播放--腾讯浏览服务(TBS),需要的朋友可以参考下
    2018-07-07
  • Android中查看USB连接的外接设备信息的代码实例

    Android中查看USB连接的外接设备信息的代码实例

    这篇文章主要介绍了Android中查看USB连接的外接设备信息的代码实例,需要的朋友可以参考下
    2014-04-04
  • Android 自定义SeekBar 实现分段显示不同背景颜色的示例代码

    Android 自定义SeekBar 实现分段显示不同背景颜色的示例代码

    这篇文章主要介绍了Android 自定义SeekBar 实现分段显示不同背景颜色,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-06-06
  • Android TextView实现垂直滚动效果的方法

    Android TextView实现垂直滚动效果的方法

    这篇文章主要介绍了Android TextView实现垂直滚动效果的方法,结合实例形式简单分析了Android TextView控件垂直滚动效果的相关属性功能与设置技巧,需要的朋友可以参考下
    2016-10-10
  • 利用Android设计一个倒计时组件

    利用Android设计一个倒计时组件

    在很多电商工作项目中经常有倒计时的场景,比如活动倒计时、抢红包倒计时等等,今天小编就带大家来学习如何利用Android设计倒计时组件,感兴趣的小伙伴一起奥
    2021-09-09
  • 如何使用Matrix对bitmap的旋转与镜像水平垂直翻转

    如何使用Matrix对bitmap的旋转与镜像水平垂直翻转

    本篇文章是对使用Matrix对bitmap的旋转与镜像水平垂直翻转进行了详细的分析介绍,需要的朋友参考下
    2013-06-06

最新评论