android之listview悬浮topBar效果

作者:小钟视野 时间:2022-12-24 23:29:58 

虽然listview是过去式,但由于项目中还是有用listview,百度一番都是scrollview中的悬浮bar,没有看到有listview的悬浮bar,所以自己写一个悬浮bar;参照夏大神的scrollview的悬浮demo

效果如下:

android之listview悬浮topBar效果

自定义的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

标签:android,listview,悬浮,topBar
0
投稿

猜你喜欢

  • WPF+DiffPlex实现文本比对工具

    2022-04-20 21:32:07
  • springboot 定时任务@Scheduled实现解析

    2023-11-10 16:18:24
  • springboot自定义stater启动流程

    2023-06-07 06:33:45
  • C#实现常见加密算法的示例代码

    2023-05-08 12:44:43
  • Android Studio快捷键生成TAG、Log.x日志输出介绍

    2022-03-14 02:10:37
  • SpringBoot+WebSocket实现即时通讯的方法详解

    2021-07-24 15:48:49
  • C/C++ Qt TreeWidget 嵌套节点操作使用

    2022-07-10 01:55:59
  • C#利用TreeView控件实现目录跳转

    2021-07-26 02:57:50
  • Intellij Idea修改代码方法参数自动提示快捷键的操作

    2022-11-19 08:08:37
  • 在Spring Boot中从类路径加载文件的示例

    2023-11-11 21:53:44
  • springboot访问静态资源遇到的坑及解决

    2022-11-06 14:45:11
  • SpringBoot 将配置文件挂到 jar 包外面的操作方法

    2023-11-17 11:09:32
  • 详解Spring Boot自动装配的方法步骤

    2023-11-18 15:02:18
  • maven profile实现多环境配置的示例

    2023-09-24 12:02:57
  • android全局监控click事件的四种方式(小结)

    2023-05-02 07:33:31
  • C# 如何调用C++ dll string类型返回

    2023-01-31 02:27:55
  • SpringBoot中并发定时任务的实现、动态定时任务的实现(看这一篇就够了)推荐

    2023-01-21 13:58:45
  • C#调用dll报错:无法加载dll,找不到指定模块的解决

    2023-08-23 23:36:12
  • Java创建与结束线程代码示例

    2023-01-16 16:20:00
  • java利用url实现网页内容的抓取

    2023-05-14 11:10:21
  • asp之家 软件编程 m.aspxhome.com