安卓中級教程(3):ScrollView

 

以上是scrollview的圖例,可見srollview是一種滑動功能的控件,亦是非常常見的控件。

一般寫法如下:

package com.mycompany.viewscroller;


import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.widget.Scroller;
import android.widget.Toast;

/**
 * 實現上下滑動的效果,主要利用了屏幕坐標系和滾動條,有五個參數必須預先設置
 * @author Administrator
 *
 */
public class VerticalPager extends ViewGroup{

    private Scroller mScroller;  //第一個參數:滾動條
    private Context mContext; //第二個參數:滾動內容
    private final static int RATE = 5; //第三個參數:速率標準
    private final static int DISTANCE = 300;//需要滾動的距離


    private VelocityTracker mVelocityTracker;//通過此方法可以計算速度


    public VerticalPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext=context;
        mScroller=new Scroller(context);


    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int totalHeight=0;
        int count=getChildCount();

        for(int i=0;i<count;i++){
            View childView=getChildAt(i);
            childView.layout(l, totalHeight, r, totalHeight+b);
            totalHeight+=b;
        }
    }




    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width=MeasureSpec.getSize(widthMeasureSpec);
        int height=MeasureSpec.getSize(heightMeasureSpec);


        int count=getChildCount();
        for(int i=0;i<count;i++){
            getChildAt(i).measure(width, height);
        }
        setMeasuredDimension(width, height);
    }


    private int mLastMotionY;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(mVelocityTracker==null){
            mVelocityTracker=VelocityTracker.obtain();
        }
        mVelocityTracker.addMovement(event);

        int action=event.getAction();

        float y=event.getY();

        switch(action){
            case MotionEvent.ACTION_DOWN:
                if(!mScroller.isFinished()){
                    mScroller.abortAnimation();
                }
                mLastMotionY=(int) y;
                Log.d("montion", ""+getScrollY());
                break;
            case MotionEvent.ACTION_MOVE:
                int deltaY=(int) (mLastMotionY-y);
                scrollBy(0,deltaY);
                invalidate();
                mLastMotionY=(int) y;
                break;
            case MotionEvent.ACTION_UP:
// if(mVelocityTracker!=null){
// mVelocityTracker.recycle();
// mVelocityTracker=null;
// }
                mVelocityTracker.computeCurrentVelocity(1, 1000); //單位為1說明,一秒一個像素,最大值為1000
                float vy = mVelocityTracker.getYVelocity();  //vy代表Y軸方向的速率
                Log.i("test","velocityTraker : "+mVelocityTracker.getYVelocity());     
                if(getScrollY()<0){
                    mScroller.startScroll(0, -DISTANCE, 0, DISTANCE);
                }else if(getScrollY()>(getHeight()*(getChildCount()-1))){
                    View lastView=getChildAt(getChildCount()-1);
                    mScroller.startScroll(0,lastView.getTop()+DISTANCE, 0, -DISTANCE);
                }else{
                    int position=getScrollY()/getHeight();
                    View positionView = null;
                    if(vy<-RATE){  //下滑
                        positionView=getChildAt(position+1);
                        mScroller.startScroll(0, positionView.getTop()-DISTANCE, 0, +DISTANCE);
                    }else if(vy>RATE){//上滑
                        positionView=getChildAt(position);
                        mScroller.startScroll(0, positionView.getTop()-DISTANCE, 0, +DISTANCE);
                    }else {
                        int mod=getScrollY()%getHeight();
                        if(mod>getHeight()/2){
                            positionView=getChildAt(position+1);
                            mScroller.startScroll(0, positionView.getTop()-DISTANCE, 0, +DISTANCE);
                        }else{
                            positionView=getChildAt(position);
                            mScroller.startScroll(0, positionView.getTop()+DISTANCE, 0, -DISTANCE);
                        }
                    }
                } 
                invalidate();
                break;
        }
        return true; //返回true表示事件由本View消費掉
    }


    @Override
    public void computeScroll() {
        super.computeScroll();
        if(mScroller.computeScrollOffset()){
            scrollTo(0, mScroller.getCurrY());
        }
    }

}

xml.格式如下:

<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <com.example.viewpagervertical.VerticalPager
        android:id="@+id/vertyPager1"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
        <TextView
           
            android:id="@+id/textView1"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:text="TextView1111" />
        <TextView
            
            android:id="@+id/textView2"
            android:layout_width="fill_parent"
            android:layout_height="100dp"
            android:text="TextView2222" />
        <TextView
            
            android:id="@+id/textView3"
            android:layout_width="fill_parent"
            android:layout_height="100dp"
            android:text="TextView2222" />
        <TextView
            android:id="@+id/textView4"
            android:layout_width="fill_parent"
            android:layout_height="100dp"
            android:text="TextView2222" />
    </com.example.viewpagervertical.VerticalPager>

</LinearLayout>

 

掌握簡單的scroll滾動功能是遠遠不足以應付我們現實上的需要,為了可以深入地深討scroll滾動功能的中級應用,我在下面先提供一條鏈結,大家可以嘗試將各種滾動功能併合在一起,測試其兼容。

 

http://xm.cmgine.net/archives/10052.html

 

在這一中級教程的章節中,我們首先會探討:如何測試ListView是否已經滾動到底部的問題。因為在ListView和ScrollView之間經常會出錯,出錯當然是指ListView無法顯示到底的問題。這是我們中竹竹一月金要解沫的問題。

 

 

//我們可以用如下方法去測試是否已經滾動到最下方

if(getScrollY() + getHeight() >=  computeVerticalScrollRange())
{
Log.d(TAG,"------滾動到最下方------");
}
else
{
Log.d(TAG,"没有到最下方");
}

//在實際應用中,可以矕繼承ScrollView,來實現這個功能,如下:

public class XScrollView extends ScrollView {
  
      
    protected Context ctx=null;
    public XScrollView(Context context) {
        super(context);
        ctx=context;
          
        // TODO Auto-generated constructor stub
    }
    protected OnScrollStateChanged sc=null;
    public void setOnScrollStateChanged(OnScrollStateChanged _sc)
    {
        sc=_sc;
    }
    @Override
    protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX,
            boolean clampedY) {
        // TODO Auto-generated method stub
        if(getScrollY() + getHeight() >=  computeVerticalScrollRange())
        {
            sc.ScrollBottom();
        }
        super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
    }
}
public interface OnScrollStateChanged
{
    public void ScrollTop();
    public void ScrollBottom();
}

 

posted @ 2015-05-15 10:29  少於無  阅读(143)  评论(0)    收藏  举报