Android Scroll實(shí)現(xiàn)彈性滑動(dòng)_列表下拉彈性滑動(dòng)的示例代碼
我這一次講使用scroll實(shí)現(xiàn)彈性滑動(dòng),我不會(huì)只有一個(gè)例子就說(shuō)完,因?yàn)閷?xiě)文章的時(shí)候我也在學(xué)習(xí),我分幾次講完吧。
首先上一段代碼,
private void smoothScrollByScroller(int dy){
mScroller.startScroll(0,dy,0,dy*-1,1000);
invalidate();
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
}
這段代碼是實(shí)現(xiàn)彈性滑動(dòng)的核心,第一個(gè)函數(shù)指的是緩慢滑動(dòng)的意思,但是卻沒(méi)有這個(gè)滑動(dòng)的實(shí)際功能。
startScroll這函數(shù)的五個(gè)參數(shù)指的是起點(diǎn)x坐標(biāo),起點(diǎn)y坐標(biāo),x位移量,y位移量,這段滑動(dòng)的時(shí)間。這個(gè)函數(shù)的內(nèi)部是不斷計(jì)算在滑動(dòng)時(shí)間里x和y坐標(biāo)應(yīng)該是什么值,然后因?yàn)閕nvalidate會(huì)調(diào)用computeScroll,這個(gè)computeScrollOffset函數(shù)是判斷當(dāng)前滑動(dòng)是否結(jié)束,如果沒(méi)有結(jié)束通過(guò)getCurrX和getCurry獲得startScroll函數(shù)計(jì)算的值,在使用scrollTo滑動(dòng)相應(yīng)的位置,因?yàn)閟tartScroll會(huì)運(yùn)算很多次,也就是將滑動(dòng)時(shí)間分成很多段,相應(yīng)的坐標(biāo)也都算出來(lái),跟著給scrollTo去實(shí)現(xiàn)滑動(dòng)。
這很像是ValueAmition,將時(shí)間分成很多段,然后計(jì)算相應(yīng)的值,同時(shí)分很多次去實(shí)現(xiàn)。
我貼一個(gè)類(lèi)似QQ消息列表的常見(jiàn)的彈性滑動(dòng),這里下拉是沒(méi)有刷新的,
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
public final class PullView extends ViewGroup {
private int mLastY;
private Context mContext;
private Scroller mScroller;
//子View的個(gè)數(shù)
private int mChildCount;
public PullView(Context context){
this(context,null);
}
public PullView(Context context, AttributeSet attributeSet){
super(context,attributeSet);
mContext=context;
initView();
}
private void initView(){
mScroller=new Scroller(mContext);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int y=(int)event.getY();
switch (event.getAction()){
//手指按下時(shí),初始化按下位置的X,Y位置值
case MotionEvent.ACTION_DOWN:
mLastY=y;
break;
//計(jì)算滑動(dòng)的偏移量,產(chǎn)生滑動(dòng)效果
case MotionEvent.ACTION_MOVE:
//手指向下滑動(dòng)delayY>0,向上滑動(dòng)delayY<0
int delayY=y-mLastY;
delayY=delayY*-1;
scrollBy(0,delayY);
break;
case MotionEvent.ACTION_UP:
/**
* scrollY是指:View的上邊緣和View內(nèi)容的上邊緣(其實(shí)就是第一個(gè)ChildView的上邊緣)的距離
* scrollY=上邊緣-View內(nèi)容上邊緣,scrollTo/By方法滑動(dòng)的知識(shí)View的內(nèi)容
* 往下滑動(dòng)scrollY是負(fù)值
*/
int scrollY=getScrollY();
smoothScrollByScroller(scrollY);
break;
}
mLastY=y;
return true;
}
/**
* 執(zhí)行滑動(dòng)效果
* 使用scroller實(shí)現(xiàn)
* @param dy
*/
private void smoothScrollByScroller(int dy){
mScroller.startScroll(0,dy,0,dy*-1,1000);
invalidate();
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
}
/**
* 重新計(jì)算子View的高度和寬度
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int measuredWidth;
int measureHeight;
mChildCount = getChildCount();
//測(cè)量子View
measureChildren(widthMeasureSpec, heightMeasureSpec);
int widthSpaceSize = MeasureSpec.getSize(widthMeasureSpec);
int widthSpaceMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSpaceSize = MeasureSpec.getSize(heightMeasureSpec);
int heightSpaceMode = MeasureSpec.getMode(heightMeasureSpec);
//獲取橫向的padding值
int paddingLeft=getPaddingLeft();
int paddingRight=getPaddingRight();
final View childView = getChildAt(0);
/**
* 如果子View的數(shù)量是0,就讀取LayoutParams中數(shù)據(jù)
* 否則就對(duì)子View進(jìn)行測(cè)量
* 此處主要是針對(duì)wrap_content這種模式進(jìn)行處理,因?yàn)槟J(rèn)情況下
* wrap_content等于match_parent
*/
if (mChildCount == 0) {
ViewGroup.LayoutParams layoutParams=getLayoutParams();
if(layoutParams!=null){
setMeasuredDimension(layoutParams.width,layoutParams.height);
}else {
setMeasuredDimension(0, 0);
}
} else if (heightSpaceMode == MeasureSpec.AT_MOST && widthSpaceMode == MeasureSpec.AT_MOST) {
measuredWidth = childView.getMeasuredWidth() * mChildCount;
measureHeight = getChildMaxHeight();
//將兩側(cè)的padding值加上去
measuredWidth=paddingLeft+measuredWidth+paddingRight;
setMeasuredDimension(measuredWidth, measureHeight);
} else if (heightSpaceMode == MeasureSpec.AT_MOST) {
measureHeight = getChildMaxHeight();
setMeasuredDimension(widthSpaceSize, measureHeight);
} else if (widthSpaceMode == MeasureSpec.AT_MOST) {
measuredWidth = childView.getMeasuredWidth() * mChildCount;
measuredWidth=paddingLeft+measuredWidth+paddingRight;
setMeasuredDimension(measuredWidth, heightSpaceSize);
}
}
/**
* 獲取子View中最大高度
* @return
*/
private int getChildMaxHeight(){
int maxHeight=0;
for (int i = 0; i < mChildCount; i++) {
View childView = getChildAt(i);
if (childView.getVisibility() != View.GONE) {
int height = childView.getMeasuredHeight();
if(height>maxHeight){
maxHeight=height;
}
}
}
return maxHeight;
}
/**
* 設(shè)置子View的布局
* @param changed
* @param l
* @param t
* @param r
* @param b
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int childLeft = 0;
for (int i = 0; i < mChildCount; i++) {
View childView = getChildAt(i);
if (childView.getVisibility() != View.GONE) {
int childWidth = childView.getMeasuredWidth();
childView.layout(childLeft, 0, childLeft + childWidth, childView.getMeasuredHeight());
childLeft += childWidth;
}
}
}
}
<android.com.listfragment.PullView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="1500dp"
android:background="#806363"></LinearLayout>
</android.com.listfragment.PullView>
這里的ViewGroup的繪畫(huà)和測(cè)量我就不多說(shuō),我就說(shuō)一下它獲取函數(shù),計(jì)算坐標(biāo)的一些事。
它在手指按下時(shí)記錄y坐標(biāo),在手指移動(dòng)時(shí),跟著移動(dòng)子View,在手指抬起時(shí),使用彈性滑動(dòng)的函數(shù)smoothScrollByScroller。
大家會(huì)發(fā)現(xiàn)為什么一些計(jì)算出的坐標(biāo)要加負(fù)號(hào),因?yàn)樵谖覀內(nèi)搜劾?,我們下拉y坐標(biāo)的位移量是正的,但是在系統(tǒng)認(rèn)為這個(gè)值是負(fù)的,原因我太菜不知道,知道的求大神評(píng)論留言告訴。
下一次寫(xiě)一個(gè)隨手指彈性滑動(dòng)的例子。
以上這篇Android Scroll實(shí)現(xiàn)彈性滑動(dòng)_列表下拉彈性滑動(dòng)的示例代碼就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- android開(kāi)發(fā)通過(guò)Scroller實(shí)現(xiàn)過(guò)渡滑動(dòng)效果操作示例
- Android使用Scroller實(shí)現(xiàn)彈性滑動(dòng)效果
- Android自定義View彈性滑動(dòng)Scroller詳解
- Android用Scroller實(shí)現(xiàn)一個(gè)可向上滑動(dòng)的底部導(dǎo)航欄
- 詳解Android應(yīng)用開(kāi)發(fā)中Scroller類(lèi)的屏幕滑動(dòng)功能運(yùn)用
- Android自定義ViewGroup實(shí)現(xiàn)彈性滑動(dòng)效果
- android自定義ViewPager水平滑動(dòng)彈性效果
- Android使用Handler實(shí)現(xiàn)View彈性滑動(dòng)
- Android?Scroller實(shí)現(xiàn)彈性滑動(dòng)效果
相關(guān)文章
Android開(kāi)發(fā)入門(mén)之Appwidget用法分析
這篇文章主要介紹了Android開(kāi)發(fā)入門(mén)之Appwidget用法,較為詳細(xì)的分析了App Widget的概念、功能、創(chuàng)建、使用方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2016-07-07
Android入門(mén)計(jì)算器編寫(xiě)代碼
這篇文章主要為大家詳細(xì)介紹了Android入門(mén)計(jì)算器編寫(xiě)代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-08-08
Android ViewFlipper用法實(shí)例分析
這篇文章主要介紹了Android ViewFlipper用法,結(jié)合實(shí)例形式分析了ViewFlipper圖片操作的相關(guān)技巧,需要的朋友可以參考下2016-01-01
Android字符串轉(zhuǎn)Ascii碼實(shí)例代碼
這篇文章主要介紹了Android字符串轉(zhuǎn)Ascii碼的方法,大家參考使用2013-11-11
從零開(kāi)始使用gradle配置即可執(zhí)行的Hook庫(kù)詳解
這篇文章主要為大家介紹了從零開(kāi)始使用gradle配置即可執(zhí)行的Hook庫(kù)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
Android開(kāi)發(fā)系列二之窗口Activity的生命周期
這篇文章主要介紹了Android學(xué)習(xí)系列二之窗口Activity的生命周期的相關(guān)資料,需要的朋友可以參考下2016-05-05
Android解析JSON格式數(shù)據(jù)的兩種方式(JSONObject和Gson)
json數(shù)據(jù)的解析相對(duì)而言,還是比較容易的,實(shí)現(xiàn)的代碼也十分簡(jiǎn)單,下面這篇文章主要給大家介紹了關(guān)于Android解析JSON格式數(shù)據(jù)的兩種方式,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07
Kotlin與Java相互調(diào)用的完整實(shí)例
Kotlin的設(shè)計(jì)過(guò)程中就考慮到了與Java的互操作性,在Kotlin中可以直接調(diào)用既有的Java代碼,反過(guò)來(lái)在Java中也可以很流暢地使用Kotlin代碼,這篇文章主要給大家介紹了關(guān)于Kotlin與Java相互調(diào)用的相關(guān)資料,需要的朋友可以參考下2021-12-12
Android自定義View實(shí)現(xiàn)shape圖形繪制
這篇文章主要為大家詳細(xì)介紹了Android使用自定義View實(shí)現(xiàn)shape圖形繪制,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01

