PullScrollView进阶(三)----->图片下拉回弹

activity_main.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:id="@+id/background_img"
        android:layout_width="match_parent"
        android:layout_height="400dp"
        android:layout_marginTop="-100dp"
        android:scaleType="fitXY"
        android:src="@drawable/pic3" />

<com.harvic.pullscrollviewdemo.PullScrollView
       android:id="@+id/pullscrollview"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
            <TableLayout
                android:id="@+id/table_layout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="150dp"/>
    </com.harvic.pullscrollviewdemo.PullScrollView>
   
</FrameLayout>

MainActivity

package com.harvic.pullscrollviewdemo;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.ImageView;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
    private TableLayout mMainLayout;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //加载布局
        setContentView(R.layout.activity_main);
        //背景图片
        ImageView headerView = (ImageView)findViewById(R.id.background_img);
        //自定义的PullScrollView
        PullScrollView pullScrollView = (PullScrollView)findViewById(R.id.pullscrollview);
        //???
        pullScrollView.setmHeaderView(headerView);
        //自定义的PullScrollView里面的元素
        mMainLayout = (TableLayout) findViewById(R.id.table_layout);
        //显示数据
        showTable();
    }


    public void showTable() {
        TableRow.LayoutParams layoutParams = new TableRow.LayoutParams(
                TableRow.LayoutParams.MATCH_PARENT,
                TableRow.LayoutParams.WRAP_CONTENT);
        layoutParams.gravity = Gravity.CENTER;
        layoutParams.leftMargin = 30;
        layoutParams.bottomMargin = 10;
        layoutParams.topMargin = 10;

        for (int i = 0; i < 30; i++) {
            TableRow tableRow = new TableRow(this);
            TextView textView = new TextView(this);
            textView.setText("Test pull down scroll view " + i);
            textView.setTextSize(20);
            textView.setPadding(15, 15, 15, 15);

            tableRow.addView(textView, layoutParams);
            if (i % 2 != 0) {
                tableRow.setBackgroundColor(Color.LTGRAY);
            } else {
                tableRow.setBackgroundColor(Color.WHITE);
            }
            final int n = i;
            tableRow.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(getApplicationContext(), "Click item " + n, Toast.LENGTH_SHORT).show();
                }
            });


            mMainLayout.addView(tableRow);
        }
    }
}

PullScrollView

package com.harvic.pullscrollviewdemo;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.TranslateAnimation;
import android.widget.ScrollView;

public class PullScrollView extends ScrollView {

	// 底部View
	private View mContentView;

	// 是否禁止控件本身的的移动
	boolean mEnableMoving = false;

	/**
	 * 阻尼系数,越小阻力就越大.
	 */
	private static final float SCROLL_RATIO = 0.5f;

	private int mContentTop, mContentBottom;

	private int mHeaderCurTop, mHeaderCurBottom;

	// 底部图片View
	private View mHeaderView;

	// 获取手指按下时候的Y轴坐标
	public static int dip2px(Context context, float dpValue) {
		final float scale = context.getResources().getDisplayMetrics().density;
		return (int) (dpValue * scale + 0.5f);
	}

	/**
	 * 构造方法
	 */
	public PullScrollView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context, attrs);
	}

	public PullScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		init(context, attrs);
	}

	// 用户定义的headview高度
	private int mHeaderHeight = 0;
	private void init(Context context, AttributeSet attrs) {
		mHeaderHeight = dip2px(context, 400);
	}

	/**
	 * 函数解析完毕后,调用的函数
	 */
	@Override
	protected void onFinishInflate() {
		if (getChildCount() > 0) {
			mContentView = getChildAt(0);
		}
		super.onFinishInflate();
	}

	public void setmHeaderView(View view) {
		mHeaderView = view;
	}

	// 初始点击位置
	private Point mTouchPoint = new Point();
	// 头部图片的初始化位置
	private Rect mHeadInitRect = new Rect();
	// ScrollView的contentView的初始化位置
	private Rect mContentInitRect = new Rect();
	// 标识当前view是否移动
	boolean mIsMoving = false;
	// 是否使用layout函数移动布局
	boolean mIsLayout = false;

	@Override
	public boolean onInterceptTouchEvent(MotionEvent event) {
		if (event.getAction() == MotionEvent.ACTION_DOWN) {
			// 保存原始位置
			mTouchPoint.set((int) event.getX(), (int) event.getY());
			// 初始化头部图片矩形区域
			mHeadInitRect.set(mHeaderView.getLeft(), mHeaderView.getTop(),
					mHeaderView.getRight(), mHeaderView.getBottom());
			// 初始化SrollView的孩子View的矩形区域
			mContentInitRect.set(mContentView.getLeft(), mContentView.getTop(),
					mContentView.getRight(), mContentView.getBottom());
			
			
			mIsMoving = false;
			// 如果当前不是从初始化位置开始滚动的话,就不让用户拖拽
			if (getScrollY() == 0) {
				mIsLayout = true;
			}
		} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
			// 如果当前的事件是我们要处理的事件时,比如现在的下拉,这时候,我们就不能让子控件来处理这个事件
			// 这里就需要把它截获,不传给子控件,更不能让子控件消费这个事件
			// 不然子控件的行为就可能与我们的相冲突

			// 移动的距离
			int deltaY = (int) event.getY() - mTouchPoint.y;
			deltaY = deltaY < 0 ? 0 : (deltaY > mHeaderHeight ? mHeaderHeight
					: deltaY);
			if (deltaY > 0 && deltaY >= getScrollY() && getScrollY() == 0) {
				onTouchEvent(event);
				return true;
			}
		}
		return super.onInterceptTouchEvent(event);
	}

	/**
	 * 处理手势事件
	 */
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_MOVE: {
			//
			int deltaY = (int) event.getY() - mTouchPoint.y;
			deltaY = deltaY < 0 ? 0 : (deltaY > mHeaderHeight ? mHeaderHeight
					: deltaY);
			if (deltaY > 0 && deltaY >= getScrollY() && mIsLayout) {
				float headerMoveHeight = deltaY * 0.5f * SCROLL_RATIO;
				mHeaderCurTop = (int) (mHeadInitRect.top + headerMoveHeight);
				mHeaderCurBottom = (int) (mHeadInitRect.bottom + headerMoveHeight);

				float contentMoveHeight = deltaY * SCROLL_RATIO;
				mContentTop = (int) (mContentInitRect.top + contentMoveHeight);
				mContentBottom = (int) (mContentInitRect.bottom + contentMoveHeight);

				if (mContentTop <= mHeaderCurBottom) {
					mHeaderView.layout(mHeadInitRect.left, mHeaderCurTop,
							mHeadInitRect.right, mHeaderCurBottom);
					mContentView.layout(mContentInitRect.left, mContentTop,
							mContentInitRect.right, mContentBottom);
					mIsMoving = true;
					mEnableMoving = true;
				}
			}
		}
			break;
		case MotionEvent.ACTION_UP: {
			// 反弹
			if (mIsMoving) {
				mHeaderView.layout(mHeadInitRect.left, mHeadInitRect.top,
						mHeadInitRect.right, mHeadInitRect.bottom);
				TranslateAnimation headAnim = new TranslateAnimation(0, 0,
						mHeaderCurTop - mHeadInitRect.top, 0);
				headAnim.setDuration(200);
				mHeaderView.startAnimation(headAnim);

				mContentView.layout(mContentInitRect.left,
						mContentInitRect.top, mContentInitRect.right,
						mContentInitRect.bottom);
				TranslateAnimation contentAnim = new TranslateAnimation(0, 0,
						mContentTop - mContentInitRect.top, 0);
				contentAnim.setDuration(200);
				mContentView.startAnimation(contentAnim);
				mIsMoving = false;
			}
			mEnableMoving = false;
			mIsLayout = false;
		}
			break;
		}
		// 禁止控件本身的滑动.
		// 这句厉害,如果mEnableMoving返回TRUE,那么就不会执行super.onTouchEvent(event)
		// 只有返回FALSE的时候,才会执行super.onTouchEvent(event)
		// 禁止控件本身的滑动,就会让它,本来应有的滑动就不会滑动了,比如向上滚动
		return mEnableMoving || super.onTouchEvent(event);
	}

}


你可能感兴趣的:(PullScrollView进阶(三)----->图片下拉回弹)