Android學習之 Scroller的介紹與使用

小呂-ICE發表於2015-05-27
  • 類概述

    Android裡Scroller類是為了實現View平滑滾動的一個Helper類。通常在自定義的View時使用,在View中定義一個私有成員mScroller = new Scroller(context)設定mScroller滾動的位置時,並不會導致View的滾動通常是用mScroller*記錄/計算View滾動的位置*,再重寫View的computeScroll(),呼叫View的scrollTo(int x,int y)方法完成實際的滾動

  • 主要方法介紹

    這裡寫圖片描述

更多關於Scroller類API詳細介紹可前往
http://api.apkbus.com/reference/android/widget/Scroller.html

  • 使用介紹-小例項-自定義一個支援滑動刪除事件的控制元件[SlideView]

    • 首先看一下例項的效果演示:
      這裡寫圖片描述

    • 下面是實現程式碼

      • 自定義控制元件佈局檔案:slide_view.xml
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/view_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

    </LinearLayout>

    <LinearLayout
        android:id="@+id/holder"
        android:layout_width="80dp"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:orientation="horizontal"
        android:background="@android:color/darker_gray">

        <TextView
            android:id="@+id/delete"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="20dp"
            android:layout_centerInParent="true"
            android:gravity="center"
            android:textColor="@android:color/white"
            android:text="detele"/>

    </LinearLayout>

</merge>
 - 自定義控制元件實現類:SlideView.java [內含Scroller的使用介紹]
import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.Scroller;
import android.widget.TextView;

/**
 * Created by ice on 15/5/4.
 */
public class SlideView extends LinearLayout{

    private Context mContext;

    private LinearLayout mViewContent;

    private LinearLayout mHolder;

    private TextView tv_delete;

    // 彈性滑動物件,實現View平滑滾動的一個幫助類
    private Scroller mScroller;

    // 滑動回撥介面,用來向上層通知滑動事件
    private OnSlideListener mOnSlideListener;

    private int mHolderWidth = 100;

    private int mLastX = 0;

    private int mLastY = 0;

    private static final int TAN = 2;


    public SlideView(Context context) {
        super(context);
        initView();
    }

    public SlideView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView();
    }


    private void initView(){
        mContext = getContext();
        mScroller = new Scroller(mContext);
        setOrientation(LinearLayout.HORIZONTAL);
        setGravity(Gravity.CENTER_VERTICAL);

        View.inflate(mContext, R.layout.slide_view, this);
        mViewContent = (LinearLayout)findViewById(R.id.view_content);
        mHolder = (LinearLayout)findViewById(R.id.holder);

        tv_delete = (TextView)findViewById(R.id.delete);

    }


    public void setButtonText(CharSequence text){
        tv_delete.setText(text);
    }


    public void setContentView(View view){
        mViewContent.addView(view);
    }


    public void onRequireTouchEvent(MotionEvent event){
            int x = (int)event.getX();
            int y = (int)event.getY();
            int scrollX = getScrollX();
            switch (event.getAction()){
                case MotionEvent.ACTION_DOWN:
                    if(!mScroller.isFinished()){
                        mScroller.abortAnimation();
                    }
                    if(mOnSlideListener != null){
                        mOnSlideListener.onSlide(this, OnSlideListener.SLIDE_STATUS_START_SCROLL);
                    }

                    break;

                case MotionEvent.ACTION_MOVE:
                    int deltaX = x - mLastX;
                    int deltaY = y - mLastY;
                    if(Math.abs(deltaX) < Math.abs(deltaY)*TAN){
                        // 滑動不滿足條件 不做橫向滑動
                        break;
                    }

                    int newScrollX = scrollX - deltaX;
                    if(deltaX != 0){
                        if(newScrollX < 0){
                            newScrollX = 0;
                        }else if(newScrollX > mHolderWidth){
                            newScrollX = mHolderWidth;
                        }
                        this.scrollTo(newScrollX, 0);
                    }

                    break;

                case MotionEvent.ACTION_UP:
                    int newScrollx = 0;
                    if(scrollX - mHolderWidth*0.75 > 0){
                        newScrollx = mHolderWidth;
                    }

                    this.smoothScrollTo(newScrollx, 0);
                    // 通知上層滑動事件
                    if(mOnSlideListener != null){
                        mOnSlideListener.onSlide(this, newScrollx == 0 ? OnSlideListener.SLIDE_STATUS_OFF
                                : OnSlideListener.SLIDE_STATUS_ON);
                    }

                    break;

                default:
                    break;
            }

            mLastX = x;
            mLastY = y;
    }


    /**
     * 呼叫此方法滾動到目標位置
     * @param fx  目標x座標
     * @param fy  目標Y座標
     */
    private void smoothScrollTo(int fx, int fy){
        int scrollX = getScrollX();
        int dx = fx - scrollX;

        int scrollY = getScrollY();
        int dy = fy - scrollY;
        //設定mScroller的滾動偏移量
        mScroller.startScroll(scrollX, scrollY, dx, dy, Math.abs((dx)*3));

        invalidate();
    }


    /**
     * 由mScroller記錄/計算好View滾動的位置後,最後由View的computeScroll(),完成實際的滾動
     */
    @Override
    public void computeScroll() {
        //先判斷mScroller滾動是否完成
        if(mScroller.computeScrollOffset()){
            //這裡呼叫View的scrollTo()完成實際的滾動
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            //必須呼叫該方法,否則不一定能看到滾動效果
            postInvalidate();
        }
        super.computeScroll();
    }


    /**
     * 設定滑動回撥
     * @param onSlideListener
     */
    public void setOnSlideListener(OnSlideListener onSlideListener){
        this.mOnSlideListener = onSlideListener;
    }


    public interface OnSlideListener {
        public static final int SLIDE_STATUS_OFF = 0;
        public static final int SLIDE_STATUS_START_SCROLL = 1;
        public static final int SLIDE_STATUS_ON = 2;

        public void onSlide(View view, int status);
    }

}
 - Activity佈局檔案:activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tv_content"
        android:text="向左滑動控制元件刪除"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <demo.ice.com.helloapple.SlideView
        android:id="@+id/sv_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/tv_content" >

    </demo.ice.com.helloapple.SlideView>

</RelativeLayout>
 - Activity類:MainActivity.java
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity implements SlideView.OnSlideListener, View.OnClickListener{

    private SlideView slideView;

    private LinearLayout slide_delete;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        slideView = (SlideView)findViewById(R.id.sv_view);

        View slideContentView = View.inflate(MainActivity.this, R.layout.slide_list_item, null);
        slideView.setContentView(slideContentView);
        slideView.setButtonText("刪除");

        slide_delete = (LinearLayout)findViewById(R.id.holder);

        slideView.setOnSlideListener(this);
        slide_delete.setOnClickListener(this);

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // 將事件交由slideView自身處理
        slideView.onRequireTouchEvent(event);
        return super.onTouchEvent(event);
    }

    @Override
    public void onClick(View view) {
        if(view.getId() == R.id.holder){
             Toast.makeText(MainActivity.this, "你點選了刪除按鈕", Toast.LENGTH_LONG).show();
        }

    }

    @Override
    public void onSlide(View view, int status) {

    }
}
 - 填充自定義控制元件內容佈局檔案:slide_list_item.xml     
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@android:drawable/ic_menu_camera"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="13歲iOS開發者:Swift開發Sprite Kit遊戲實踐"/>

</LinearLayout>




如果您對文章內容有任何疑問或有更好的見解, 歡迎通過留言或發郵件的方式聯絡我:
ice_zhengbin@163.com

如需要轉載,請註明出處,謝謝!!

相關文章