Android ScrollView妙用(scrolling tricks详解)
最近辞职在家闲来无事搞起了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真实让人冰火俩重天,好用的时候真好用,难用的时候让人想砸电脑!!
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。