Android ScrollView妙用(scrolling tricks詳解)
最近辭職在家閒來無事搞起了Android studio,剛上手時各種頭痛,現在適應來一段時間發現它確實要比eclipse強大一些,那麼我們今天就來說一下scrollview的一些用法,相信很多人用scrollview時只是簡單的把它當一個滾動裝置來用,其實scrollview有很多簡單卻又炫酷的用法,先看個效果.
相信很多人會感到眼熟,這就是ScrollingTricks的效果,我們今天就是來分析它的工作原理,畢竟從原理上理解效果會更好。
1,STICKY
我們知道scrollview的onScrollChanged方法是隻能通過繼承scrollview來獲取的,那麼我們就通過介面的回撥把我們需要的值給取出來。
接著我們可以在佈局中引用我們自己寫的scrollviewpublic class ObservableScrollView extends ScrollView { public Callbacks mCallbacks; public ObservableScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public void setCallbacks(Callbacks callbacks) { this.mCallbacks = callbacks; } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (mCallbacks != null){ mCallbacks.onScrollchanged(t); } } /** * 由垂直方向滾動條代表的所有垂直範圍,預設的範圍是當前檢視的畫圖高度。 */ public int computeVerticalScrollRange(){ return super.computeVerticalScrollRange(); } public interface Callbacks { public void onScrollchanged(int t); public void onTouchUp(); public void onTouchDown(); } }
<com.example.apple.myapplication.ObservableScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/scroll_view" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <View style="@style/Item.Top" /> <View android:id="@+id/placeholder" android:layout_width="match_parent" android:layout_height="@dimen/sticky_height" /> <View style="@style/Item.Bottom" /> <View style="@style/Item.Bottom.Alt" /> <View style="@style/Item.Bottom" /> <View style="@style/Item.Bottom.Alt" /> <View style="@style/Item.Bottom" /> <View style="@style/Item.Bottom.Alt" /> </LinearLayout> <TextView android:id="@+id/sticky" style="@style/Item.Sticky" /> </FrameLayout> </com.example.apple.myapplication.ObservableScrollView>
注意我們裡面一定要用FrameLayout
public class StickyActivity extends Activity implements ObservableScrollView.Callbacks {
private TextView txtContent;
private ObservableScrollView observableScrollView;
private View mPlaceholderView;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sticky);
mPlaceholderView = (View)findViewById(R.id.placeholder);
txtContent = (TextView) findViewById(R.id.sticky);
txtContent.setText("StickyActivity");
observableScrollView = (ObservableScrollView) findViewById(R.id.scroll_view);
observableScrollView.setCallbacks(this);
/**
* 當佈局繪製完全的時候我們才可以得到view.getTop()等
*/
observableScrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
onScrollchanged(observableScrollView.getScrollY());
}
});
}
@Override
public void onScrollchanged(int t) {
int translation = Math.max(t,mPlaceholderView.getTop());
txtContent.setTranslationY(translation);
}
@Override
public void onTouchUp() {
}
@Override
public void onTouchDown() {
}
}
很簡單不是麼,不過在這裡還是要給大家解釋一下,getViewTreeObserver,因為我們要獲取到view.getTop的值,但我們在oncreate裡面獲取時獲取不到的,返回值永遠為0,所以我們要新增整體佈局監聽。
接下來的onScrollchanged方法我們上個圖解釋一下
為什麼我的眼裡充滿淚水,是因為我根本沒有繪畫天賦。。
這樣我們直觀的看一下,Math.max(t,gettop);就是不斷的比較,當t大於gettop的時候我們可以認為滑倒頂部了,接下來因為t還在增大我們setTranslationY也在不斷增大,所以效果上就是我們的textview停在了最上面。
2,QUICKRETURN
效果就是不管我們滑動了多遠只要向下滑動的時候我們的textview就可以顯示出來,我們接著分析程式碼,其實也不難
/**
* 上滑動狀態
*/
private static final int STATE_ONSCREEN = 0;
/**
* 上滑動至完全遮蓋住mPlaceholderView
*/
private static final int STATE_OFFSCREEN = 1;
/**
* 完全遮蓋住時,下滑狀態
*/
private static final int STATE_RETURING = 2;
private int mState = STATE_ONSCREEN;
/**
* 高度
*/
private int mViewHeight;
private int minRaw;
其他的基本類似,我們可以看到新增了三個狀態,以及一個minraw,這個值後面是用來做判斷以及確認位置的
@Override
public void onScrollchanged(int t) {
int raw = mPlaceholderView.getTop() - t;
int translationY = 0;
switch (mState) {
case STATE_ONSCREEN:
// Log.d("TAG","STATE_ONSCREEN");
if (raw < -mViewHeight) {
mState = STATE_OFFSCREEN;
minRaw = raw;
}
translationY = raw;
break;
case STATE_OFFSCREEN:
// Log.d("TAG","STATE_OFFSCREEN");
if (raw<=minRaw){
minRaw = raw;
}
else{
mState = STATE_RETURING;
}
translationY = raw;
break;
case STATE_RETURING:
translationY = (raw - minRaw) - mViewHeight;
Log.d("TAG","translationY:"+translationY);
if (translationY > 0) {
translationY = 0;
minRaw = raw - mViewHeight;
}
if (raw > 0) {
mState = STATE_ONSCREEN;
translationY = raw;
}
if (translationY < -mViewHeight) {
mState = STATE_OFFSCREEN;
minRaw = raw;
}
break;
}
txtContent.setTranslationY(translationY+t);
}
這次在onscrollchange裡面的程式碼可能多了一些,但是隻要理解了其實沒什麼。
首先是raw = getTop() - t;
空間能力強的可能已經自行腦補出來畫面了,我們這裡分析一下t是y軸上的變化值,gettop為距離頂部的值,那麼我們這樣一相減得到的是不是當前位置。
STATE_ONSCREEN:向上滑動當raw < -ViewHeight時說明螢幕上已經徹底看不到我們的text了,狀態就轉變成STATE_OFFSCREEN.
STATE_OFFSCREEN:此時我們已經看不到text所以我們只要向下滑動的時候minraw>raw = true;此時就轉變成STATE_RETURING.
STATE_RETURING:因為我們時向下滑動,所以我們要算出來滑動的距離以及text顯示的部分,所以translationY = (raw - minRaw) - mViewHeight;
這樣的話應該就沒什麼難理解的了,最後說下android studio真實讓人冰火倆重天,好用的時候真好用,難用的時候讓人想砸電腦!!