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真实让人冰火俩重天,好用的时候真好用,难用的时候让人想砸电脑!!


项目源码





郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。