我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android怎么自定义View实现竖向滑动回弹效果

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android怎么自定义View实现竖向滑动回弹效果

这篇文章主要介绍“Android怎么自定义View实现竖向滑动回弹效果”,在日常操作中,相信很多人在Android怎么自定义View实现竖向滑动回弹效果问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Android怎么自定义View实现竖向滑动回弹效果”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一、关键代码

public class UniversalBounceView extends FrameLayout implements IPull {     private static final String TAG = "UniversalBounceView";    //default.    private static final int SCROLL_DURATION = 200;    private static final float SCROLL_FRACTION = 0.4f;     private static final int VIEW_TYPE_NORMAL = 0;    private static final int VIEW_TYPE_ABSLISTVIEW = 1;    private static final int VIEW_TYPE_SCROLLVIEW = 2;     private static float VIEW_SCROLL_MAX = 720;    private int viewHeight;     private AbsListView alv;    private OnBounceStateListener onBounceStateListener;     private View child;    private Scroller scroller;    private boolean pullEnabled = true;    private boolean pullPaused;    private int touchSlop = 8;     private int mPointerId;     private float downY, lastDownY, tmpY;    private int lastPointerIndex;     private float moveDiffY;    private boolean isNotJustInClickMode;    private int moveDelta;    private int viewType = VIEW_TYPE_NORMAL;     public UniversalBounceView(Context context) {        super(context);        init(context);    }     public UniversalBounceView(Context context, AttributeSet attrs) {        super(context, attrs);        init(context);    }     public UniversalBounceView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init(context);    }     private void init(Context context) {        scroller = new Scroller(context, new CustomDecInterpolator());        touchSlop = (int) (ViewConfiguration.get(context).getScaledTouchSlop() * 1.5);    }     class CustomDecInterpolator extends DecelerateInterpolator {         public CustomDecInterpolator() {            super();        }         public CustomDecInterpolator(float factor) {            super(factor);        }         public CustomDecInterpolator(Context context, AttributeSet attrs) {            super(context, attrs);        }         @Override        public float getInterpolation(float input) {            return (float) Math.pow(input, 6.0 / 12);        }    }     private void checkCld() {        int cnt = getChildCount();        if (1 <= cnt) {            child = getChildAt(0);        } else if (0 == cnt) {            pullEnabled = false;            child = new View(getContext());        } else {            throw new ArrayIndexOutOfBoundsException("child count can not be less than 0.");        }    }     @Override    protected void onFinishInflate() {        checkCld();        super.onFinishInflate();    }     @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        viewHeight = h;        VIEW_SCROLL_MAX = h * 1 / 3;    }     private boolean isTouch = true;     public void setTouch(boolean isTouch) {        this.isTouch = isTouch;    }     @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        if (!isTouch) {            return true;        } else {            try {                if (isPullEnable()) {                    if (ev.getActionMasked() == MotionEvent.ACTION_MOVE) {                        if (Math.abs(ev.getY() - tmpY) < touchSlop) {                            return super.dispatchTouchEvent(ev);                        } else {                            tmpY = Integer.MIN_VALUE;                        }                    }                    return takeEvent(ev);                }            } catch (IllegalArgumentException | IllegalStateException e) {                e.printStackTrace();            }            if (getVisibility() != View.VISIBLE) {                return true;            }            return super.dispatchTouchEvent(ev);        }    }     private boolean takeEvent(MotionEvent ev) {        int action = ev.getActionMasked();        switch (action) {            case MotionEvent.ACTION_DOWN:                mPointerId = ev.getPointerId(0);                downY = ev.getY();                tmpY = downY;                scroller.setFinalY(scroller.getCurrY());                setScrollY(scroller.getCurrY());                scroller.abortAnimation();                pullPaused = true;                isNotJustInClickMode = false;                moveDelta = 0;                break;            case MotionEvent.ACTION_UP:            case MotionEvent.ACTION_CANCEL:                pullPaused = false;                smoothScrollTo(0);                if (isNotJustInClickMode) {                    ev.setAction(MotionEvent.ACTION_CANCEL);                }                postDelayed(new Runnable() {                    @Override                    public void run() {                        if (getScrollY() == 0 && onBounceStateListener != null) {                            onBounceStateListener.overBounce();                        }                    }                }, 200);                break;            case MotionEvent.ACTION_MOVE:                lastPointerIndex = ev.findPointerIndex(mPointerId);                lastDownY = ev.getY(lastPointerIndex);                moveDiffY = Math.round((lastDownY - downY) * getScrollFraction());                downY = lastDownY;                boolean canStart = isCanPullStart();                boolean canEnd = isCanPullEnd();                int scroll = getScrollY();                float total = scroll - moveDiffY;                if (canScrollInternal(scroll, canStart, canEnd)) {                    handleInternal();                    break;                }                if (Math.abs(scroll) > VIEW_SCROLL_MAX) {                    return true;                }                if ((canStart && total < 0) || (canEnd && total > 0)) {                    if (moveDelta < touchSlop) {                        moveDelta += Math.abs(moveDiffY);                    } else {                        isNotJustInClickMode = true;                    }                    if (onBounceStateListener != null) {                        onBounceStateListener.onBounce();                    }                    scrollBy(0, (int) -moveDiffY);                    return true;                }//                else if ((total > 0 && canStart) || (total < 0 && canEnd)) {//                    if (moveDelta < touchSlop) {//                        moveDelta += Math.abs(moveDiffY);//                    } else {//                        isNotJustInClickMode = true;//                    }//                    scrollBy(0, -scroll);//                    return true;//                }                break;            case MotionEvent.ACTION_POINTER_UP:                handlePointerUp(ev, 1);                break;            default:                break;        }        return super.dispatchTouchEvent(ev);    }     private boolean canScrollInternal(int scroll, boolean canStart, boolean canEnd) {        boolean result = false;        if ((child instanceof RecyclerView) || (child instanceof AbsListView) || child instanceof ScrollView) {            viewType = VIEW_TYPE_ABSLISTVIEW;            result = canStart && canEnd;        } else if (child instanceof ScrollView || child instanceof NestedScrollView) {            viewType = VIEW_TYPE_SCROLLVIEW;        } else {            return false;        }        if (result) {            isNotJustInClickMode = true;            if (moveDelta < touchSlop) {                moveDelta += Math.abs(moveDiffY);                return true;            }            return false;        }        if (((scroll == 0 && canStart && moveDiffY < 0) || (scroll == 0 && canEnd && moveDiffY > 0) || (!canStart && !canEnd))) {            return true;        }        if (moveDelta < touchSlop) {            moveDelta += Math.abs(moveDiffY);            return true;        } else {            isNotJustInClickMode = true;        }        return false;    }     private void handleInternal() {     }     private void handlePointerUp(MotionEvent event, int type) {        int pointerIndexLeave = event.getActionIndex();        int pointerIdLeave = event.getPointerId(pointerIndexLeave);        if (mPointerId == pointerIdLeave) {            int reIndex = pointerIndexLeave == 0 ? 1 : 0;            mPointerId = event.getPointerId(reIndex);            // 调整触摸位置,防止出现跳动            downY = event.getY(reIndex);        }    }     @Override    public boolean onTouchEvent(MotionEvent event) {        return super.onTouchEvent(event);    }     private void smoothScrollTo(int value) {        int scroll = getScrollY();        scroller.startScroll(0, scroll, 0, value - scroll, SCROLL_DURATION);        postInvalidate();    }     @Override    public void computeScroll() {        super.computeScroll();        if (!pullPaused && scroller.computeScrollOffset()) {            scrollTo(scroller.getCurrX(), scroller.getCurrY());            postInvalidate();        }    }     private float getScrollFraction() {        float ratio = Math.abs(getScrollY()) / VIEW_SCROLL_MAX;        ratio = ratio < 1 ? ratio : 1;        float fraction = (float) (-2 * Math.cos((ratio + 1) * Math.PI) / 5.0f) + 0.1f;        return fraction < 0.10f ? 0.10f : fraction;    }     @Override    public boolean isPullEnable() {        return pullEnabled;    }     @Override    public boolean isCanPullStart() {        if (child instanceof RecyclerView) {            RecyclerView recyclerView = (RecyclerView) child;            return !recyclerView.canScrollVertically(-1);        }        if (child instanceof AbsListView) {            AbsListView lv = (AbsListView) child;            return !lv.canScrollVertically(-1);        }        if (child instanceof RelativeLayout                || child instanceof FrameLayout                || child instanceof LinearLayout                || child instanceof WebView                || child instanceof View) {            return child.getScrollY() == 0;        }        return false;    }     @Override    public boolean isCanPullEnd() {        if (child instanceof RecyclerView) {            RecyclerView recyclerView = (RecyclerView) child;            return !recyclerView.canScrollVertically(1);        }        if (child instanceof AbsListView) {            AbsListView lv = (AbsListView) child;            int first = lv.getFirstVisiblePosition();            int last = lv.getLastVisiblePosition();            View view = lv.getChildAt(last - first);            if (null == view) {                return false;            } else {                return (lv.getCount() - 1 == last) &&                        (view.getBottom() <= lv.getHeight());            }        }        if (child instanceof ScrollView) {            View v = ((ScrollView) child).getChildAt(0);            if (null == v) {                return true;            } else {                return child.getScrollY() >= v.getHeight() - child.getHeight();            }        }        if (child instanceof NestedScrollView) {            View v = ((NestedScrollView) child).getChildAt(0);            if (null == v) {                return true;            } else {                return child.getScrollY() >= v.getHeight() - child.getHeight();            }        }        if (child instanceof WebView) {            return (((WebView) child).getContentHeight() * ((WebView) child).getScale()) - (((WebView) child).getHeight() + ((WebView) child).getScrollY()) <= 10;        }        if (child instanceof RelativeLayout                || child instanceof FrameLayout                || child instanceof LinearLayout                || child instanceof View) {            return (child.getScrollY() == 0);        }        return false;    }         public void replaceAddChildView(View replaceChildView) {        if (replaceChildView != null) {            removeAllViews();            child = replaceChildView;            addView(replaceChildView);        }    }     public void setPullEnabled(boolean enable) {        pullEnabled = enable;    }     public interface OnBounceStateListener {        public void onBounce();         public void overBounce();    }     public void setOnBounceStateListener(OnBounceStateListener onBounceStateListener) {        this.onBounceStateListener = onBounceStateListener;    }     @Override    public boolean dispatchKeyEvent(KeyEvent event) {        try {            return super.dispatchKeyEvent(event);        } catch (IllegalArgumentException | IllegalStateException e) {            e.printStackTrace();        }        return false;    }     @Override    public void dispatchWindowFocusChanged(boolean hasFocus) {        try {            super.dispatchWindowFocusChanged(hasFocus);        } catch (IllegalArgumentException | IllegalStateException e) {            e.printStackTrace();        }    }  }

二、注意要点

滑动结束的时候要防止动画抖动

private void handlePointerUp(MotionEvent event, int type) {        int pointerIndexLeave = event.getActionIndex();        int pointerIdLeave = event.getPointerId(pointerIndexLeave);        if (mPointerId == pointerIdLeave) {            int reIndex = pointerIndexLeave == 0 ? 1 : 0;            mPointerId = event.getPointerId(reIndex);            // 调整触摸位置,防止出现跳动            downY = event.getY(reIndex);        }    }

到此,关于“Android怎么自定义View实现竖向滑动回弹效果”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android怎么自定义View实现竖向滑动回弹效果

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android怎么自定义View实现竖向滑动回弹效果

这篇文章主要介绍“Android怎么自定义View实现竖向滑动回弹效果”,在日常操作中,相信很多人在Android怎么自定义View实现竖向滑动回弹效果问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Andro
2023-06-30

Android中自定义view实现侧滑效果

效果图:看网上的都是两个view拼接,默认右侧的不显示,水平移动的时候把右侧的view显示出来。但是看最新版QQ上的效果不是这样的,但给人的感觉却很好,所以献丑来一发比较高仿的。 知识点: 1、ViewDragHelper 的用法; 2、
2022-06-06

Android怎么自定义scrollview实现回弹效果

本篇内容主要讲解“Android怎么自定义scrollview实现回弹效果”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Android怎么自定义scrollview实现回弹效果”吧!1. 新建M
2023-06-29

Android自定义View实现弹性小球效果

照例先看效果图自定义代码示例public class BezierView extends View {Paint paint;//画笔Path path;//路径int radius = 50;//圆的半径int time = 100;/
2022-06-06

怎么在Android中通过自定义view实现滑动解锁效果

怎么在Android中通过自定义view实现滑动解锁效果?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。自定义view如下@SuppressLint("ClickableVi
2023-06-15

Android如何自定View实现滑动验证效果

本篇内容主要讲解“Android如何自定View实现滑动验证效果”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Android如何自定View实现滑动验证效果”吧!效果图自定义属性代码
2023-06-22

Android自定义View实现动画效果详解

这篇文章主要为大家详细介绍了Android如何通过自定义View实现动画效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
2023-02-02

Android自定义View实现竖直跑马灯效果案例解析

首先给出跑马灯效果图 中间的色块是因为视频转成GIF造成的失真,自动忽略哈。 大家知道,横向的跑马灯android自带的TextView就可以实现,详情请百度【Android跑马灯效果】。但是竖直的跑马灯效果原生Android是不支持的。
2022-06-06

Android自定义View实现loading动画加载效果

项目开发中对Loading的处理是比较常见的,安卓系统提供的不太美观,引入第三发又太麻烦,这时候自己定义View来实现这个效果,并且进行封装抽取给项目提供统一的loading样式是最好的解决方式了。 先自定义一个View,继承自Linea
2022-06-06

Android 自定义view实现水波纹动画效果

在实际的开发中,很多时候还会遇到相对比较复杂的需求,比如产品妹纸或UI妹纸在哪看了个让人兴奋的效果,兴致高昂的来找你,看了之后目的很明确,当然就是希望你能给她;在这样的关键时候,身子板就一定得硬了,可千万别说不行,爷们儿怎么能说不行呢;好了
2023-05-31

Android自定义控件实现滑动开关效果

自定义开关控件 Android自定义控件一般有三种方式 1、继承Android固有的控件,在Android原生控件的基础上,进行添加功能和逻辑。 2、继承ViewGroup,这类自定义控件是可以往自己的布局里面添加其他的子控件的。
2022-06-06

Android自定义View实现纵向跑马灯效果详解

首先看看效果图(录制的gif有点卡,真实的效果还是很流畅的)实现思路通过上面的gif图可以得出结论,其实它就是同时绘制两条文本信息,然后通过动画不断的改变两条文本信息距离顶部的高度,以此来实现滚动的效果。 具体实现首先定义一些要用到的属性<
2022-06-06

Android自定义View实现飘动的叶子效果(三)

上一篇对自定义View及一些方法有所了解,下面做一个简单的叶子飘动的例子主要技术点 1、添加背景图片canvas.drawBitmap() 2、Matrix动画类 3、Matrix添加到画布上 步骤 1、添加黄色背景颜色public Lea
2022-06-06

Android中怎么自定义View实现标签流效果

本篇内容主要讲解“Android中怎么自定义View实现标签流效果”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Android中怎么自定义View实现标签流效果”吧!一、概述Android自定义
2023-06-29

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录