Android App事件交互Event之模仿京东App实现下拉刷新功能(附源码 可直接使用)

news2025/7/23 15:25:50

运行有问题或需要源码请点赞关注收藏后评论区留言~~~

一、正常下拉与下拉刷新的冲突处理

电商App的首页通常都支持下拉刷新,比如京东首页的头部轮播图一直顶到系统的状态栏,并且页面下拉到顶后,继续下拉会拉出带有下拉刷新字样的布局,此时松手会触发页面的刷新动作,虽然Android提供了专门的下拉刷新布局SwipeRefreshLayout,但是它没有实现页面随手势下滚的动态效果,所以只能我们自己编写一个自定义的布局控件。

自定义的下拉刷新布局首先要能够区分是页面的正常下滚还是拉到头部要求刷新,二者之间的区别很简单,直观上就是判断当前页面是否拉到顶,倘若还没拉到顶,继续下拉动作属于正常的页面滚动,倘若已经拉到顶,继续下拉动作才会拉出头部提示刷新,所以此处需要捕捉页面滚动到顶部的事件,相对应的是页面滚动到底部的事件。鉴于App首页基本采用滚动视图实现页面滚动功能

对于下面几种情况要统筹管理

1:水平方向的左右滑动 不做额外处理

2:垂直方向的向上拉动 不做额外处理

3:下拉的时候尚未拉到页面顶部 不做额外处理

4:拉动顶之后继续下拉,则在隐藏工具栏的同时让下拉头部跟着往下滑动

5:下拉刷新过程中松开手势 判断下拉滚动的距离,距离太短则直接缩回头部,不刷新页面,只有距离足够长才会刷新页面,等待刷新完毕再缩回头部

实现效果如下

一直向上拉到顶就会自动刷新

 

 

 

 代码如下

Java类

package com.example.event;

import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import androidx.appcompat.app.AppCompatActivity;

import android.os.Looper;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.example.event.constant.ImageList;
import com.example.event.util.StatusBarUtil;
import com.example.event.util.Utils;
import com.example.event.widget.BannerPager;
import com.example.event.widget.PullDownRefreshLayout;

@SuppressLint("DefaultLocale")
public class PullRefreshActivity extends AppCompatActivity implements PullDownRefreshLayout.PullRefreshListener {
    private static final String TAG = "PullRefreshActivity";
    private PullDownRefreshLayout pdrl_main; // 声明一个下拉刷新布局对象
    private TextView tv_flipper; // 声明一个文本视图对象
    private LinearLayout ll_title; // 声明一个线性布局对象
    private ImageView iv_scan; // 声明一个图像视图对象
    private ImageView iv_msg; // 声明一个图像视图对象
    private boolean isDragging = false; // 是否正在拖动
    private ProgressDialog mDialog; // 声明一个进度对话框对象

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pull_refresh);
        pdrl_main = findViewById(R.id.pdrl_main);
        pdrl_main.setOnRefreshListener(this); // 设置下拉刷新监听器
        tv_flipper = findViewById(R.id.tv_flipper);
        ll_title = findViewById(R.id.ll_title);
        iv_scan = findViewById(R.id.iv_scan);
        iv_msg = findViewById(R.id.iv_msg);
        BannerPager banner = findViewById(R.id.banner_pager);
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) banner.getLayoutParams();
        params.height = (int) (Utils.getScreenWidth(this) * 250f / 640f);
        banner.setLayoutParams(params); // 设置广告轮播条的布局参数
        banner.setImage(ImageList.getDefault()); // 设置广告轮播条的图片列表
        // 设置广告轮播条的图片点击监听器
        banner.setOnBannerListener(position -> {
            String desc = String.format("您点击了第%d张图片", position + 1);
            tv_flipper.setText(desc);
        });
        floatStatusBar(); // 添加悬浮状态栏效果
    }

    private void floatStatusBar() {
        // 让App页面扩展到状态栏区域
        StatusBarUtil.fullScreen(this);
        RelativeLayout.LayoutParams titleParams = (RelativeLayout.LayoutParams) ll_title.getLayoutParams();
        // 标题栏在上方留出一段距离,看起来仍在状态栏下方
        titleParams.topMargin = StatusBarUtil.getStatusBarHeight(this);
        ll_title.setLayoutParams(titleParams);
    }

    // 开始页面刷新
    private void beginRefresh() {
        if (mDialog == null || !mDialog.isShowing()) {
            // 显示进度对话框
            mDialog = ProgressDialog.show(this, "请稍等", "正在努力刷新页面");
            // 延迟1秒后启动刷新结束任务
            new Handler(Looper.myLooper()).postDelayed(() -> endRefresh(), 1000);
        }
    }

    // 结束页面刷新
    private void endRefresh() {
        if (isDragging) {
            mDialog.dismiss(); // 关闭进度对话框
            pdrl_main.finishRefresh();
            isDragging = false;
        }
    }

    // 计算标题栏与状态栏的渐变背景色
    private int getTitleBgColor(double scale) {
        int alpha = (int) Math.round(scale / 2 * 255);
        alpha = Math.min(alpha, 255);
        return Color.argb(alpha, 255, 255, 255);
    }

    // 在下拉刷新时触发
    @Override
    public void pullRefresh() {
        isDragging = true;
        beginRefresh(); // 开始页面刷新
    }

    // 在往上拉动时触发
    @Override
    public void pullUp(double scale) {
        int bgColor = getTitleBgColor(scale);
        ll_title.setBackgroundColor(bgColor);
        ll_title.setVisibility(View.VISIBLE);
        iv_scan.setImageResource(R.drawable.icon_scan_gray);
        iv_msg.setImageResource(R.drawable.icon_msg_gray);
        // 上拉页面,让状态栏背景渐渐变为白色
        StatusBarUtil.setStatusBarColor(this, bgColor, true);
    }

    // 在往下拉动时触发
    @Override
    public void pullDown(double scale) {
        int bgColor = getTitleBgColor(scale);
        ll_title.setBackgroundColor(bgColor);
        ll_title.setVisibility(View.VISIBLE);
        iv_scan.setImageResource(R.drawable.icon_scan_white);
        iv_msg.setImageResource(R.drawable.icon_msg_white);
        // 下拉到顶了,让状态栏背景渐渐变为透明
        StatusBarUtil.setStatusBarColor(this, bgColor, false);
    }

    @Override
    public void hideTitle() {
        ll_title.setVisibility(View.INVISIBLE);
    }

    @Override
    public void showTitle() {
        ll_title.setVisibility(View.VISIBLE);
    }

}

XML文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white">

    <com.example.event.widget.PullDownRefreshLayout
        android:id="@+id/pdrl_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <com.example.event.widget.PullDownScrollView
            android:id="@+id/pdsv_main"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <com.example.event.widget.BannerPager
                    android:id="@+id/banner_pager"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />

                <TextView
                    android:id="@+id/tv_flipper"
                    android:layout_width="match_parent"
                    android:layout_height="300dp"
                    android:background="#eeffee"
                    android:gravity="top|center_horizontal"
                    android:paddingTop="10dp"
                    android:text="请反复下拉页面和上拉页面"
                    android:textColor="@color/black"
                    android:textSize="17sp" />

                <View
                    android:layout_width="match_parent"
                    android:layout_height="1000dp"
                    android:background="#9999ff" />

                <View
                    android:layout_width="match_parent"
                    android:layout_height="10dp"
                    android:background="@color/white" />
            </LinearLayout>
        </com.example.event.widget.PullDownScrollView>
    </com.example.event.widget.PullDownRefreshLayout>

    <!-- title_drag.xml是带搜索框的工具栏布局 -->
    <include layout="@layout/title_drag" />

</RelativeLayout>

创作不易 觉得有帮助请点赞关注收藏~~~

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

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

相关文章

leaflet教程039: 只显示一屏地图,设定范围不让循环延展

第039个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet只显示一屏地图,并且根据maxBounds和bounds的设定,来改变不同的地图呈现状态。 直接复制下面的 vue+leaflet源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源代码(共68行)心得总结相…

[附源码]java毕业设计期刊在线投稿平台

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

小程序基础原理

前言 本文会围绕小程序的基础原理进行介绍。主要包括小程序的基础结构、编译、加载、通讯等几个方面。旨在阅读完毕后可以对小程序有一个基本的印象。 一、基础 对于用户来讲&#xff0c;小程序无需下载、用完即走、体验良好。 对于开发者来讲&#xff0c;小程序主要是区别…

同花顺_代码解析_技术指标_M

本文通过对同花顺中现成代码进行解析&#xff0c;用以了解同花顺相关策略设计的思想 目录 MACD MACDFS MARSI MASS MAVOL MCL MCO MFI MI MICD MIKE MTM MTMFS MACD 指数平滑异同平均线 MACD指标说明 MACD指数平滑异同移动平均线为两条长、短的平滑平均线。 其…

拉取多CPU架构容器镜像推送到其他仓库

一、背景 一个docker镜像可能会有多种CPU架构的变体&#xff0c;有时需要把这些多架构的镜像全部从公共镜像库&#xff08;如&#xff1a; hub.docker.com &#xff09;同步到自建的库上。 二、解决方法 使用 docker buildx 多架构打包机制&#xff0c;进行重制推送&#xf…

Bean 作用域和生命周期

一 : Bean的默认作用域 Bean 默认情况下是单例状态(singleton),所有人使用的都是同一个对象.举例理解Bean的单例状态 : 假设现在有一个公共的 Bean&#xff0c;提供给 A 用户和 B 用户使用&#xff0c;然而在使用的途中 A 用户却“悄悄”地修 改了公共 Bean 的数据&#xff0…

[附源码]SSM计算机毕业设计中医药系统论文2022JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

快速清除PPT缓存文件或C盘隐藏大文件

是否遇到过电脑的磁盘空间越来越满&#xff0c; 请注意这些临时文件可谓是C盘的存储杀手&#xff0c;无形中吞噬掉很多磁盘空间&#xff0c;这里以PPT为例&#xff1a; C:\Users\Admin\AppData\Roaming\Microsoft\PowerPoint\ 1.首先在PPT2019软件中&#xff0c;打开一个PPT文…

实现BIO多客户端通讯模式

实现BIO多客户端通讯模式背景思想实现服务端线程类服务端客户端结果背景 如果服务端需要处理很多个客户端的消息通信请求应该如何处理呢&#xff0c;此时我们就需要在服务端引入线程了&#xff0c;也就是说客户端每发起一个请求&#xff0c;服务端就创建一个新的线程来处理这个…

PyTorch搭建基于图神经网络(GCN)的天气推荐系统(附源码和数据集)

需要源码和数据集请点赞关注收藏后评论区留言~~~ 一、背景 极端天气情况一直困扰着人们的工作和生活。部分企业或者工种对极端天气的要求不同&#xff0c;但是目前主流的天气推荐系统是直接将天气信息推送给全部用户。这意味着重要的天气信息在用户手上得不到筛选&#xff0c;…

(C语言)背答案

[#4练习赛]背答案 题目描述 传智专修学院“Java程序设计”的期末考试来源于一个选择库&#xff0c;共有 nnn 道题目&#xff0c;每道题目由问题和答案组成&#xff0c;都是一个字符串&#xff0c;保证所有题目题面互不相同。这个题库已经发给同学进行备考准备。 正式考试中&…

Labview+STM32无线温湿度采集

一.介绍 该项目采用正点原子的STM32ZET6精英板DHT11温湿度模块泽耀科技的无线串口作为下位机&#xff0c;Labview无线串口作为上位机读取下位机发来的数据并处理。 泽耀科技的产品是我在开发过程中经常用到的&#xff0c;他们不仅产品做的非常不错&#xff0c;而且资料齐全售后…

远离cmd,拥抱powershell

简介&#xff1a;cmd命令提示符是在操作系统中&#xff0c;提示进行命令输入的一种工作提示符。在不同的操作系统环境下&#xff0c;命令提示符各不相同。 在windows环境下&#xff0c;命令行程序为cmd.exe&#xff0c;是一个32位的命令行程序&#xff0c;微软Windows系统基于W…

动态规划--区间dp

区间dp题目列表&#xff1a;(1)石子合并(2)环形石子合并(3)能量项链(4)加分二叉树(5)凸多边形的划分(6)棋盘分割题目列表&#xff1a; (1)石子合并 在复习石子合并之前&#xff0c;为了直接进入专题“区间dp“&#xff0c;做一个区间dp的基础题&#xff0c;这个题目具有代表性…

1.2 Android 5.0 的特点

和其他版本相比&#xff0c; Android 5.0 的突出特性如下所示。 &#xff08;1&#xff09;全新的 Material 界面设计 Android 5.0 Lollipop 界面设计的灵感来源于自然、 物理学 以及基于打印效果的粗体、图标化的设计&#xff0c;换句话说&#xff0c;它的设 计是一种基于高品…

智慧建筑BIM解决方案-最新全套文件

智慧建筑BIM解决方案-最新全套文件一、建设背景为什么要发展智慧建筑二、思路架构三、建设方案智慧建筑建设时应考虑下面3个方面&#xff1a;1、减少耗能&#xff0c;促进资源利用效率2、优化工作和生活环境3、确保运营安全可靠四、获取 - 智慧建筑BIM全套最新解决方案合集一、…

m超外差单边带接收机的simulink仿真

目录 1.算法概述 2.仿真效果预览 3.MATLAB部分代码预览 4.完整MATLAB程序 1.算法概述 超外差是利用本地产生的振荡波与输入信号混频&#xff0c;将输入信号频率变换为某个预先确定的频率的方法。这种方法是为了适应远程通信对高频率、弱信号接收的需要&#xff0c;在外差原…

基于springboot在线玩具商城交易平台的设计与实现

随着科技创新不断突破玩具界限&#xff0c;特别是随着智能时代到来&#xff0c;电子游戏的兴起对传统玩具行业带来了冲击&#xff0c;智能玩具应运而生&#xff0c;成为新产品方向。智能玩具受消费者青睐&#xff0c; 随着电子商务的发展&#xff0c;其在我国的经济地位越来越…

spring boot酒店会员点餐系统毕业设计源码072005

Springboot酒店会员点餐系统 摘 要 进入21世纪以来&#xff0c;计算机有了迅速的发展。计算机应用、信息技术全面渗透到了人类社会的各个方面&#xff0c;信息化已成为世界经济和社会发展的大趋势。―企业的管理也从人工操作变得更加自动化、智能化和高效化。如果复杂的工作光靠…

PMP大家都是怎么备考的?使用什么工具可以分享一下吗?

这里分享PMP理论中的4个工具&#xff0c;在人生管理和项目管理中是通用的。所有的工具&#xff0c;只有在对的时间&#xff0c;用在对的地方&#xff0c;才能真正指导实践。 项目经理应符合PMI人才三角。分别为&#xff1a;技术项目管理&#xff1b;领导力&#xff1b;战略和…