Android ScrollView實(shí)現(xiàn)下拉彈回動(dòng)畫(huà)效果
這里設(shè)計(jì)一個(gè)自定義View,繼承了ScrollView,實(shí)現(xiàn)可以下拉里面的內(nèi)容,松手后畫(huà)面彈回,這個(gè)自定義的View可以當(dāng)做ScrollView來(lái)使用。
一般設(shè)計(jì)時(shí)的應(yīng)用效果:

一.自定義View的設(shè)計(jì)代碼
package com.lwz.mathbox.weight;
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;
/**
* 實(shí)現(xiàn)了可以有下拉彈回的ScrollView的自定義View
*/
public class SpringScrollView extends ScrollView {
private View inner;// 孩子
private float y;// 坐標(biāo)
private Rect normal = new Rect();// 矩形空白
public SpringScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/***
* 根據(jù) XML 生成視圖工作完成.該函數(shù)在生成視圖的最后調(diào)用,在所有子視圖添加完之后. 即使子類(lèi)覆蓋了 onFinishInflate
* 方法,也應(yīng)該調(diào)用父類(lèi)的方法,使該方法得以執(zhí)行.
*/
@Override
protected void onFinishInflate() {
if (getChildCount() > 0) {
inner = getChildAt(0);// 獲取其孩子
}
}
@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:
y = ev.getY();// 獲取點(diǎn)擊y坐標(biāo)
break;
case MotionEvent.ACTION_UP:
if (isNeedAnimation()) {
animation();
}
break;
case MotionEvent.ACTION_MOVE:
final float preY = y;
float nowY = ev.getY();
int deltaY = (int) (preY - nowY);// 獲取滑動(dòng)距離
y = nowY;
// 當(dāng)滾動(dòng)到最上或者最下時(shí)就不會(huì)再滾動(dòng),這時(shí)移動(dòng)布局
if (isNeedMove()) {
if (normal.isEmpty()) {
// 填充矩形,目的:就是告訴this:我現(xiàn)在已經(jīng)有了,你松開(kāi)的時(shí)候記得要執(zhí)行回歸動(dòng)畫(huà).
normal.set(inner.getLeft(), inner.getTop(),
inner.getRight(), inner.getBottom());
}
// 移動(dòng)布局
inner.layout(inner.getLeft(), inner.getTop() - deltaY / 2,
inner.getRight(), inner.getBottom() - deltaY / 2);
}
break;
default:
break;
}
}
/***
* 開(kāi)啟動(dòng)畫(huà)移動(dòng)
*/
public void animation() {
// 開(kāi)啟移動(dòng)動(dòng)畫(huà)
TranslateAnimation ta = new TranslateAnimation(0, 0, inner.getTop(),
normal.top);
ta.setDuration(300);
inner.startAnimation(ta);
// 設(shè)置回到正常的布局位置
inner.layout(normal.left, normal.top, normal.right, normal.bottom);
normal.setEmpty();// 清空矩形
}
/***
* 是否需要開(kāi)啟動(dòng)畫(huà)
* <p>
* 如果矩形不為空,返回true,否則返回false.
*
* @return
*/
public boolean isNeedAnimation() {
return !normal.isEmpty();
}
/***
* 是否需要移動(dòng)布局 inner.getMeasuredHeight():獲取的是控件的高度
* getHeight():獲取的是當(dāng)前控件在屏幕中顯示的高度
*
* @return
*/
public boolean isNeedMove() {
int offset = inner.getMeasuredHeight() - getHeight();
int scrollY = getScrollY();
// 0是頂部,后面那個(gè)是底部
if (scrollY == 0 || scrollY == offset) {
return true;
}
return false;
}
}
二.簡(jiǎn)單調(diào)用示例
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
//包名+類(lèi)型
<com.lwz.mathbox.weight.SpringScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:orientation="vertical">
<EditText
android:id="@+id/et_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:gravity="top"
android:hint="輸入文字"
android:minLines="4"
android:singleLine="false"
android:textSize="14sp" />
<TextView
android:id="@+id/tv_size"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:gravity="right"
android:text="0/255" />
</LinearLayout>
</com.lwz.mathbox.weight.SpringScrollView>
</LinearLayout>
調(diào)用的話只需要在xml中調(diào)用就可以了,邏輯操作的實(shí)現(xiàn)已經(jīng)在自定義的View中完成了, 對(duì)應(yīng)這些工具類(lèi),沒(méi)有必要很深入去理解,學(xué)會(huì)調(diào)用就可以了。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
ijkPlayer播放器的全自動(dòng)編譯腳本及最終編譯包
這篇文章主要介紹了ijkPlayer播放器的全自動(dòng)編譯腳本及最終編譯包,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
Android編程之頁(yè)面切換測(cè)試實(shí)例
這篇文章主要介紹了Android編程之頁(yè)面切換測(cè)試,實(shí)例分析了Android實(shí)現(xiàn)頁(yè)面點(diǎn)擊切換的相關(guān)技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04
Android ActionBarActivity設(shè)置全屏無(wú)標(biāo)題的方法總結(jié)
這篇文章主要介紹了Android ActionBarActivity設(shè)置全屏無(wú)標(biāo)題的相關(guān)資料,需要的朋友可以參考下2017-07-07
Android開(kāi)發(fā)Jetpack組件DataBinding用例詳解
這篇文章主要為大家介紹了Android開(kāi)發(fā)Jetpack組件DataBinding的使案用例詳解說(shuō)明,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-02-02
Android 6.0動(dòng)態(tài)權(quán)限申請(qǐng)教程
本文主要介紹了Android 6.0動(dòng)態(tài)權(quán)限申請(qǐng)的教程,具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-03-03
Android的HTTP類(lèi)庫(kù)Volley入門(mén)學(xué)習(xí)教程
這篇文章主要介紹了Android應(yīng)用開(kāi)發(fā)框架Volley的入門(mén)學(xué)習(xí)教程,Volley適合于輕量級(jí)的通信功能開(kāi)發(fā),善于處理JSON對(duì)象,需要的朋友可以參考下2016-02-02
android長(zhǎng)截屏原理及實(shí)現(xiàn)代碼
本篇文章主要介紹了android長(zhǎng)截屏原理及實(shí)現(xiàn)代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-08-08
Android自定義View原理(實(shí)戰(zhàn))
這篇文章主要介紹了Android自定義View原理,由于Android系統(tǒng)內(nèi)置的View不滿足我們的業(yè)務(wù)需求,變產(chǎn)生了需要自定義View的原因,關(guān)于自定義詳情,需要的小伙伴可以參考下面文章具體詳情2022-05-05
Android 通過(guò)Intent調(diào)用系統(tǒng)拍照程序出現(xiàn)圖片太小的問(wèn)題解決辦法
這篇文章主要介紹了Android 通過(guò)Intent調(diào)用系統(tǒng)拍照程序出現(xiàn)圖片太小的問(wèn)題解決辦法的相關(guān)資料,需要的朋友可以參考下2017-07-07
Android之仿美團(tuán)加載數(shù)據(jù)幀動(dòng)畫(huà)
本文主要介紹了Android仿美團(tuán)加載數(shù)據(jù)幀動(dòng)畫(huà)的實(shí)例方法。具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-04-04

