oschina源码分析之侧滑菜单界面之可以拖动的ScrollView

2023-11-13

先上源码:

package net.oschina.app.widget;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.TranslateAnimation;
import android.widget.ScrollView;

/**
 * 可以拖动的ScrollView
 *
 */
public class CustomerScrollView extends ScrollView {
    private static final String TAG = "CustomerScrollView";
    private static final int size = 4;
    private View inner;
    private float y;
    private Rect normal = new Rect();

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

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

    @Override
    protected void onFinishInflate() {
        if (getChildCount() > 0) {
            inner = getChildAt(0);
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (inner == null) {
            return super.onTouchEvent(ev);
        } else {
            commOnTouchEvent(ev);
        }
        return super.onTouchEvent(ev);
    }

    public void commOnTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        switch (action) {
        case MotionEvent.ACTION_DOWN:
            y = ev.getY();
            break;
        case MotionEvent.ACTION_UP:
            if (isNeedAnimation()) {
                // Log.v("mlguitar", "will up and animation");
                animation();
            }
            break;
        case MotionEvent.ACTION_MOVE:
            final float preY = y;
            float nowY = ev.getY();
            /**
             * size=4 表示 拖动的距离为屏幕的高度的1/4
             */
            int deltaY = (int) (preY - nowY) / size;
            Log.i(TAG, "commOnTouchEvent: deltay="+ deltaY +"preY" + preY +"nowY" + nowY );
            // 滚动
            // scrollBy(0, deltaY);

            y = nowY;
            if (isNeedMove()) {
                Log.i(TAG, "commOnTouchEvent:  normal.isEmpty:"  + normal.isEmpty());
                if (normal.isEmpty()) {
                    Log.i(TAG, "commOnTouchEvent: inner:" + inner.getLeft() + "," + inner.getTop() + "," + inner.getRight() + "," + inner.getBottom());

                    normal.set(inner.getLeft(), inner.getTop(),
                            inner.getRight(), inner.getBottom());
                    return;
                }
                int yy = inner.getTop() - deltaY;
                Log.i(TAG, "commOnTouchEvent: new layout:" + inner.getLeft() + "," + yy + "," + inner.getRight() + "," + (inner.getBottom() - deltaY));
                // 移动布局
                inner.layout(inner.getLeft(), yy, inner.getRight(),
                        inner.getBottom() - deltaY);
            }
            break;
        default:
            break;
        }
    }

    public void animation() {
        TranslateAnimation ta = new TranslateAnimation(0, 0, inner.getTop(),
                normal.top);
        ta.setDuration(200);

        Log.i(TAG, "animation start " + "(0,0," + inner.getTop() +"," + normal.top + ")");


        inner.startAnimation(ta);
        inner.layout(normal.left, normal.top, normal.right, normal.bottom);
        normal.setEmpty();
    }

    public boolean isNeedAnimation() {
        Log.i(TAG, "isNeedAnimation: " + !normal.isEmpty());
        return !normal.isEmpty();
    }

    public boolean isNeedMove() {
        int offset = inner.getMeasuredHeight() - getHeight();
        int scrollY = getScrollY();
        Log.i(TAG, "isNeedMove: " + "scrollY=" + scrollY + "offset=" + offset);
        if (scrollY == 0 || scrollY == offset) {
            return true;
        }
        return false;
    }

}
  • 先看isNeedMove()函数:

    1. int offset = inner.getMeasuredHeight() - getHeight();

    前者一般与后者相等,只有当view超出屏幕后前者才会比后者大,getMeasuredHeight() 等于 getHeight()加上屏幕之外没有显示的大小。

    1. int scrollY = getScrollY();

    看下官方对这个函数的介绍:The top edge of the displayed part of your view, in pixels. 返回的是view的顶端超过屏幕部分的大小。

因此,这个函数的判断条件其实就是view在屏幕最上面或者最下面这两种情况才需要移动。

  • 再看移动事件(commOnTouchEvent):
    1. 点击获取初始位置,抬起判断是否需要移动,主要看一下移动这个事件(MotionEvent.ACTION_MOVE)。
    2. 首先根据移动的Y和初始的Y得到移动的距离:int deltaY = (int) (preY - nowY) / size;
    3. 判断是否需要移动。如果需要,第一次用normal这个变量来记录原始的view范围,然后用inner.layout(inner.getLeft(), yy, inner.getRight(),
      inner.getBottom() - deltaY);来移动布局。就是根据先前得到的移动距离来改变view的上下显示范围。
    4. 最后就是退回动画:TranslateAnimation ta = new TranslateAnimation(0, 0, inner.getTop(),
      normal.top);就是简单的由现在的Y变化到记录的原始的Y。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

oschina源码分析之侧滑菜单界面之可以拖动的ScrollView 的相关文章

  • 使用开源软件的可填写、可保存表单的 PDF [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我的问题是一个延伸this one https stackoverflow com questions
  • 还有充分的理由支持 JDK 1.4 吗? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我正在考虑用 Java 构建一个开源项目 并且正在激烈争论不支持 JDK 1 4 及更早版本 该框架绝对可以使用较旧的 Java 模式和习惯用法
  • 最佳开源 LINQ 提供商 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 你能给我指一个大型 Python 开源项目吗? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想看看用 Python 完成的大型 gt 40 名开发人员 项目是什么样子的 代码是什么样子的 他们使
  • 有哪些很棒的在线数据库建模工具? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 是否有用于 Windows 驱动程序开发的开源 C 库(非 c++)? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否有用于 Windows 驱动程序开发的开源 C 库 非 c 我正在开发一个网络设备驱动程序 需要一些
  • 有 ASP.Net 基准测试工具吗? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想测量 Net 应用程序的性能 特别是在服务器中运行时 ASP Net 中的 Web 应用程序 我需
  • 通用枚举到可迭代转换器[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 HttpServletRequest 使用了大量 java util Enumeration 我想在
  • 有开源的pastebin吗? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我经常编写 wiki 页面或设置需要与其他开发人员共享的配置文件 是否有任何可以安装在您自己的网络中的
  • .Net WikiText 到 HTML 解析器 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我知道 我知道 这听起来很愚蠢 但似乎没有开源强大的 NET 库可以将 Wikitext 解析为 HT
  • 有哪些开源 C 项目值得学习来学习好的设计? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 有哪些小型 C 语言开源项目对于学习良好的设计很有趣 该项目应该是 不太大 像linux内核 有据可查 也许仍在积极开发中 我刚刚开始学习
  • C++ 开源随机数生成算法? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我需要连续生成 1 10000 范围内的随机数 不能重复 有什么建议吗 描述 我们正在为我们的应用程序
  • iPhone 平台的开源框架/项目 [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找适用于 iPhone 平台的开源框架 项目集合 我发现了很多好的框架和资源 例如ASIHTTP
  • 是否存在 Yahoogroups api?

    我们有 yahoogroups api 吗 我有一个 yahoo 群组 我希望每当我的 RSS 源更新时 都会自动向该群组发布一条消息 其中包含该帖子的链接 那可能吗 不 Yahoo 没有公共 API 团体 如果这样的 API 被开放 雅虎
  • 值得学习的优秀 Zend Framework 示例应用程序 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 礼仪:版本会影响我的开源项目分支吗? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 这个问题是关于礼仪和开源项目的 我从 github 分叉了一个应用程序并添加了两个新功能 The 第一个特征在其他地方经常被要求 我已经添加了
  • 哪里可以找到可靠的 K-medoid(不是 k-means)开源软件/工具? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在学习 K medoids 算法 所以如果我提出不恰当的问题 我很抱歉 据我所知 K medoid
  • Safari 的“阅读器模式” - 开源解决方案? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 Safari 有一个 阅读器模式 可以删除网站上除文本之外的所有内容 有谁知道提供相同功能的开源库 或
  • 将 GitHub 与另一个 Bug 跟踪器一起使用? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我参与了这个项目 Pinta http pinta project com 我们目前正在使用 GitHub 进行开发 我们都喜欢 Git 和 G
  • 将字符转换为日期时间 odoo 9

    我有两个字符字段 从 odoo 中的 excel 或 csv 导入数据 time 1 fields Char string Time 1 time 2 fields Char string Time 2 result fields Floa

随机推荐

  • Qt 与外部exe进程间通信-基于操作系统的消息传递

    步骤 进程A 通过WindowAPI找到需要传递信息的窗口 然后通过windowAPI发送自定义的消息 其实本质上还是window操作系统定义的消息结构 只不过其中有个字段的值被设置成了自己特有的值 const ULONG PTR CUST
  • Java分割字符串(spilt())

    String 类的 split 方法可以按指定的分割符对目标字符串进行分割 分割后的内容存放在字符串数组中 该方法主要有如下两种重载形式 str split String sign str split String sign int lim
  • 学好了Python可以干什么?

    随着我国对编程的重视程度上升 Python编程的学习趋势逐渐低龄化 在全国掀起Python编程热的同时 还是有许多人对于学习Python抱有怀疑 那么我们就来看看学好了Python究竟可以干什么 根据目前就业市场的反馈 我们可以看到Pyth
  • Cscope的使用

    转载自 http blog csdn net dengxiayehu article details 6330200 首先在目录下建立cscope索引文件 find name c gt cscope file cscope Rbkq 这个命
  • ST芯片使用串口 + DMA接收 + 空闲中断处理,有USART1和LPUART

    普通串口 USART1 首先是DMA初始化 DMA初始化 void MX DMA Init void Init with LL driver DMA controller clock enable LL AHB EnableClock LL
  • 最新淘宝主图下载方法-最新淘宝主图下载工具-马赛克视频助手

    做电商的朋友经常需要去下载淘宝上的别人的主图视频 那么淘宝主图视频怎么下载呢 工具 材料 马赛克视频助手 免费工具 www mask4 com 大家自行下载 操作方法 1 先打开马赛克视频助手 2 随便打开一个淘宝主图地址 如果是手机端的朋
  • ORA-00937: not a single-group group function说明及解决方法

    A SELECT list cannot include both a group function such as AVG COUNT MAX MIN SUM STDDEV or VARIANCE and an individual co
  • uni-app调用手机摄像头进行扫码

  • 放弃node-sass,启用sass

    在下载一个新项目时运行 npm run install 发现报错 npm uninstall 异常 Error Could not find any Visual Studio installation to use 或是 You need
  • 滑动平均滤波

    滑动平均滤波是一种常用的数字信号处理技术 它可以有效地去除信号中的噪声 提高信号的质量 滑动平均滤波的原理是对信号的每一个采样点 取其周围的若干个点的平均值作为滤波后的值 这样 信号中的随机噪声会被平均掉 而信号中的有用信息会被保留 用C语
  • 人民日报:密码,让百姓生活更安全

    密码技术是保障网络与信息安全的核心技术和基础支撑 通过加密保护和安全认证两大核心功能 可以完整实现防假冒 防泄密 防篡改 抗抵赖等安全需求 在网络空间中扮演着 信使 卫士 和 基因 的重要角色 信息化 网络化 数字化高度发达的今天 密码技术
  • 【突发】解决remote: Support for password authentication was removed on August 13, 2021. Please use a perso

    今天 github突然宣布 无法通过用户名加密码进行上传代码和访问 git push remote Support for password authentication was removed on August 13 2021 Plea
  • 策略模式+注解,代替if-else

    策略模式 经常在网上看到一些名为 别再if else走天下了 教你干掉if else 等之类的文章 大部分都会讲到用策略模式去代替if else 策略模式实现的方式也大同小异 主要是定义统一行为 接口或抽象类 并实现不同策略下的处理逻辑 对
  • 判断exe是64位还是32位

    右击exe属性 查看兼容模式 如果有windwos vista之前的版本则为32位的 如下图 如果没有windwos vista之前的版本则为64位的 如下图 转载于 https www cnblogs com tiandsp p 9603
  • Dubbo基础学习

    目录 第一章 概念介绍 1 1 什么是RPC框架 1 2 什么是分布式系统 1 3 Dubbo概述 1 3 Dubbo基本架构 第二章 服务提供者 直连 2 1 目录结构和依赖 2 2 model层 2 3 service层 2 4 res
  • 复用推挽输出与推挽输出区别

    GPIO InitStructure GPIO Mode GPIO Mode AF PP 复用推挽输出 GPIO SetBits GPIOE GPIO Pin 5 如果LED1是上拉的话 这时候它被点亮了 GPIO Mode AF PP g
  • QT 调用执行 linux脚本的三种方法

    在linux系统下 Qt执行shell命令的方式有3种 1 QProcess execute ls 2 system ls 3 QProcess process new QProcess process gt start ls 注1 以上3
  • 2020电赛准备总结(四)

    现在是2020 10 6 距离电赛开始还有三天 最近在考虑要不要让自己提前紧张起来 第一次准备这样的比赛 实在是没有经验 还差一口气没顶上去的感觉 最近开始调整状态了 从开学9 10到现在也快一个月了 感觉自己写博客总是在诉苦 像个怨妇一样
  • UVA-1601 万圣节后的早晨 题解答案代码 算法竞赛入门经典第二版

    GitHub jzplp aoapc UVA Answer 算法竞赛入门经典 例题和习题答案 刘汝佳 第二版 以三个点的当前位置作为状态 广度优先遍历 找到终点即为最短次数 注意 一次可以移动多个点 但是每个点只能移动一步 在同一次中 B可
  • oschina源码分析之侧滑菜单界面之可以拖动的ScrollView

    先上源码 package net oschina app widget import android annotation SuppressLint import android content Context import android