Android HorizontalScrollView回彈效果
阿新 • • 發佈:2019-01-22
轉載記錄備份查閱
import android.annotation.SuppressLint; import android.os.Build; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewTreeObserver; import android.widget.HorizontalScrollView; import android.widget.ScrollView; /** * Created by Sugar on 2017/12/7/0007. */ public class UITools { /**HorizontalScrollView新增阻尼效果 * ScrollView效果不太好 * 利用父元素的Padding給ScrollView新增彈性 * @param scrollView * @param padding */ public static void elasticPadding(final ScrollView scrollView, final int padding){ View child = scrollView.getChildAt(0); //記錄以前的padding final int oldpt = child.getPaddingTop(); final int oldpb = child.getPaddingBottom(); //設定新的padding child.setPadding(child.getPaddingLeft(), padding+oldpt, child.getPaddingRight(), padding+oldpb); //新增檢視佈局完成事件監聽 scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { private boolean inTouch = false; //手指是否按下狀態 @SuppressLint("NewApi") private void disableOverScroll(){ scrollView.setOverScrollMode(ScrollView.OVER_SCROLL_NEVER); } /** 滾動到頂部 */ private void scrollToTop(){ scrollView.smoothScrollTo(scrollView.getScrollX(), padding-oldpt); } /** 滾動到底部 */ private void scrollToBottom(){ scrollView.smoothScrollTo(scrollView.getScrollX(), scrollView.getChildAt(0).getBottom()-scrollView.getMeasuredHeight()-padding+oldpb); } /** 檢測scrollView結束以後,復原位置 */ private final Runnable checkStopped = new Runnable() { @Override public void run() { int y = scrollView.getScrollY(); int bottom = scrollView.getChildAt(0).getBottom()-y-scrollView.getMeasuredHeight(); if(y <= padding && !inTouch){ scrollToTop(); }else if(bottom<=padding && !inTouch){ scrollToBottom(); } } }; @SuppressWarnings("deprecation") @Override public void onGlobalLayout() { //移除監聽器 scrollView.getViewTreeObserver().removeGlobalOnLayoutListener(this); //設定最小高度 //scrollView.getChildAt(0).setMinimumHeight(scrollView.getMeasuredHeight()); //取消overScroll效果 if(Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD){ disableOverScroll(); } scrollView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if(event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_POINTER_DOWN){ inTouch = true; }else if(event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL){ inTouch = false; //手指彈起以後檢測一次是否需要復原位置 scrollView.post(checkStopped); } return false; } }); scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() { @Override public void onScrollChanged() { if(!inTouch && scrollView!=null && scrollView.getHandler()!=null){//如果持續滾動,移除checkStopped,停止滾動以後只執行一次檢測任務 scrollView.getHandler().removeCallbacks(checkStopped); scrollView.postDelayed(checkStopped, 100); } } }); //第一次載入檢視,復原位置 scrollView.postDelayed(checkStopped, 300); } }); } /** * 利用父元素的Padding給HorizontalScrollView新增彈性 * @param scrollView * @param padding */ public static void elasticPadding(final HorizontalScrollView scrollView, final int padding){ Log.i("", "elasticPadding>>>>!!"); View child = scrollView.getChildAt(0); //記錄以前的padding final int oldpt = child.getPaddingTop(); final int oldpb = child.getPaddingBottom(); //設定新的padding child.setPadding(padding+oldpt, child.getPaddingTop(), padding+oldpb, child.getPaddingBottom()); //新增檢視佈局完成事件監聽 scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { private boolean inTouch = false; //手指是否按下狀態 @SuppressLint("NewApi") private void disableOverScroll(){ scrollView.setOverScrollMode(ScrollView.OVER_SCROLL_NEVER); } /** 滾動到左邊 */ private void scrollToLeft(){ scrollView.smoothScrollTo(padding-oldpt, scrollView.getScrollY()); } /** 滾動到底部 */ private void scrollToRight(){ scrollView.smoothScrollTo(scrollView.getChildAt(0).getRight()-scrollView.getMeasuredWidth()-padding+oldpb, scrollView.getScrollY()); } /** 檢測scrollView結束以後,復原位置 */ private final Runnable checkStopped = new Runnable() { @Override public void run() { int x = scrollView.getScrollX(); int bottom = scrollView.getChildAt(0).getRight()-x-scrollView.getMeasuredWidth(); if(x <= padding && !inTouch){ scrollToLeft(); }else if(bottom<=padding && !inTouch){ scrollToRight(); } } }; @SuppressWarnings("deprecation") @Override public void onGlobalLayout() { //移除監聽器 scrollView.getViewTreeObserver().removeGlobalOnLayoutListener(this); //取消overScroll效果 if(Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD){ disableOverScroll(); } scrollView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if(event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_POINTER_DOWN){ inTouch = true; }else if(event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL){ inTouch = false; //手指彈起以後檢測一次是否需要復原位置 scrollView.post(checkStopped); } return false; } }); scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() { @Override public void onScrollChanged() { //如果持續滾動,移除checkStopped,停止滾動以後只執行一次檢測任務 if(!inTouch && scrollView!=null && scrollView.getHandler()!=null){ scrollView.getHandler().removeCallbacks(checkStopped); scrollView.postDelayed(checkStopped, 100); } } }); //第一次載入檢視,復原位置 scrollView.postDelayed(checkStopped, 300); } }); } }
呼叫方式:
UITools.elasticPadding((HorizontalScrollView) findViewById(R.id.hs), 500);