先上圖
(好多效果文章都不帶圖,我覺得先放圖也能給大家節省時間,合適了在往下看)
今天在開發的時候有這樣的一種需求,百度好久,沒有滿意的,基本上代碼扔一堆太複雜而且也沒有整理,沒心情看,最後放棄。
決定自己研究,嘗試了兩種思路:爲了方便,給要固定的那一欄起個名字叫 A 吧
1.最初我想通過兩個ScrollView,第一個Scroll裏面放(內容,A和 第二個Scroll)。當第一個Scroll大小滑完之後,會留A和第二個Scroll佔滿全屏,繼續滑動的時候當然只會滑動第二個Scroll,自然A就保持在頂部,這個最好想,應該可以實現,但是每個手機分辨率不一樣,刻意去設置大小可能會不兼容。放棄這個思路。
重點在這
2.第二個是判斷當A滑出屏外的時候,把A從Scroll拿出來,然後放到頂部。當判斷A滑入屏幕裏面在把A放入Scroll裏面。上圖就是第二種,看起來固定的很完美,我反正是看不出來有什麼瑕疵
看佈局代碼,這個主要是理解,理解之後就能72變,佈局代碼
//最外層用相對佈局,爲了讓放置A的容器固定在屏幕頂部,並且擋住ScrollView <RelativeLayout> //藍色是滑動控件和線性佈局組合 <ScrollView> <LinearLayout > //這個是放A的容器 <LinearLayout> //這是A <LinearLayout> </LinearLayout> </LinearLayout> </LinearLayout> </ScrollView> //這是懸浮A的容器,想放哪都行,根據需要 放左 放右 放上 放下。 <RelativeLayout> </RelativeLayout> </RelativeLayout>
這個佈局總的來講就是需要給A準備兩個盛放容器,一個滑動的,一個固定的
然後java代碼很少,僅僅給ScrollView 設置滑動監聽、然後裏面進行簡單 if 就可以了
下面代碼裏 linewai1 是滑動容器中放 A 的容器,re1是放 A 懸浮容器
public void listener(){ scrol.setOnScrollChangeListener(new View.OnScrollChangeListener() { @Override public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { if(scrollY>=linewai1.getY()){ removeOneself(A); re1.addView(A); }else if(linewai1.indexOfChild(A)<0){//這裏判斷A是否在A原來的容器裏,沒有的話就把A從懸浮容器移除 removeOneself(A); linewai1.addView(A);//放置到滑動容器 } } });
}
這裏提一下,如何判斷一個控件是否被滑出屏幕,這個也是問題,百度沒找到答案,我是根據控件的相對座標來進行判定的,這裏利用ScrollView的滑動距離和放置A的容器的getY( )來判斷的,實驗發現,當一個控件被滑出屏幕,那滑動距離一定大於該控件的相對Y座標。當小於的時候該控件是應該顯示出來的。
當A滑出屏幕,就從原容器移除,放到懸浮容器中,當A滑入屏幕,反向操作。
這裏值得注意的是,從容器中移除A,不能簡單的利用layout.removeview(View view)這個方法,會報錯的,只能從父控件中移除子控件,但是佈局和A並不是直接的父子關係,需要調入如下方法,這個方法是借鑑一位大佬的方法。
public static void removeOneself(View child){ if (child != null){ ViewGroup parent = (ViewGroup)child.getParent(); if (parent != null && parent instanceof ViewGroup) { parent.removeView(child); } } }
這個方法直接用就可以了
只要佈局設置好,只要一個滑動監聽就夠了,是不是代碼很少?前面提到的72變,理解了這個,是不是底部懸浮,左側懸浮,右側懸浮,亂七八糟的懸浮都OK了,😄😄😄😄😄😄
還有比這個簡單的麼,歡迎留言😛😛😛😛😛
小小的踩坑經驗分享完畢,有幫助的話給我個提醒贊哦