1. 程式人生 > >【Android】Android開發實現帶有反彈效果,仿IOS反彈scrollview詳解教程

【Android】Android開發實現帶有反彈效果,仿IOS反彈scrollview詳解教程

作者:程式設計師小冰,GitHub主頁:https://github.com/QQ986945193
新浪微博:http://weibo.com/mcxiaobing
首先給大家看一下我們今天這個最終實現的效果圖:
這裡寫圖片描述
這個是ios中的反彈效果。當然我們安卓中如果想要實現這種效果,
感覺不會那麼生硬,滾動到底部或者頂部的時候。當然
使用scrollview是無法實現的。所以我們需要新建一個view繼承ScrollView

package davidbouncescrollview.qq986945193.com.davidbouncescrollview;

import android.annotation.SuppressLint;
import
android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.animation.TranslateAnimation; import android.widget.ScrollView; /** * @author :程式設計師小冰 * @新浪微博 :http://weibo.com/mcxiaobing * @GitHub
:https://github.com/QQ986945193 * @CSDN部落格: http://blog.csdn.net/qq_21376985 * @交流Qq :986945193 * 類名:帶有反彈效果的scrollview */
public class BounceScrollView extends ScrollView { private View inner;// 孩子View private float y;// 點選時y座標 private Rect normal = new Rect();// 矩形(這裡只是個形式,只是用於判斷是否需要動畫.) private
boolean isCount = false;// 是否開始計算 public BounceScrollView(Context context, AttributeSet attrs) { super(context, attrs); } /*** * 根據 XML 生成檢視工作完成.該函式在生成檢視的最後呼叫,在所有子檢視新增完之後. 即使子類覆蓋了 onFinishInflate * 方法,也應該呼叫父類的方法,使該方法得以執行. */ @SuppressLint("MissingSuperCall") @Override protected void onFinishInflate() { if (getChildCount() > 0) { inner = getChildAt(0); } } /*** * 監聽touch */ @Override public boolean onTouchEvent(MotionEvent ev) { if (inner != null) { commOnTouchEvent(ev); } return super.onTouchEvent(ev); } /*** * 觸控事件 * * @param ev */ public void commOnTouchEvent(MotionEvent ev) { int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: break; case MotionEvent.ACTION_UP: // 手指鬆開. if (isNeedAnimation()) { animation(); isCount = false; } break; /*** * 排除出第一次移動計算,因為第一次無法得知y座標, 在MotionEvent.ACTION_DOWN中獲取不到, * 因為此時是MyScrollView的touch事件傳遞到到了LIstView的孩子item上面.所以從第二次計算開始. * 然而我們也要進行初始化,就是第一次移動的時候讓滑動距離歸0. 之後記錄準確了就正常執行. * https://github.com/QQ986945193 */ case MotionEvent.ACTION_MOVE: final float preY = y;// 按下時的y座標 float nowY = ev.getY();// 時時y座標 int deltaY = (int) (preY - nowY);// 滑動距離 if (!isCount) { deltaY = 0; // 在這裡要歸0. } y = nowY; // 當滾動到最上或者最下時就不會再滾動,這時移動佈局 if (isNeedMove()) { // 初始化頭部矩形 if (normal.isEmpty()) { // 儲存正常的佈局位置 normal.set(inner.getLeft(), inner.getTop(), inner.getRight(), inner.getBottom()); } // Log.e("jj", "矩形:" + inner.getLeft() + "," + inner.getTop() // + "," + inner.getRight() + "," + inner.getBottom()); // 移動佈局 inner.layout(inner.getLeft(), inner.getTop() - deltaY / 2, inner.getRight(), inner.getBottom() - deltaY / 2); } isCount = true; break; default: break; } } /*** * 回縮動畫 */ public void animation() { // 開啟移動動畫 TranslateAnimation ta = new TranslateAnimation(0, 0, inner.getTop(), normal.top); ta.setDuration(200); inner.startAnimation(ta); // 設定回到正常的佈局位置 inner.layout(normal.left, normal.top, normal.right, normal.bottom); // Log.e("jj", "迴歸:" + normal.left + "," + normal.top + "," + normal.right // + "," + normal.bottom); normal.setEmpty(); } // 是否需要開啟動畫 public boolean isNeedAnimation() { return !normal.isEmpty(); } /*** * 是否需要移動佈局 inner.getMeasuredHeight():獲取的是控制元件的總高度 * <p/> * getHeight():獲取的是螢幕的高度 * <p/> * https://github.com/QQ986945193 * * @return */ public boolean isNeedMove() { int offset = inner.getMeasuredHeight() - getHeight(); int scrollY = getScrollY(); // Log.e("jj", "scrolly=" + scrollY); // 0是頂部,後面那個是底部 if (scrollY == 0 || scrollY == offset) { return true; } return false; } }

然後他的用法就是和ScrollView用法一樣了。比如直接在佈局中引用:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="davidbouncescrollview.qq986945193.com.davidbouncescrollview.MainActivity">

    <davidbouncescrollview.qq986945193.com.davidbouncescrollview.BounceScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="@android:color/black" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:text="大家好,我是程式設計師小冰" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="@android:color/black" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:text="大家好,我是程式設計師小冰" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="@android:color/black" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:text="大家好,我是程式設計師小冰" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="@android:color/black" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:text="大家好,我是程式設計師小冰" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="@android:color/black" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:text="大家好,我是程式設計師小冰" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="@android:color/black" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:text="大家好,我是程式設計師小冰" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="@android:color/black" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:text="大家好,我是程式設計師小冰" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="@android:color/black" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:text="大家好,我是程式設計師小冰" />
        </LinearLayout>

    </davidbouncescrollview.qq986945193.com.davidbouncescrollview.BounceScrollView>

</LinearLayout>