android之listview懸浮topBar效果
雖然listview是過(guò)去式,但由于項(xiàng)目中還是有用listview,百度一番都是scrollview中的懸浮bar,沒(méi)有看到有l(wèi)istview的懸浮bar,所以自己寫一個(gè)懸浮bar;參照夏大神的scrollview的懸浮demo
效果如下:

自定義的Listview和scrollView沒(méi)什么區(qū)別都是重寫onScrollChange()然后在里邊調(diào)用自己實(shí)現(xiàn)的接口,是對(duì)外提供的接口吧,這里沒(méi)有封裝,需要的可以自己將其封裝,然后在自己項(xiàng)目中使用。
重點(diǎn)的方法:
onScrollChanged()方法:是在ListView和ScrollView在滾動(dòng)時(shí)會(huì)回調(diào)的方法并且能獲取到當(dāng)前最新的top left和上一次的top 和left
getViewTreeObservew().addOnGlobalLayoutLister():這是View都有的方法,可以監(jiān)控改view的變化(如顯示、隱藏)都會(huì)回調(diào)以及在view被繪制時(shí)會(huì)被回調(diào)。
思路如下:
一、可以使用getViewTreeObservew().addOnGlobalLayoutLister():方法在第一次進(jìn)入到這個(gè)頁(yè)面后將懸浮的bar與目標(biāo)view繪制重合。防止顯示隱藏會(huì)有一閃的情況
二、在onScrollChaged()方法中回調(diào)自定義的接口onScrollListener的方法onScroll()在這里通過(guò)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);
// 當(dāng)布局的狀態(tài)或者控件的可見(jiàn)性發(fā)生改變回調(diào)的接口:當(dāng)布局都繪制好后會(huì)執(zhí)行一次
findViewById(R.id.parent_layout).getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// 這一步很重要,一開(kāi)始讓目標(biāo)懸浮的view和要懸浮的view重合一起,之后懸浮view跟隨一起目標(biāo)view一起移動(dòng)
onScroll(lvFloat.getScrollY());
}
});
lvFloat.setAdapter(new DataListAdapter(this));
}
@Override
public void onScroll(int scrollY) {
// SrcollView和這個(gè)Listview不同之處:scrolly是scrollview.getTop(),parent的坐標(biāo)沒(méi)變,只是手指向上滾動(dòng)時(shí)就是scrollview滾出屏幕,但是top還是距離parent的距離,所以那里用max取最大值
//listview手指向上滑動(dòng)屏幕時(shí)會(huì)導(dǎo)致headRoot的top為負(fù)值,因?yàn)閔ead是滾出屏幕的head部分并不是listview中item重用機(jī)制
int headTop = head.getTop();
if (headTop <= 0 && Math.abs(headTop) <= mFloatTargetLayout.getTop() && scrollY >= 0) {//手指向上滑動(dòng)屏幕
mFloatTopLayout.layout(0, mFloatTargetLayout.getTop() + headTop, mFloatTopLayout.getWidth(),
mFloatTargetLayout.getTop() + headTop + mFloatTopLayout.getHeight());
} else if (headTop == 0) {//當(dāng)手指從上往下滑動(dòng)屏幕到達(dá)最頂端時(shí),但還有一段可滑行的距離放手后又回到起始位置,跟系統(tǒng)有關(guān)
//此時(shí)這個(gè)listview的Top是負(fù)值所以要減去-scrolly:注這個(gè)scrollY=listview.getTop();讓懸浮的Title跟隨實(shí)際的title一起浮動(dòng)
mFloatTopLayout.layout(0, mFloatTargetLayout.getTop() - scrollY, mFloatTopLayout.getWidth(),
mFloatTargetLayout.getTop() - scrollY + mFloatTopLayout.getHeight());
} else if (headTop < 0) {//由于手指向上滑動(dòng)屏幕的很快會(huì)導(dǎo)致title懸浮不到頂部,所以要強(qiáng)制其在頂部
mFloatTopLayout.layout(0, 0, mFloatTopLayout.getWidth(),
mFloatTopLayout.getHeight());
}
//這種方式會(huì)導(dǎo)致閃跳的現(xiàn)象,可以通過(guò)動(dòng)畫來(lái)實(shí)現(xiàn)
}
}
主要是onScroll()方法的邏輯:
可以看看夏大神的實(shí)現(xiàn)
public void onScroll(int scrollY) {
int mBuyLayout2ParentTop = Math.max(scrollY, mBuyLayout.getTop());
mTopBuyLayout.layout(0, mBuyLayout2ParentTop, mTopBuyLayout.getWidth(), mBuyLayout2ParentTop + mTopBuyLayout.getHeight());
}
他這里是直接使用scrollY(其實(shí)是scrollview的最新top值)和目標(biāo)view的top值去最大,因?yàn)镾crollView是滑出屏幕的,但是其parent的位置沒(méi)變,所以scrollview的top會(huì)越來(lái)越大而且是正值。所以可以通過(guò)這種方式來(lái)繪制懸浮的bar。
但是Listview的機(jī)制不一樣,滑動(dòng)出屏幕時(shí)item由于是重用機(jī)制,所以listView中的top并沒(méi)有改變;巧的是head的機(jī)制有點(diǎn)像Scrollview滑出的機(jī)制,但是又不一樣得到的head的top值是負(fù)值,猜測(cè)相對(duì)坐標(biāo)由于listView這個(gè)父布局沒(méi)動(dòng)但是head已經(jīng)滑出屏幕所以是負(fù)值。根據(jù)這個(gè)值處理我們想要的結(jié)果,剩下的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);
}
/**
* 設(shè)置滾動(dòng)接口
* @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);
}
/**
* 滾動(dòng)時(shí)會(huì)執(zhí)行
* @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);
}
}
/**
*
* 滾動(dòng)的回調(diào)接口
*
* @author xiaanming
*
*/
public interface OnScrollListener{
/**
* 回調(diào)方法, 返回MyScrollView滑動(dòng)的Y方向距離
* @param scrollY
* 、
*/
public void onScroll(int scrollY);
}
}
沒(méi)什么邏輯,就是重寫了onSizeChaged()方法,然后在里邊寫了調(diào)用接口的回調(diào)。
就是這么簡(jiǎn)單?。?br />
demo如下:listview懸浮topBar
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android TextView實(shí)現(xiàn)跑馬燈效果的方法
這篇文章主要介紹了Android TextView跑馬燈效果實(shí)現(xiàn)方法,涉及Android布局文件中相關(guān)屬性的設(shè)置技巧,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-01-01
Android編程實(shí)現(xiàn)二維碼的生成與解析
這篇文章主要介紹了Android編程實(shí)現(xiàn)二維碼的生成與解析方法,結(jié)合實(shí)例分析了Android二維碼的生成與讀取二維碼的相關(guān)技巧,并提供了二維碼jar包供讀者下載,需要的朋友可以參考下2015-11-11
Android控制文本輸入框最多輸入10個(gè)字符長(zhǎng)度
這篇文章主要為大家詳細(xì)介紹了Android控制文本輸入框最多輸入10個(gè)字符長(zhǎng)度,即最多輸入5個(gè)漢字,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10
Flutter Set存儲(chǔ)自定義對(duì)象時(shí)保證唯一的方法詳解
在Flutter中,Set和List是兩種不同的集合類型,List中存儲(chǔ)的元素可以重復(fù),Set中存儲(chǔ)的元素不可重復(fù),如果想在Set中存儲(chǔ)自定義對(duì)象,需要確保對(duì)象的唯一性,那么如何保證唯一,接下來(lái)小編就給大家詳細(xì)的介紹一下2023-11-11
Android RecyclerView添加上拉加載更多效果
這篇文章主要為大家詳細(xì)介紹了Android RecyclerView添加上拉加載更多效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02
詳談Android中onTouch與onClick事件的關(guān)系(必看)
下面小編就為大家?guī)?lái)一篇詳談Android中onTouch與onClick事件的關(guān)系(必看)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-03-03
android 獲取手機(jī)GSM/CDMA信號(hào)信息,并獲得基站信息的方法
下面小編就為大家?guī)?lái)一篇android 獲取手機(jī)GSM/CDMA信號(hào)信息,并獲得基站信息的方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-11-11
Android編程中activity啟動(dòng)時(shí)出現(xiàn)白屏、黑屏問(wèn)題的解決方法
這篇文章主要介紹了Android編程中activity啟動(dòng)時(shí)出現(xiàn)白屏、黑屏問(wèn)題的解決方法,涉及Android針對(duì)activity啟動(dòng)設(shè)置的技巧,需要的朋友可以參考下2015-12-12
Android下拉刷新控件SwipeRefreshLayout源碼解析
這篇文章主要為大家詳細(xì)解析Android下拉刷新控件SwipeRefreshLayout源碼,感興趣的小伙伴們可以參考一下2016-07-07

