热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

android之listview悬浮topBar效果

这篇文章主要为大家详细介绍了android之listview悬浮topBar效果的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

虽然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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • PHP 编程疑难解析与知识点汇总
    本文详细解答了 PHP 编程中的常见问题,并提供了丰富的代码示例和解决方案,帮助开发者更好地理解和应用 PHP 知识。 ... [详细]
  • 深入理解 Oracle 存储函数:计算员工年收入
    本文介绍如何使用 Oracle 存储函数查询特定员工的年收入。我们将详细解释存储函数的创建过程,并提供完整的代码示例。 ... [详细]
  • 在计算机技术的学习道路上,51CTO学院以其专业性和专注度给我留下了深刻印象。从2012年接触计算机到2014年开始系统学习网络技术和安全领域,51CTO学院始终是我信赖的学习平台。 ... [详细]
  • CSS 布局:液态三栏混合宽度布局
    本文介绍了如何使用 CSS 实现液态的三栏布局,其中各栏具有不同的宽度设置。通过调整容器和内容区域的属性,可以实现灵活且响应式的网页设计。 ... [详细]
  • Linux 系统启动故障排除指南:MBR 和 GRUB 问题
    本文详细介绍了 Linux 系统启动过程中常见的 MBR 扇区和 GRUB 引导程序故障及其解决方案,涵盖从备份、模拟故障到恢复的具体步骤。 ... [详细]
  • 本文介绍了如何使用jQuery根据元素的类型(如复选框)和标签名(如段落)来获取DOM对象。这有助于更高效地操作网页中的特定元素。 ... [详细]
  • 本文将详细介绍如何使用剪映应用中的镜像功能,帮助用户轻松实现视频的镜像效果。通过简单的步骤,您可以快速掌握这一实用技巧。 ... [详细]
  • 本文介绍如何在 Xcode 中使用快捷键和菜单命令对多行代码进行缩进,包括右缩进和左缩进的具体操作方法。 ... [详细]
  • 本文介绍了一款用于自动化部署 Linux 服务的 Bash 脚本。该脚本不仅涵盖了基本的文件复制和目录创建,还处理了系统服务的配置和启动,确保在多种 Linux 发行版上都能顺利运行。 ... [详细]
  • 在Linux系统中配置并启动ActiveMQ
    本文详细介绍了如何在Linux环境中安装和配置ActiveMQ,包括端口开放及防火墙设置。通过本文,您可以掌握完整的ActiveMQ部署流程,确保其在网络环境中正常运行。 ... [详细]
  • Android 渐变圆环加载控件实现
    本文介绍了如何在 Android 中创建一个自定义的渐变圆环加载控件,该控件已在多个知名应用中使用。我们将详细探讨其工作原理和实现方法。 ... [详细]
  • 如何在WPS Office for Mac中调整Word文档的文字排列方向
    本文将详细介绍如何使用最新版WPS Office for Mac调整Word文档中的文字排列方向。通过这些步骤,用户可以轻松更改文本的水平或垂直排列方式,以满足不同的排版需求。 ... [详细]
  • 本文总结了在使用Ionic 5进行Android平台APK打包时遇到的问题,特别是针对QRScanner插件的改造。通过详细分析和提供具体的解决方法,帮助开发者顺利打包并优化应用性能。 ... [详细]
  • 理解存储器的层次结构有助于程序员优化程序性能,通过合理安排数据在不同层级的存储位置,提升CPU的数据访问速度。本文详细探讨了静态随机访问存储器(SRAM)和动态随机访问存储器(DRAM)的工作原理及其应用场景,并介绍了存储器模块中的数据存取过程及局部性原理。 ... [详细]
author-avatar
ririye2011
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有