android listview优化_android之listview悬浮topBar效果

时间:2021-07-01  来源:  阅读:

虽然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的位置。

基本就如此

 

 代码如下

packagecom.example.zwr.listviewfloatbardemo;

 

importandroid.app.Activity;

importandroid.os.Bundle;

importandroid.util.Log;

importandroid.view.View;

importandroid.view.ViewTreeObserver.OnGlobalLayoutListener;

importandroid.widget.ImageView;

importandroid.widget.LinearLayout;

 

 

/**

 * @author zhongwr

 */

publicclassMainActivityextendsActivityimplementsFloatListView.OnScrollListener {

  protectedstaticfinalString TAG ="FloatListView";

  /**

   * 自定义的listview

   */

  privateFloatListView lvFloat;

  /**

   * listview中的headView中要悬浮的view

   */

  privateLinearLayout mFloatTargetLayout;

  /**

   * 悬浮的view,跟headView的要一致

   */

  privateLinearLayout mFloatTopLayout;

  privateView head;

 

  @SuppressWarnings("deprecation")

  @Override

  protectedvoidonCreate(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(newOnGlobalLayoutListener() {

 

      @Override

      publicvoidonGlobalLayout() {

        // 这一步很重要,一开始让目标悬浮的view和要悬浮的view重合一起,之后悬浮view跟随一起目标view一起移动

        onScroll(lvFloat.getScrollY());

      }

    });

    lvFloat.setAdapter(newDataListAdapter(this));

  }

 

  @Override

  publicvoidonScroll(intscrollY) {

    //   SrcollView和这个Listview不同之处:scrolly是scrollview.getTop(),parent的坐标没变,只是手指向上滚动时就是scrollview滚出屏幕,但是top还是距离parent的距离,所以那里用max取最大值

    //listview手指向上滑动屏幕时会导致headRoot的top为负值,因为head是滚出屏幕的head部分并不是listview中item重用机制

    intheadTop = 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());

    }elseif(headTop ==0) {//当手指从上往下滑动屏幕到达最顶端时,但还有一段可滑行的距离放手后又回到起始位置,跟系统有关

      //此时这个listview的Top是负值所以要减去-scrolly:注这个scrollY=listview.getTop();让悬浮的Title跟随实际的title一起浮动

      mFloatTopLayout.layout(0, mFloatTargetLayout.getTop() - scrollY, mFloatTopLayout.getWidth(),

          mFloatTargetLayout.getTop() - scrollY + mFloatTopLayout.getHeight());

    }elseif(headTop <0) {//由于手指向上滑动屏幕的很快会导致title悬浮不到顶部,所以要强制其在顶部

      mFloatTopLayout.layout(0,0, mFloatTopLayout.getWidth(),

          mFloatTopLayout.getHeight());

    }

 

    //这种方式会导致闪跳的现象,可以通过动画来实现

  }

 

}

 

主要是onScroll()方法的逻辑:

可以看看大神的实现

 

 代码如下

publicvoidonScroll(intscrollY) {

    intmBuyLayout2ParentTop = 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代码如下

 

 代码如下

packagecom.example.zwr.listviewfloatbardemo;

 

importandroid.content.Context;

importandroid.util.AttributeSet;

importandroid.util.Log;

importandroid.widget.ListView;

/**

 *

 * @author zhongwr

 *

 */

publicclassFloatListViewextendsListView {

  privatestaticfinalString TAG ="FloatListView";

  privateOnScrollListener onScrollListener;

   

  publicFloatListView(Context context) {

   this(context,null);

  }

   

  publicFloatListView(Context context, AttributeSet attrs) {

   this(context, attrs,0);

  }

 

  publicFloatListView(Context context, AttributeSet attrs,intdefStyle) {

   super(context, attrs, defStyle);

  }

   

   

  /**

  * 设置滚动接口

  * @param onScrollListener

  */

  publicvoidsetOnScrollListener(OnScrollListener onScrollListener) {

   this.onScrollListener = onScrollListener;

  }

  

 

  @Override

  protectedvoidonSizeChanged(intw,inth,intoldw,intoldh) {

//  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

  protectedvoidonScrollChanged(intl,intt,intoldl,intoldt) {

   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

  *

  */

  publicinterfaceOnScrollListener{

   /**

    * 回调方法, 返回MyScrollView滑动的Y方向距离

    * @param scrollY

    *       、

    */

   publicvoidonScroll(intscrollY);

  }

   

  

 

}

 

没什么逻辑,就是重写了onSizeChaged()方法,然后在里边写了调用接口的回调。
就是这么简单!!

demo如下:listview悬浮topBar

android listview优化_android之listview悬浮topBar效果

http://m.bbyears.com/zhufuduanxin/127199.html

推荐访问:android studio listview
相关阅读 猜你喜欢
本类排行 本类最新