最近辞职在家闲来无事搞起了Android studio,刚上手时各种头痛,现在适应来一段时间发现它确实要比eclipse强大一些,那么我们今天就来说一下scrollview的一些用法,相信很多人用scrollview时只是简单的把它当一个滚动装置来用,其实scrollview有很多简单却又炫酷的用法,先看个效果.
相信很多人会感到眼熟,这就是ScrollingTricks的效果,我们今天就是来分析它的工作原理,毕竟从原理上理解效果会更好。
1,STICKY
我们知道scrollview的onScrollChanged方法是只能通过继承scrollview来获取的,那么我们就通过接口的回调把我们需要的值给取出来。
public 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();
}
}
接着我们可以在布局中引用我们自己写的scrollview
<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真实让人冰火俩重天,好用的时候真好用,难用的时候让人想砸电脑!!