Android開發(fā)實現(xiàn)帶有反彈效果仿IOS反彈scrollview教程詳解
首先給大家看一下我們今天這個最終實現(xiàn)的效果圖:
這個是ios中的反彈效果。當然我們安卓中如果想要實現(xiàn)這種效果,感覺不會那么生硬,滾動到底部或者頂部的時候。當然
使用scrollview是無法實現(xiàn)的。所以我們需要新建一個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);
}
/***
* 根據(jù) XML 生成視圖工作完成.該函數(shù)在生成視圖的最后調(diào)用,在所有子視圖添加完之后. 即使子類覆蓋了 onFinishInflate
* 方法,也應該調(diào)用父類的方法,使該方法得以執(zhí)行.
*/
@SuppressLint("MissingSuperCall")
@Override
protected void onFinishInflate() {
if (getChildCount() > 0) {
inner = getChildAt(0);
}
}
/***
* 監(jiān)聽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. 之后記錄準確了就正常執(zhí)行.
* 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>
最后直接運行即可看到上面的效果。
(AndroidStudio版)github下載地址:
https://github.com/QQ986945193/DavidBounceScrollView
以上所述是小編給大家介紹的Android開發(fā)實現(xiàn)帶有反彈效果仿IOS反彈scrollview教程詳解,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關文章
Android實現(xiàn)MVVM架構數(shù)據(jù)刷新詳解流程
MVVM架構模式,即Model-View-ViewModel三個層級,MVVM模式出來的時間已經(jīng)很長了,網(wǎng)上關于MVVM模式的解析也有很多,我這里只說一下我自己的理解,基本上是和MVP模式相比較的一個差異2021-10-10
Android高德地圖poi檢索仿微信發(fā)送位置實例代碼
本篇文章主要介紹了Android高德地圖poi檢索仿微信發(fā)送位置實例代碼,具有一定的參考價值,有興趣的可以了解一下。2017-04-04
android自定義控件ImageView實現(xiàn)圓形圖片
這篇文章主要為大家詳細介紹了android自定義控件ImageView實現(xiàn)圓形圖片,適用于用戶頭像,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-12-12
Android應用開發(fā)中View繪制的一些優(yōu)化點解析
這篇文章主要介紹了Android應用開發(fā)中View繪制的一些優(yōu)化點解析,包括Layout布局和硬件加速等方面,需要的朋友可以參考下2016-03-03
Android動態(tài)使用VectorDrawable過程詳解
這篇文章主要介紹了Android動態(tài)使用VectorDrawable過程,2014年6月26日的I/O 2014開發(fā)者大會上谷歌正式推出了Android L,它帶來了全新的設計語言Material Design,新的API也提供了這個類VectorDrawable2023-02-02

