Android自定义控件ScrollView实现上下滑动功能

news2025/6/24 6:26:08

本文实例为大家分享了Android ScrollView实现上下滑动功能的具体代码,供大家参考,具体内容如下

package com.example.zhuang;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Scroller;
public class MyScrollView extends ViewGroup {
private int mScreeHeight;//屏幕高度
private Scroller mScroller;
private int mLastY;
private int mStart;
private int mEnd;
private Context context;
public MyScrollView(Context context) {
super(context);
initView(context);
}
public MyScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public MyScrollView(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
}
private void initView(Context context) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
//DisplayMetrics 类提供了一种关于显示的通用信息,如显示大小,分辨率和字体。
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
mScreeHeight = dm.heightPixels;//高度(像素)
mScroller = new Scroller(context);
}
//继承ViewGroup必须要实现的方法
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int childCount = getChildCount();//获取子view的个数
//设置ViewGroup的高度
MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();
mlp.height = mScreeHeight * childCount;
setLayoutParams(mlp);
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child.getVisibility() != View.GONE) {
//参数为相对父容器的左上右下位置,第三个参数必须为r
child.layout(0, i * mScreeHeight, r, (i + 1) * mScreeHeight);
}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
measureChild(child, widthMeasureSpec, heightMeasureSpec);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int y = (int) event.getY();//相对于view的y值,getRawY()是相对屏幕
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastY = y;//上一次的y值
mStart = getScrollY();//记录触摸起点
break;
case MotionEvent.ACTION_MOVE:
if(!mScroller.isFinished()) {
mScroller.abortAnimation();//放弃移到最终位置
}
int dy = mLastY - y;//偏移距离
//如果滑动距离小于0或大于屏幕高度,不偏移
if(getScrollY()<0){
dy = 0;
}
if(getScrollY()   getHeight()-mScreeHeight){
dy = 0;
}
scrollBy(0,dy);//移动
mLastY = y;
break;
case MotionEvent.ACTION_UP:
int dScrollY = checkAlignment();//整体移动的距离
if(dScrollY   0){
if(dScrollY < mScreeHeight / 3){
mScroller.startScroll(0,getScrollY(),0,-dScrollY);
}else{
mScroller.startScroll(0,getScrollY(),0,mScreeHeight-dScrollY);
}
}else{
if(-dScrollY < mScreeHeight / 3){
mScroller.startScroll(0,getScrollY(),0,-dScrollY);
}else{
mScroller.startScroll(0,getScrollY(),0,-mScreeHeight-dScrollY);
}
}
break;
}
postInvalidate();
return true;
}
private int checkAlignment(){
mEnd = getScrollY();//记录触摸终点
boolean isUp = ((mEnd - mStart) 0) ? true : false;
int lastPrev = mEnd % mScreeHeight;
int lastNext = mScreeHeight - lastPrev;
if(isUp){
return lastPrev;//向上
}else
return -lastNext;
}
@Override
public void computeScroll() {
super.computeScroll();
if(mScroller.computeScrollOffset()){//返回true,表示还未移动完
scrollTo(0,mScroller.getCurrY());//移到当前位置
postInvalidate();
//invalidate()是用来刷新View的,必须是在UI线程中进行工作。
//postInvalidate()可以在非UI线程调用
}
}
}

知识点:

1、获取屏幕参数代码:

DisplayMetrics metric = new DisplayMetrics(); 
//API 17之后使用,获取的像素宽高包含虚拟键所占空间,在API 17之前通过反射获取 
context.getWindowManager().getDefaultDisplay().getRealMetrics(metric); 
//获取的像素宽高不包含虚拟键所占空间 
//context.getWindowManager().getDefaultDisplay().getMetrics(metric); 
int width = metric.widthPixels; // 宽度(像素) 
int height = metric.heightPixels; // 高度(像素) 
float density = metric.density; // dp缩放因子 
int densityDpi = metric.densityDpi; // 广义密度 
float xdpi = metric.xdpi;//x轴方向的真实密度 
float ydpi = metric.ydpi;//y轴方向的真实密度 

屏幕高度值包含了状态栏的像素,非沉浸模式下真实的Activity高度需要减去状态栏的高度。获取状态栏高度代码:

private int getStatusBarHeight() { 
Rect rect = new Rect(); 
getWindow().getDecorView().getWindowVisibleDisplayFrame(rect); 
return rect.top; 
} 

屏幕参数Width和Height的值和屏幕方向有关,另外4个值和屏幕方向无关。

更多Android进阶指南 可以扫码 解锁 《Android十大板块文档》

1.Android车载应用开发系统学习指南(附项目实战)

2.Android Framework学习指南,助力成为系统级开发高手

3.2024最新Android中高级面试题汇总+解析,告别零offer

4.企业级Android音视频开发学习路线+项目实战(附源码)

5.Android Jetpack从入门到精通,构建高质量UI界面

6.Flutter技术解析与实战,跨平台首要之选

7.Kotlin从入门到实战,全方面提升架构基础

8.高级Android插件化与组件化(含实战教程和源码)

9.Android 性能优化实战+360°全方面性能调优

10.Android零基础入门到精通,高手进阶之路

敲代码不易,关注一下吧。ღ( ´・ᴗ・` ) 🤔

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1584458.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Asterisk 21.2.0编译安装经常遇到的问题和解决办法之pjproject

目录 Asterisk社区官方的说法然而买家秀是这样的pjproject-2.14下载不了的问题如何解决 Asterisk社区官方的说法 编译安装Asterisk 21.2.0版本 按照官网文档&#xff0c;原则上只需要如下几步&#xff1a; ./contrib/scripts/install_prereq install ./configure make make i…

建立一个网站需要多长时间?如何从零开始制作企业网站,建站流程是怎么样的

为了维持你的品牌形象&#xff0c;你必须有一个在线的网站存在&#xff0c;但是创建一个网站需要多长时间呢&#xff1f;从开始到结束&#xff0c;你最期待什么&#xff1f; 我们将介绍网站开发过程的步骤以及每个步骤可能需要多少时间。我们还将探讨您设计和部署网站的选项&a…

手机银行客户端框架之TMF框架介绍

腾讯移动开发平台&#xff08;Tencent Mobile Framework&#xff09;整合了腾讯在移动产品中开发、测试、发布和运营的技术能力&#xff0c;为企业提供一站式、覆盖全生命周期的移动端技术平台。核心服务包括移动客户端开发组件、H5容器、灰度发布、热更新、离线包、网关服务、…

[【JSON2WEB】 13 基于REST2SQL 和 Amis 的 SQL 查询分析器

【JSON2WEB】01 WEB管理信息系统架构设计 【JSON2WEB】02 JSON2WEB初步UI设计 【JSON2WEB】03 go的模板包html/template的使用 【JSON2WEB】04 amis低代码前端框架介绍 【JSON2WEB】05 前端开发三件套 HTML CSS JavaScript 速成 【JSON2WEB】06 JSON2WEB前端框架搭建 【J…

wpf下如何实现超低延迟的RTMP或RTSP播放

技术背景 我们在做Windows平台RTMP和RTSP播放模块对接的时候&#xff0c;有开发者需要在wpf下调用&#xff0c;如果要在wpf下使用&#xff0c;只需要参考C#的对接demo即可&#xff0c;唯一不同的是&#xff0c;视频流数据显示的话&#xff0c;要么通过控件模式&#xff0c;要么…

Python球球大作战

文章目录 写在前面球球大作战程序设计注意事项写在后面 写在前面 安装pygame的命令&#xff1a; pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pygame球球大作战 《球球大作战》是一款简单易上手、充满趣味性和竞技性的休闲手游。游戏的核心玩法可以用一句话概…

李廉洋:4.11黄金原油早盘#行情走势#分析及策略。

美国通胀数据超出预期&#xff0c;抑制了对美联储降息的押注。Coex Partners有限公司宏观经济学家Henrik Gullberg表示&#xff1a;“对新兴市场和风险资产来说&#xff0c;(通胀)高企持续时间更长是个坏消息&#xff0c;还因为它增加了美国和全球经济更明显下滑的风险。CPI数据…

(一)基于IDEA的JAVA基础13

数组遍历 遍历数组就是把数组内的数据一个个的取出来 1.我们可以用for循环&#xff0c;依次把数字类的元素取出来。 2.增强型for循环。 用第一个方法写一下&#xff0c;看一下 public class Test01 { public static void main(String[] args) { //存储一组数据{…

计算机网络 Telnet远程访问交换机和Console终端连接交换机

一、实验要求和内容 1、配置交换机进入特权模式密文密码为“abcd两位班内学号”&#xff0c;远程登陆密码为“123456” 2、验证PC0通过远程登陆到交换机上&#xff0c;看是否可以进去特权模式 二、实验步骤 1、将一台还没配置的新交换机&#xff0c;利用console线连接设备的…

如何在极狐GitLab 使用Docker 仓库功能

本文作者&#xff1a;徐晓伟 GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 本文主要讲述了如何在[极狐GitLab…

Unity 获取RenderTexture像素颜色值

拿来吧你~ &#x1f9aa;功能介绍&#x1f32d;Demo &#x1f9aa;功能介绍 &#x1f4a1;不通过Texture2D 而是通过ComputerShader 提取到RenderTexture的像素值&#xff0c;效率有提升哦&#xff01; &#x1f4a1;通过扩展方法调用&#xff0c;方便快捷&#xff1a;xxxRT.G…

借助 Keras 3 轻松上手 Gemma 模型

作者 / Keras 产品经理 Martin Grner Keras 团队非常高兴地宣布&#xff0c;KerasNLP 集合现已支持 Gemma&#xff01;Gemma 是先进的轻量级开放模型系列&#xff0c;采用了与构建 Gemini 模型相同的研究和技术。借助 Keras 3&#xff0c;Gemma 可以在 JAX、PyTorch 和 TensorF…

【MySQL数据库 | 第二十四篇】Limit语句的性能问题和调优策略

前言&#xff1a; MySQL作为最流行的关系型数据库管理系统之一&#xff0c;被广泛应用于各种规模和类型的应用程序中。其强大的功能和灵活的查询语言使得开发人员能够高效地执行各种数据操作和分析。 然而&#xff0c;在处理大量数据或复杂查询时&#xff0c;一些开发人员可能…

【QT+QGIS跨平台编译】175:【QGIS_App跨平台编译】—【错误处理:未定义的class APP_EXPORT】

点击查看专栏目录 文章目录 一、未定义的class APP_EXPORT二、错误处理 一、未定义的class APP_EXPORT 报错信息&#xff1a; 二、错误处理 第18行增加&#xff1a; #include "qgis_app.h"

【MYSQL锁】透彻地理解MYSQL锁

&#x1f525;作者主页&#xff1a;小林同学的学习笔录 &#x1f525;mysql专栏&#xff1a;小林同学的专栏 目录 1.锁 1.1 概述 1.2 全局锁 1.2.1 语法 1.2.1.1 加全局锁 1.2.1.2 数据备份 1.2.1.3 释放锁 1.2.1.4 特点 1.2.1.5 演示 1.3 表级锁 1.3.1 介绍 …

区块链:开启信任的新时代

区块链是一种基于去中心化、分布式的数据存储、传输、记录和验证的数据库技术。它通过一串使用密码学算法链接起来的区块&#xff0c;形成了一个公开透明、不可篡改的数据记录系统。 区块链技术的核心特点就是去中心化。在传统的中心化系统中&#xff0c;数据存储和记录往往由…

正则表达式 速成

正则表达式的作用 正则表达式&#xff0c;又称规则表达式,&#xff08;Regular Expression&#xff0c;在代码中常简写为regex、regexp或RE&#xff09;&#xff0c;是一种文本模式&#xff0c;包括普通字符&#xff08;例如&#xff0c;a 到 z 之间的字母&#xff09;和特殊字…

蓝桥杯嵌入式速成

蓝桥杯嵌入式速成 cubmx创建工程利用官方提供的LCD代码创建工程&#xff08;15届不能用&#xff09;利用官方提供的LCD代码创建工程&#xff08;15届能用&#xff09;Keil配置头文件注意其他注意 LED闪烁 按键短按长按双击 LCD高亮行高亮字符 RTCADCI2Cuart接收发送 PWMDAC定时…

c++的学习之路:22、多态(1)

摘要 本章主要是说一些多态的开头。 目录 摘要 一、多态的概念 二、多态的定义及实现 2.1、多态的构成条件 2.2、虚函数 2.3、虚函数的重写 2.4、C11 override 和 final 2.5、重载、覆盖(重写)、隐藏(重定义)的对比 三、思维导图 一、多态的概念 多态的概念&#…

ELK 企业级日志分析系统 简单介绍

目录 一 ELK 简介 1&#xff0c; elk 是什么 2&#xff0c;elk 架构图 3&#xff0c;elk 日志处理步骤 二 Elasticsearch 简介 1&#xff0c; Elasticsearch 是什么 2&#xff0c; Elasticsearch 的核心概念 3&#xff0c; Elasticsearch 的原理 三 Logstas…