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

本文实例为大家分享了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.mzph.cn/news/806469.shtml

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

相关文章

HTML5学习记录

简介 超文本标记语言&#xff08;HyperText Markup Language&#xff0c;简称HTML&#xff09;&#xff0c;是一种用于创建网页的标准标记语言。 编辑器 下载传送门https://code.visualstudio.com/ 下载编辑器插件 标题 标题通过 <h1> - <h6> 标签进行定义。 …

科技助力输电线安全隐患预警,基于YOLOv5全系列参数【n/s/m/l/x】模型开发构建电力设备场景下输电线安全隐患目标检测预警系统

电力的普及让我们的生活变得更加便利&#xff0c;四通八达的电网连接着生活的方方面面&#xff0c;电力能源主要是依托于庞大复杂的电网电力设备进行传输的&#xff0c;有效地保障电网场景下输电线的安全对于保障我们日常生活所需要的电力有着重要的意义&#xff0c;但是电力设…

【Web开发】jquery图片放大镜效果制作变焦镜头图片放大

jquery图片放大镜效果制作变焦镜头图片放大实现 整体步骤流程&#xff1a; 1. 前端html实现 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"…

【测试开发学习历程】python面向对象

1 面向对象的基本概念 面向对象&#xff1a;是把构成问题事务分解成各个对象&#xff0c;建立对象的目的不是为了完成一个步骤&#xff0c;而是为了描叙某个事物在整个解决问题的步骤中的行为。 怎么理解面向对象&#xff1f; 面向对象是一种编程思想&#xff0c;就是把要解决…

ruoyi-nbcio-plus基于vue3的flowable的自定义业务提交申请组件的升级修改

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 http://122.227.135.243:9666/ 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a…

NAV2 ros galactic安装教程

sudo apt install ros-galactic-gazebo-* 这个必须下载 sudo apt-get install -y ros-galactic-rmw* 这个也是 使用操作系统中的包管理器安装 Nav2 包: sudo apt install ros-galactic-navigation2 sudo apt install ros-galactic-nav2-bringup安装Turtlebot 3 软件包: sudo…

Java快速入门系列-8(Web开发基础)

第8章 Web开发基础 8.1 Servlet与JSP8.1.1 Servlet简介8.1.2 JSP简介与使用8.1.3 Servlet与JSP协作8.2 Web服务器与Tomcat8.2.1 安装与配置Tomcat8.2.2 配置与管理Web应用8.3 MVC设计模式与Java Web应用8.3.1 MVC原理8.3.2 MVC在Java Web中的应用8.4 RESTful API设计与实现8.4.…

参数化方案对耦合模式影响试验

今天建立几个实验 HIST_model_test_lthf_tbf HIST_model_test_lthf_phiq HIST_model_test_sshf_tbf HIST_model_test_pblh_zli HIST_model_test_nocouple 十天过去了&#xff0c;这次运行的速度显然慢了好多&#xff0c;还没运行到2000年&#xff0c;没办法只能就地取材了。 我…

虚拟货币:数字金融时代的新工具

在数字化时代的到来之后&#xff0c;虚拟货币逐渐成为了一种广为人知的金融工具。虚拟货币是一种数字化的资产&#xff0c;它不像传统货币那样由政府或中央银行发行和监管。相反&#xff0c;虚拟货币通过密码学技术和分布式账本技术来实现去中心化的发行和交易。 虚拟货币的代…

xss跨站脚本攻击笔记

1 XSS跨站脚本攻击 1.1 xss跨站脚本攻击介绍 跨站脚本攻击英文全称为(Cross site Script)缩写为CSS&#xff0c;但是为了和层叠样式表(CascadingStyle Sheet)CSS区分开来&#xff0c;所以在安全领域跨站脚本攻击叫做XSS 1.2 xss跨战脚本攻击分类 第一种类型:反射型XSS 反射…

JVM规范中的运行时数据区

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a;每天一个知识点 ✨特色专栏&#xff1a…

Qt 多窗体

前言 在 Qt编程中经常会遇到要在多个界面之间切换的情况&#xff0c;如从登录界面跳转到主界面&#xff0c;从主界面跳转到设置界面&#xff0c;再返回到主界面。我们将会用一个简单的示例来实现多窗体功能。 登录窗口 创建基类为QMainWindow&#xff0c;类名为LoginWin。再使用…

SpringBoot中的Redis的简单使用

在Spring Boot项目中使用Redis作为缓存、会话存储或分布式锁等组件&#xff0c;可以简化开发流程并充分利用Redis的高性能特性。以下是使用Spring Boot整合Redis的详细步骤&#xff1a; 1. 环境准备 确保开发环境中已安装&#xff1a; Java&#xff1a;用于编写和运行Spring…

图书馆自习室|基于SSM的图书馆自习室座位预约小程序设计与实现(源码+数据库+文档)

图书馆自习室目录 基于SSM的图书馆自习室座位预约小程序设计与实现 一、前言 二、系统设计 三、系统功能设计 1、小程序端&#xff1a; 2、后台 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a…

MacOS下Qt 5开发环境安装与配置

最近笔者在MacOS中使用Qt Creator开发Qt程序时遇到了一些问题&#xff0c;在网上查了不少资料&#xff0c;都没有找到解决方案&#xff0c;只有自己进行研究摸索了&#xff0c;今天晚上终于将目前遇到的问题全部解决了&#xff0c;特记录下来分享给大家。 笔者使用的是MacOS 1…

【高校科研前沿】青藏高原所李新研究员为第一作者在REV GEOPHYS发表长篇综述:陆面数据同化–陆面过程研究中理论与数据的和弦

1.文章简介 论文名称&#xff1a;Land Data Assimilation: Harmoni-zing Theory and Data in Land Surface Process Studies 第一作者及通讯作者&#xff1a;李新研究员&#xff08;兼通讯作者&#xff09; 第一作者及通讯作者单位&#xff1a;中国科学院青藏高原研…

网站SEO关键词规划时如何筛选出合适的关键词?

在网站SEO优化过程中&#xff0c;关键词布局是一个至关重要的环节。首先&#xff0c;我们需要确定核心关键词&#xff0c;然后通过各种策略和方法对关键词进行扩展。完成关键词扩展后&#xff0c;接下来的任务就是对这些扩展后的关键词进行筛选。那么&#xff0c;如何进行有效的…

模型训练基本概念-赛博炼丹

文章目录 拓展知识基础名词解释&#xff08;语义库更新&#xff09;机器学习任务流程模型训练基本流程模型训练详细流程正向传播与反向传播正向传播-求误差值反向传播-求参数值 学习率激活函数激活函数-为什么希望激活函数输出均值为0&#xff1f;激活函数 — softmax & ta…

机器学习和深度学习-- 李宏毅(笔记与个人理解)Day10

Day 10 Genaral GUidance training Loss 不够的case Loss on Testing data over fitting 为什么over fitting 留到下下周哦~~ 期待 solve CNN卷积神经网络 Bias-Conplexiy Trade off cross Validation how to split? N-fold Cross Validation mismatch 这节课总体听下来比较…