android之listview悬浮topBar效果
作者:小钟视野 发布时间:2022-12-24 23:29:58
虽然listview是过去式,但由于项目中还是有用listview,百度一番都是scrollview中的悬浮bar,没有看到有listview的悬浮bar,所以自己写一个悬浮bar;参照夏大神的scrollview的悬浮demo
效果如下:
自定义的Listview和scrollView没什么区别都是重写onScrollChange()然后在里边调用自己实现的接口,是对外提供的接口吧,这里没有封装,需要的可以自己将其封装,然后在自己项目中使用。
重点的方法:
onScrollChanged()方法:是在ListView和ScrollView在滚动时会回调的方法并且能获取到当前最新的top left和上一次的top 和left
getViewTreeObservew().addOnGlobalLayoutLister():这是View都有的方法,可以监控改view的变化(如显示、隐藏)都会回调以及在view被绘制时会被回调。
思路如下:
一、可以使用getViewTreeObservew().addOnGlobalLayoutLister():方法在第一次进入到这个页面后将悬浮的bar与目标view绘制重合。防止显示隐藏会有一闪的情况
二、在onScrollChaged()方法中回调自定义的接口onScrollListener的方法onScroll()在这里通过layout()方法不断重新绘制悬浮bar的位置。
基本就如此
package com.example.zwr.listviewfloatbardemo;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
/**
* @author zhongwr
*/
public class MainActivity extends Activity implements FloatListView.OnScrollListener {
protected static final String TAG = "FloatListView";
/**
* 自定义的listview
*/
private FloatListView lvFloat;
/**
* listview中的headView中要悬浮的view
*/
private LinearLayout mFloatTargetLayout;
/**
* 悬浮的view,跟headView的要一致
*/
private LinearLayout mFloatTopLayout;
private View head;
@SuppressWarnings("deprecation")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lvFloat = (FloatListView) findViewById(R.id.scrollView);
head = getLayoutInflater().inflate(R.layout.buy_layout_head, null);
lvFloat.addHeaderView(head);
mFloatTargetLayout = (LinearLayout) findViewById(R.id.buy);
mFloatTopLayout = (LinearLayout) findViewById(R.id.top_buy_layout);
lvFloat.setOnScrollListener(this);
// 当布局的状态或者控件的可见性发生改变回调的接口:当布局都绘制好后会执行一次
findViewById(R.id.parent_layout).getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// 这一步很重要,一开始让目标悬浮的view和要悬浮的view重合一起,之后悬浮view跟随一起目标view一起移动
onScroll(lvFloat.getScrollY());
}
});
lvFloat.setAdapter(new DataListAdapter(this));
}
@Override
public void onScroll(int scrollY) {
// SrcollView和这个Listview不同之处:scrolly是scrollview.getTop(),parent的坐标没变,只是手指向上滚动时就是scrollview滚出屏幕,但是top还是距离parent的距离,所以那里用max取最大值
//listview手指向上滑动屏幕时会导致headRoot的top为负值,因为head是滚出屏幕的head部分并不是listview中item重用机制
int headTop = head.getTop();
if (headTop <= 0 && Math.abs(headTop) <= mFloatTargetLayout.getTop() && scrollY >= 0) {//手指向上滑动屏幕
mFloatTopLayout.layout(0, mFloatTargetLayout.getTop() + headTop, mFloatTopLayout.getWidth(),
mFloatTargetLayout.getTop() + headTop + mFloatTopLayout.getHeight());
} else if (headTop == 0) {//当手指从上往下滑动屏幕到达最顶端时,但还有一段可滑行的距离放手后又回到起始位置,跟系统有关
//此时这个listview的Top是负值所以要减去-scrolly:注这个scrollY=listview.getTop();让悬浮的Title跟随实际的title一起浮动
mFloatTopLayout.layout(0, mFloatTargetLayout.getTop() - scrollY, mFloatTopLayout.getWidth(),
mFloatTargetLayout.getTop() - scrollY + mFloatTopLayout.getHeight());
} else if (headTop < 0) {//由于手指向上滑动屏幕的很快会导致title悬浮不到顶部,所以要强制其在顶部
mFloatTopLayout.layout(0, 0, mFloatTopLayout.getWidth(),
mFloatTopLayout.getHeight());
}
//这种方式会导致闪跳的现象,可以通过动画来实现
}
}
主要是onScroll()方法的逻辑:
可以看看夏大神的实现
public void onScroll(int scrollY) {
int mBuyLayout2ParentTop = Math.max(scrollY, mBuyLayout.getTop());
mTopBuyLayout.layout(0, mBuyLayout2ParentTop, mTopBuyLayout.getWidth(), mBuyLayout2ParentTop + mTopBuyLayout.getHeight());
}
他这里是直接使用scrollY(其实是scrollview的最新top值)和目标view的top值去最大,因为ScrollView是滑出屏幕的,但是其parent的位置没变,所以scrollview的top会越来越大而且是正值。所以可以通过这种方式来绘制悬浮的bar。
但是Listview的机制不一样,滑动出屏幕时item由于是重用机制,所以listView中的top并没有改变;巧的是head的机制有点像Scrollview滑出的机制,但是又不一样得到的head的top值是负值,猜测相对坐标由于listView这个父布局没动但是head已经滑出屏幕所以是负值。根据这个值处理我们想要的结果,剩下的onScroll()方法的注释写的很清楚了。
自定义的listView代码如下
package com.example.zwr.listviewfloatbardemo;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ListView;
/**
*
* @author zhongwr
*
*/
public class FloatListView extends ListView {
private static final String TAG = "FloatListView";
private OnScrollListener onScrollListener;
public FloatListView(Context context) {
this(context, null);
}
public FloatListView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public FloatListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* 设置滚动接口
* @param onScrollListener
*/
public void setOnScrollListener(OnScrollListener onScrollListener) {
this.onScrollListener = onScrollListener;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// Log.d(TAG, "w = "+w);
// Log.d(TAG, "h = "+h);
super.onSizeChanged(w, h, oldw, oldh);
}
/**
* 滚动时会执行
* @param l 新的getLeft
* @param t 新的getTop
* @param oldl
* @param oldt
*/
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
// Log.d(TAG, "onScrollChanged l = " + l + " t = " + t);
// Log.d(TAG, "onScrollChanged oldl = " + oldl + " oldt = " + oldt);
if (onScrollListener != null) {
onScrollListener.onScroll(t);
}
}
/**
*
* 滚动的回调接口
*
* @author xiaanming
*
*/
public interface OnScrollListener{
/**
* 回调方法, 返回MyScrollView滑动的Y方向距离
* @param scrollY
* 、
*/
public void onScroll(int scrollY);
}
}
没什么逻辑,就是重写了onSizeChaged()方法,然后在里边写了调用接口的回调。
就是这么简单!!
demo如下:listview悬浮topBar
猜你喜欢
- 这是一个介绍基本异常处理的小例子,包括抛出,捕获,断言,日志。Java异常处理通过5个关键字try、catch、throw、throws、f
- 先创建一个CacheHelper.cs类,代码如下:using System;using System.Web;using System.C
- 性能测试过程中,如果进行大量的并发时,界面容易卡死。通过非GUI(命令行)的方式是个不错的选择。windows环境1.在安装Jmeter的目
- 简介:在团队协作开发的过程中,好的代码管理能更加有效的使日常开发的过程中对各个开发人员提高开发速度。下面将详细介绍在IDEA中使用git提交
- 1. 前言Spring最重要的一个概念当属Bean了,我们写的Controller、Service、Dao凡是加了对应注解交给Spring管
- 一、SpringCache介绍Spring Cache 是一个优秀的缓存组件。自Spring 3.1起,提供了类似于@Transaction
- Spring * 监测每个Controller或方法的执行时长首先写一个类(TestInterceptor)让他继承HandlerInter
- SpringMVC文件上传中要解决的问题一、中文文件名编码问题通过过滤器解决二、文件位置存储问题放在当前项目下,作为静态资源,这样可以通过U
- 本文实例讲述了C#实现彻底删除文件的方法。分享给大家供大家参考。具体实现方法如下:经常用360的文件粉碎,删除隐私文件貌似还不错的。不过C#
- 引言RecyclerView是在Android5.0版本作为support-v7的一个组件出现,高效替代了最初的ListView等列表组件。
- 1. 问题所示编译ssm的项目的时候出现了这个错误导致一直运行不起来SLF4J: Failed to load class "or
- 最近研究C#相关的ORC技术,图像识别一般C和C++这种底层语言做的比较多,C#主要是依托一些封装好的组件进行调用,这里介绍三种身份证识别的
- 本文分享了c#操作Excel的相关代码,还是比较全面的,其实无外乎存取,增删改查等操作,参考下。具体代码://引用Microsoft.Off
- 在国际化环境下,越来越多的程序需要做多语言版本,以适应各种业务需求的变化。在Winform应用程序中实现多语言也有常规的处理方式处理,不过需
- java String的深入理解一、Java内存模型 按照官方的说法:Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和
- 前言最近做一个微信公众号服务,有一些简单的图片处理功能。主要就是用户在页面操作,前端做一些立刻显示的效果,然后提交保存时后端真正修改原图。从
- 前置知识在微服务项目中,如果我们想实现服务间调用,一般会选择Feign。之前介绍过一款HTTP客户端工具Retrofit,配合SpringB
- 背景在Spring boot项目开发中经常遇到需要使用枚举的场景,比如描述状态、性别、类型等相关字段。通常这些字段在数据库会以tinyint
- 目录概述基本使用1. 在低层 module_common 中声明服务2. 在上层 module 中实现服务3. 在其它上层 module 中
- java可以通过Runtime.getRuntime().exec()执行一个操作系统的命令,在操作系统层面执行命令也就创建了一个进程,Ja