本文主要是介绍Android滑动回弹效果,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
原理:
addHeaderView里做的事:
1.测量出header的宽高,调用了measureView方法
2.设置LayoutParams,宽:MATCH_PARENT,高:10
3.设置topMargin的值为负的header的高度,即将header隐藏在屏幕最上方
onInterceptTouchEvent:
如果滑动距离为零,让onInterceptTouchEvent处理。屏幕没有滑动效果。
onTouchEvent:
如果滑动距离大于零,让onTouchEvent处理。在滑动过程中不断的计算header的topMargin,让屏幕有滑动效果。
代码:
/** * android回弹效果 by haidaye */ public class HaidayeView extends LinearLayout {private int mLastMotionY; /** * 头部view */ private View mHeaderView; private LayoutInflater mInflater; private ScrollView mScrollView; /** * 头部view的高 */ private int mHeaderViewHeight; public HaidayeView(Context context, AttributeSet attrs) {super(context, attrs); init(); }public HaidayeView(Context context) {super(context); init(); }private void init() {// Load all of the animations we need in code rather than through XML mInflater = LayoutInflater.from(getContext()); // header view 在此添加,保证是第一个添加到linearlayout的最上端 addHeaderView(); }private void addHeaderView() {// header view mHeaderView = mInflater.inflate(R.layout.header, this, false); measureView(mHeaderView); mHeaderViewHeight = mHeaderView.getMeasuredHeight(); LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, mHeaderViewHeight); // 设置topMargin的值为负的header View高度,即将其隐藏在最上方 params.topMargin = -(mHeaderViewHeight); addView(mHeaderView, params); }@Overrideprotected void onFinishInflate() {super.onFinishInflate(); initContentAdapterView(); }private void initContentAdapterView() {mScrollView = (ScrollView) getChildAt(1); }private void measureView(View child) {ViewGroup.LayoutParams p = child.getLayoutParams(); if (p == null) {p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); }int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width); int lpHeight = p.height; int childHeightSpec; if (lpHeight > 0) {childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY); } else {childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); }child.measure(childWidthSpec, childHeightSpec); }@Overridepublic boolean onInterceptTouchEvent(MotionEvent e) {int y = (int) e.getRawY(); switch (e.getAction()) {case MotionEvent.ACTION_DOWN:// 首先拦截down事件,记录y坐标 mLastMotionY = y; break; case MotionEvent.ACTION_MOVE:// deltaY > 0 是向下运动,< 0是向上运动 int deltaY = y - mLastMotionY; if (isRefreshViewScroll(deltaY)) {return true; }mLastMotionY = y; break; case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL:break; }return false; }/* * 如果在onInterceptTouchEvent()方法中没有拦截(即onInterceptTouchEvent()方法中 return * false)则由PullToRefreshView 的子View来处理;否则由下面的方法来处理(即由HaidayeView自己来处理) */ @Overridepublic boolean onTouchEvent(MotionEvent event) {int y = (int) event.getRawY(); switch (event.getAction()) {case MotionEvent.ACTION_DOWN:// onInterceptTouchEvent已经记录 // mLastMotionY = y; break; case MotionEvent.ACTION_MOVE:int deltaY = y - mLastMotionY; headerPrepareToRefresh(deltaY); mLastMotionY = y; break; case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL:int topMargin = getHeaderTopMargin(); setHeaderTopMargin(-mHeaderViewHeight); break; case MotionEvent.ACTION_POINTER_DOWN://设置多点触控 this.mLastMotionY = y; break; }return super.onTouchEvent(event); }/** * 是否应该到了父View,即PullToRefreshView滑动 * * @param deltaY , deltaY > 0 是向下运动,< 0是向上运动 * @return */ private boolean isRefreshViewScroll(int deltaY) {// 对于ScrollView if (mScrollView != null) {// 子scroll view滑动到最顶端 View child = mScrollView.getChildAt(0); if (deltaY > 0 && mScrollView.getScrollY() == 0) {return true; } else if (deltaY < 0 && child.getMeasuredHeight() <= getHeight()+ mScrollView.getScrollY()) {return true; }}return false; }/** * header 准备刷新,手指移动过程,还没有释放 * * @param deltaY ,手指滑动的距离 */ private void headerPrepareToRefresh(int deltaY) {int newTopMargin = changingHeaderViewTopMargin(deltaY); }private int changingHeaderViewTopMargin(int deltaY) {LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams(); float newTopMargin = params.topMargin + deltaY * 0.3f; params.topMargin = (int) newTopMargin; mHeaderView.setLayoutParams(params); invalidate(); return params.topMargin; }/** * 设置header view 的topMargin的值 */ private void setHeaderTopMargin(int topMargin) {LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams(); params.topMargin = topMargin; mHeaderView.setLayoutParams(params); invalidate(); }private int getHeaderTopMargin() {LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams(); return params.topMargin; } }
致敬海大爷
这篇关于Android滑动回弹效果的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!